Setting an immutable field for later use - scala

I'm in a situation where I need to set a certain field in a singleton object so it can be used later.
def register(importantField: String): Unit = {
Factory.setField(importantField)
}
where Factory is:
object Factory {
var field: Option[String] = None
def setField(importantField: String): Unit = {
field = Option(importantField)
}
def functionThatWillBeCalledLater: Unit = {
// do something with member "field"
}
}
but I really want to avoid using var. Is there some kind of idiomatic way to do this?

Don't do this. Global factories, besides being racy and breaking referential transparency, are also a nightmare for unit testing. You should really think about designing your code in a way, where you can keep all the "important fields" where you need them.
The trick is that instead of something like
class Foo {
def doFoo() = Factory.bar
}
Factory.register(param)
new Foo().doFoo()
You would have to write
class Foo {
def doFoo(factory: Factory) = factory.bar
}
new Foo().doFoo(new Factory(param)
Or maybe
class Foo(factory: Factory) {
def doFoo() = factory.bar
}
new Foo(new Factory(param)).doFoo
It may seem a bit tedious compared, to just throwing all the stuff into a global state object, and accessing it from everywhere ... but that's only as long as all of the uses of that function everywhere always use the same value of the parameter (in which case, it is better off just being a constant in the first place) or (perhaps, more importantly) until you start thinking about writing unit tests to test places that use your Factory. You cannot mock an object ... so, what will you do?

Singleton objects have to be thread safe - since the object is static, there's no guarantee that only one thread will access it, so your call not to use a var is totally reasonable. All vals are final and guaranteed to be thread safe, but we can't say the same about vars (and, well, if we're talking about idiomatic, mutable state is generally frowned upon).
You could implement your own getter and setter (using proper synchronization) for a private var, or use a scala.concurrent.Promise for this purpose - a Promise can only be completed once, and is guaranteed to be thread safe.
import scala.concurrent.Promise
object Factory {
private val _field: Promise[String] = Promise()
// the notation below allows you to set it via `Factory.field = "a"`
def field_=(value: String): Boolean = _field.trySuccess(value)
def field: Option[String] = _field.future.value.flatMap(_.toOption)
}
That said, the most idiomatic Scala way to approach factories with variable baseline conditions would be to create one with all the variables set to the values you need. An object is essentially just a val, so instead of an actual singleton object you could instantiate the Factory with all the parameters you need once they're available - and then just use that everywhere.

Related

How to enforce encapsulation of immutable class in Scala?

I am trying to write immutable code in Dart. Dart wasn't really built with immutability in mind, that's why I need to write a lot of boilerplate in order to achieve immutability. Because of this, I got interested in how a language, like Scala, which was built around the concept of immutability, would solve this.
I am currently using the following class in Dart:
class Profile{
List<String> _inSyncBikeIds = []; // private field
String profileName; // public field
Profile(this.profileName); // You should not be able to pass a value to _inSyncBikeIds
void synchronize(String bikeId){
_inSyncBikeIds.add(bikeId);
}
bool isInSync(String bikeId){
return _inSyncBikeIds.contains(bikeId);
}
void reset(){
_inSyncBikeIds = [];
}
}
The same class in immutable:
class Profile{
final List<String> _inSyncBikeIds = []; // private final field
final String profileName; // public final field
factory Profile(String profileName) => Profile._(profileName); // You should not be able to pass a value to _inSyncBikeIds
Profile._(this._inSyncBikeIds, this.profileName); // private contructor
Profile synchronize(String bikeId){
return _copyWith(inSyncBikeIds: _inSyncBikeIds.add(bikeId);
}
bool isInSync(String bikeId) {
return _inSyncBikeIds.contains(bikeId);
}
Profile reset(){
return _copyWith(inSyncBikeIds: []);
}
Profile copyWith({
String profileName,
}) {
return _copyWith(profileName: profileName)
}
Profile _copyWith({
String profileName,
List<Id> inSyncBikeIds,
}) {
return Profile._(
profileName: profileName ?? this.profileName,
inSyncBikeIds: inSyncBikeIds ?? _inSyncBikeIds);
}
}
What I understand from Scala so far, is that for every class a copy method is automatically created. In order to be able to change a field using the copy method, it needs to be part of the constructor.
I want the field _inSyncBikeIds to be final (val in Scala). In order to change the value of the field _inSyncBikeIds I need to create a copy of the object. But in order to use the copy method, to change the field, it needs to be part of the constructor of the class, like class Profile(private val _inSyncBikeIds, val profileName). But this would then break encapsulation, because everyone can create an object and initialize _inSyncBikeIds. In my case, _inSyncBikeIds should always be an empty list after initialization.
Three questions:
How do I solve this in Scala?
When I use the copy method inside the class, can I change private fields using the copy method?
Does the copy method in Scala copy private fields as well (even when they are not part of the constructor, you can't mutate that private field then of course)?
Scala comes from a tradition that tends to view immutable data as a license for free sharing (thus public by default etc.). The interpretation of encapsulation is more that code outside an object not be able to directly mutate data: immutable data regardless of visibility satisfies this.
It's possible to suppress the auto-generated copy method for a case class by making it abstract (nearly always sealed abstract with a private constructor). This is commonly used to make the apply/copy methods return a different type (e.g. something which encodes a validation failure as a value without throwing an exception (as require would)), but it can be used for your purpose
sealed abstract case class Profile private(private val _inSyncBikeIds: List[String], profileName: String) {
def addBike(bikeId: String): Profile = Profile.unsafeApply(bikeId :: _inSyncBikeIds, profileName)
// Might consider using a Set...
def isInSync(bikeId: String): Boolean = _inSyncBikeIds.contains(bikeId)
def copy(profileName: String = profileName): Profile = Profile.unsafeApply(_inSyncBikeIds, profileName)
}
object Profile {
def apply(profileName: String): Profile = unsafeApply(Nil, profileName)
private[Profile] def apply(_inSyncBikeIds: List[String], profileName: String): Profile = new Profile(_inSyncBikeIds, profileName) {}
}
unsafeApply is more common for the validation as value use-case, but the main purpose it serves is to limit the concrete implementations of the abstract Profile to only that anonymous implementation; this monomorphism has beneficial implications for runtime performance.
Notes: case classes are Serializable, so there is a Java serialization hole: in application code this is solvable by never ever using Java serialization because it's broken, but it makes up for being broken by being completely evil (i.e. if you have a Scala application that uses Java serialization, you should probably re-evaluate the choices that led you there).
There's no way to encode sealedness in JVM bytecode AFAIK (Scala uses an annotation, IIRC, so Scala will limit extension of Profile to that compilation unit but, e.g, Kotlin won't), nor is the private[Profile] access control encoded in a way that JVM languages which aren't Scala will enforce (the unsafeApply method is actually public in the bytecode). Again, in application code, the obvious question is "why are you trying to use this from Java/Kotlin/Clojure/...?". In a library, you might have to do something hacky like throw an exception, catch it and inspect the top frames of the stack, throwing again if it's not hunky-dory.
I have no idea if it is possible in dart, but in scala this would be done with a private constructor:
class Profile private (val _foo: Seq[String], val bar: String) {
def this(bar: String) = this(Nil, bar)
}
This lets you define
private copy(foo: Seq[String], bar: String) = new Profile(foo, bar)
This is fine as long the class is final. If you subclass it, badness ensues: Child.copy() returns an instance of Parent, unless you override copy in every subclass, but there is no good way to enforce it (scala 3 admittedly has some improvement over this).
The generated copy method you mentioned only works for case classes. But subclassing a case class would lead to some even more interesting results.
This is really rarely useful though. Looking at your code for instance, if I read the ask correctly, you want the user to not be able to do
Profile(List("foo"), "bar") but Profile("bar").synchronize("foo") is still possible even though it produces exactly the same result. This hardly seems useful.

Delayed variable initialization

Let's say I have a variable which I cannot initialize immediately, because I do not know its value (so lazy val won't work for me). I also cannot control the moment the object creation because it is handled by a framework (e.g. Activity in an Android app), so I cannot delay creation of whole object. I do NOT want to use var for this, as it brings the risk of incomplete initialization and invalid states.
So far I've been using approach like:
class MyClass extends InterfaceWithDelayedInitialization {
private val delayedValueP = Promise[Type]()
private val delayedValueF = delayedValueP.future
def onCreate(value: Type): Unit = {
delayedValueP.successful(value)
}
def someOtherMethod(): Unit = {
delayedValueF foreach { value =>
// do something with value
}
}
}
but I cannot help but feel that this approach is kind of smelly (not as smelly as using mutability and vars though).
Is there some standard solution for a problems like this one?

scala: Should private utility methods live in companion objects?

The question is self explanatory, but please allow me to provide an example:
I have the following:
class Foo {
def doAndPrint {
val result = doSomething()
val msg = message(result)
println(msg)
}
private def message(result: Result): String = {
"message formatted with %s".format(result)
}
}
In this context, the question is: Should def message(result: Result) live in object Foo?
The argument in favor is making explicit that def message(result: Result) does not depends on any state within class Foo.
The argument against is that the motivation of companion objects was to provide a place to put java public static methods.
The answer to this false dichotomy is neither. It should be a local method to doAndPrint.
class Foo {
def doAndPrint {
val result = doSomething()
def message(result: Result): String = s"message formatted with $result"
val msg = message(result)
println(msg)
}
}
In fact,
class Foo {
def doAndPrint {
val result = doSomething()
def message = s"message formatted with $result"
println(message)
}
}
Notice that it really depends on local state.
Edit: OK, as a nod to "self-explanatory," I would add, use the smallest scope that makes sense, and the example points out an asymmetry in the private relations between companions. Which begs for many puns which I haven't time to supply.
Answering more directly, from my observations, the companion module does not normally serve as a repository for FooUtil-style functions, though it does serve as a repository for implicit conversions, which have an arguably similar flavor, albeit public. Consider what winds up in the objects of collection types.
Consider a separation of concerns:
class Foo(f: String => Unit) {
def doSomethingAndDoSomethingWithIt {
val result = doSomething()
def message = s"message formatted with $result"
f(message)
}
}
You should put the methods where they belong. If you need to break things up for testing purposes, readability or even maintainability then you need to break them up. Even though Scala is influenced by FP concepts, FP patterns, and an FP mindset, it is still also an OO language.
Private helper methods are just that, helper methods to make your code easier to work with. If your class needs them, then there is no reason to spread out that logic in another class... just 'cause. Put them in the same place (and add in some means to access those methods for unit testing purposes like package visibility.)

Force initialization of Scala singleton object

I'm working on an automatic mapping framework built on top of Dozer. I won't go into specifics as it's not relevant to the question but in general it's supposed to allow easy transformation from class A to class B. I'd like to register the projections from a class's companion object.
Below is a (simplified) example of how I want this to work, and a Specs test that assures that the projection is being registered properly.
Unfortunately, this doesn't work. From what I can gather, this is because nothing initializes the A companion object. And indeed, if I call any method on the A object (like the commented-out hashCode call, the projection is being registered correctly.
My question is - how can I cause the A object to be initialized automatically, as soon as the JVM starts? I don't mind extending a Trait or something, if necessary.
Thanks.
class A {
var data: String = _
}
class B {
var data: String = _
}
object A {
projekt[A].to[B]
}
"dozer projektor" should {
"transform a simple bean" in {
// A.hashCode
val a = new A
a.data = "text"
val b = a.-->[B]
b.data must_== a.data
}
}
Short answer: You can't. Scala objects are lazy, and are not initialized until first reference. You could reference the object, but then you need a way of ensuring the executing code gets executed, reducing the problem back to the original problem.
In ended up doing this:
trait ProjektionAware with DelayedInit
{
private val initCode = new ListBuffer[() => Unit]
override def delayedInit(body: => Unit)
{
initCode += (() => body)
}
def registerProjektions()
{
for (proc <- initCode) proc()
}
}
object A extends ProjektionAware {
projekt[A].to[B]
}
Now I can use a classpath scanning library to initialize all instances of ProjektionAware on application bootstrap. Not ideal, but works for me.
You can force the instantiation of A to involve the companion object by using an apply() method or some other sort of factory method defined in the object instead of directly using the new A() constructor.
This does not cause the object to be initialized when the JVM starts, which I think as noted in another answer can't generally be done.
As Dave Griffith and Don Roby already noted, it cannot be done at JVM startup in general. However maybe this initialization could wait until first use of your framework?
If so, and if you don't mind resorting to fragile reflection tricks, in your --> method you could obtain reference to the companion object and get it initialize itself.
You can start at Getting object instance by string name in scala.
We could use this sort of a way to ensure that companion object gets initialized first and then the class gets instantiated.
object B {
val i = 0
def apply(): B = new B()
}
class B {
// some method that uses i from Object B
def show = println(B.i)
}
// b first references Object B which calls apply()
// then class B is instantiated
val b = B()

How do I declare a constructor for an 'object' class type in Scala? I.e., a one time operation for the singleton

I know that objects are treated pretty much like singletons in scala. However, I have been unable to find an elegant way to specify default behavior on initial instantiation. I can accomplish this by just putting code into the body of the object declaration but this seems overly hacky. Using an apply doesn't really work because it can be called multiple times and doesn't really make sense for this use case.
Any ideas on how to do this?
Classes and objects both run the code in their body upon instantiation, by design. Why is this "hacky"? It's how the language is supposed to work. If you like extra braces, you can always use them (and they'll keep local variables from being preserved and world-viewable).
object Initialized {
// Initalization block
{
val someStrings = List("A","Be","Sea")
someStrings.filter(_.contains('e')).foreach(s => println("Contains e: " + s))
}
def doSomething { println("I was initialized before you saw this.") }
}
scala> Initialized.doSomething
Contains e: Be
Contains e: Sea
I was initialized before you saw this.
scala> Initialized.someStrings
<console>:9: error: value someStrings is not a member of object Initialized
Initialized.someStrings
Rex has it right, I just wanted to point out a pattern I use a lot, that saves you from having to use vars, while avoiding namespace pollution by intermediate values.
object Foo {
val somethingFooNeeds = {
val intermediate = expensiveCalculation
val something = transform(intermediate)
something
}
}
If it makes you feel better, you can create some class with protected constructor and object will create singleton of this class:
sealed class MyClass protected (val a: String, b: Int) {
def doStuff = a + b
}
object MyObject extends MyClass("Hello", b = 1)
Also notice, that sealed stops other classes and objects to extend MyClass and protected will not allow creation of other MyClass instances.
But I personally don't see any problems with some code in the body of the object. You can also create some method like init and just call it:
object MyObject {
init()
def init() {
...
}
}
The body of object and class declarations IS the default constructor and any code placed in there will be executed upon first reference, so that is exactly the way to do it.