Initializing a val lately - scala

Is it possible to do that in Scala using only val:
class MyClass {
private val myVal1: MyClass2 //.....????? what should be here?
def myMethod1(param1: Int) = {
myVal1 = new MyClass2(param1)
//....
// some code....
}
}
The idea is that I can't initialize myVal1 immediately since the argument for its constructor is unknown yet and I have to do that in myMethod1. myVal1 should be visible withing a class and should be immutable.
No mutable state allowed.
So is it possible?

No, it isn't possible to do in the way you want. Consider, what would be the result of
val mc = new MyClass
mc.method1(0)
mc.method1(1)
? An exception thrown for setting myVal1 twice? Or should it keep the first value?

This is not possible, but there are some ways (in addition to using param1 as a constructor parameter)
Change the var into an Option; the setter myMethod1 returns a new instance of the same class with the Option set to the value.
Create a separate mutable Builder class with a var, and turn it into an immutable one later, when all data has been collected
If you are dealing with forward or cyclic references, consider using call-by-name and lazy vals (example 1, example 2)
Update: Example for 1:
class MyClass(val myVal1: Option[Int]) {
def myMethod1(param1: Int): MyClass = {
new MyClass(Some(param1))
}
}
object MyClass {
def apply() = new MyClass(None)
def apply(i: Int) = new MyClass(Some(i))
}
This pattern is used by immutable.Queue for example.
Update: Example for 3 (cyclic reference):
// ref ... call by name
class MyClass(val id: Int, ref: => MyClass) {
lazy val myVal1 = ref
override def toString: String = s"$id -> ${myVal1.id}"
}
to be used like this:
val a: MyClass = new MyClass(1, b)
val b: MyClass = new MyClass(2, a)
println(a)
println(b)
Update: Example for 3 (forward reference):
class MyClass2(val id: Int)
// ref ... call by name
class MyClass(val id: Int, ref: => MyClass2) {
lazy val myVal1 = ref
override def toString: String = s"$id -> ${myVal1.id}"
}
to be used with
val a = new MyClass(1, x)
println(a.id) // You can use a.id, but not yet the lazy val
val x = new MyClass2(10)
println(a)

To imitate a lazy "value" whose initial value might not be retrieved until after instance initialization completes (btw, there is nothing special about such objects, e.g. Swift have lazy properties that are even recommended to be declared as variables), you can introduce a wrapper to repeat the same logic that the Scala compiler generates internally for lazy values in Scala:
class LazyVar[T] {
private[this] var value$compute: () => T = () => null.asInstanceOf[T]
#volatile private[this] var value$: T = null.asInstanceOf[T]
#volatile private[this] var isInitialized$ = false
#volatile private[this] var isComputed$ = false
def value_=(value: T) = this.synchronized {
if(!isInitialized$) {
value$compute = () => value
isInitialized$ = true
}
else throw new IllegalStateException("Already initialized")
}
def value: T = this.synchronized {
if(!isInitialized$) throw new IllegalStateException("Not yet initialized")
else if(isComputed$) value$
else {
value$ = value$compute()
isComputed$ = true
value$
}
}
}
Now you just have to change MyClass2 to LazyVar[MyClass2] keeping tha val keyword as you wanted:
case class MyClass2(param: Int)
class MyClass {
private val myVal1: LazyVar[MyClass2] = new LazyVar[MyClass2]
def this(param: Int) {
this()
println("Storing the result of an expensive function...")
myVal1.value = new MyClass2(param)
}
def debug() = println(myVal1.value)
}
Now, if you write something like
val myClass = new MyClass(42)
myClass.debug
myClass.debug
you'll see the value is only computed once:
Storing the result of an expensive function...
MyClass2(42)
MyClass2(42)

Related

Scala: assigning a variable once without val

This is what I want to do -
class A(some args) {
var v: SomeType = null
def method1(args) = {
v = something1
...
method3
}
def method2(args) = {
v = something2
...
method3
}
def method3 = {
// uses v
}
}
In this specific case method1 and 2 are mutually exclusive and either one of them is called exactly once in the lifetime of an instance of A. Also, v is assigned once. I would prefer making it a val. But since I need method2 or method3's context to initialize v, I can't do that in the constructor.
How can achieve this "val" behavior? I can think of modifying method1 and method2 to apply methods, but I don't like the idea. Moreover, method1 and 2 have the same argument signature (hence apply would need some more info to distinguish the 2 types of calls).
An important question is: what exactly do you call "val behavior"? To me "val behavior" is that is assigned once immediately when it is declared, which can be enforced statically. You seem to want to enforce that v is not assigned twice. You possibly also want to enforce it is never read before it is assigned. You could create a very small helper box for that:
final class OnceBox[A] {
private[this] var value: Option[A] = None
def update(v: A): Unit = {
if (value.isDefined)
throw new IllegalStateException("Value assigned twice")
value = Some(v)
}
def apply(): A = {
value.getOrElse {
throw new IllegalStateException("Value not yet assigned")
}
}
}
and now your snippet:
class A(some args) {
val v = new OnceBox[SomeType]
def method1(args) = {
v() = something1
...
method3
}
def method2(args) = {
v() = something2
...
method3
}
def method3 = {
// uses v
v()
}
}
Oh and, just kidding, but Ozma has single-assignment vals built-in :-p
Similar idea to the other answer, but instead of subtypes, a field.
scala> :pa
// Entering paste mode (ctrl-D to finish)
class A {
private[this] var context: Int = _
lazy val v: String =
context match {
case 1 => "one"
case 2 => "two"
case _ => ???
}
def m1() = { context = 1 ; v }
def m2() = { context = 2 ; v }
}
// Exiting paste mode, now interpreting.
defined class A
scala> val a = new A
a: A = A#62ce72ff
scala> a.m2
res0: String = two
scala> a.m1
res1: String = two
Something like this maybe:
class A private (mtdType: Int, ...) {
val v = mdtType match {
case 1 => method1(...)
case 2 => method2(...)
}
}
object A {
def withMethod1(...) = new A(1, ...)
def withMethod2(...) = new A(2, ...)
}
Or, another possibilty:
sealed trait A {
val v
def method3 = println(v)
}
class Method1(...) extends A {
val v = method1(...)
}
class Method2(...) extends A {
val v = method2(...)
}

Make a lazy field be evaluated [duplicate]

Is it possible to do that in Scala using only val:
class MyClass {
private val myVal1: MyClass2 //.....????? what should be here?
def myMethod1(param1: Int) = {
myVal1 = new MyClass2(param1)
//....
// some code....
}
}
The idea is that I can't initialize myVal1 immediately since the argument for its constructor is unknown yet and I have to do that in myMethod1. myVal1 should be visible withing a class and should be immutable.
No mutable state allowed.
So is it possible?
No, it isn't possible to do in the way you want. Consider, what would be the result of
val mc = new MyClass
mc.method1(0)
mc.method1(1)
? An exception thrown for setting myVal1 twice? Or should it keep the first value?
This is not possible, but there are some ways (in addition to using param1 as a constructor parameter)
Change the var into an Option; the setter myMethod1 returns a new instance of the same class with the Option set to the value.
Create a separate mutable Builder class with a var, and turn it into an immutable one later, when all data has been collected
If you are dealing with forward or cyclic references, consider using call-by-name and lazy vals (example 1, example 2)
Update: Example for 1:
class MyClass(val myVal1: Option[Int]) {
def myMethod1(param1: Int): MyClass = {
new MyClass(Some(param1))
}
}
object MyClass {
def apply() = new MyClass(None)
def apply(i: Int) = new MyClass(Some(i))
}
This pattern is used by immutable.Queue for example.
Update: Example for 3 (cyclic reference):
// ref ... call by name
class MyClass(val id: Int, ref: => MyClass) {
lazy val myVal1 = ref
override def toString: String = s"$id -> ${myVal1.id}"
}
to be used like this:
val a: MyClass = new MyClass(1, b)
val b: MyClass = new MyClass(2, a)
println(a)
println(b)
Update: Example for 3 (forward reference):
class MyClass2(val id: Int)
// ref ... call by name
class MyClass(val id: Int, ref: => MyClass2) {
lazy val myVal1 = ref
override def toString: String = s"$id -> ${myVal1.id}"
}
to be used with
val a = new MyClass(1, x)
println(a.id) // You can use a.id, but not yet the lazy val
val x = new MyClass2(10)
println(a)
To imitate a lazy "value" whose initial value might not be retrieved until after instance initialization completes (btw, there is nothing special about such objects, e.g. Swift have lazy properties that are even recommended to be declared as variables), you can introduce a wrapper to repeat the same logic that the Scala compiler generates internally for lazy values in Scala:
class LazyVar[T] {
private[this] var value$compute: () => T = () => null.asInstanceOf[T]
#volatile private[this] var value$: T = null.asInstanceOf[T]
#volatile private[this] var isInitialized$ = false
#volatile private[this] var isComputed$ = false
def value_=(value: T) = this.synchronized {
if(!isInitialized$) {
value$compute = () => value
isInitialized$ = true
}
else throw new IllegalStateException("Already initialized")
}
def value: T = this.synchronized {
if(!isInitialized$) throw new IllegalStateException("Not yet initialized")
else if(isComputed$) value$
else {
value$ = value$compute()
isComputed$ = true
value$
}
}
}
Now you just have to change MyClass2 to LazyVar[MyClass2] keeping tha val keyword as you wanted:
case class MyClass2(param: Int)
class MyClass {
private val myVal1: LazyVar[MyClass2] = new LazyVar[MyClass2]
def this(param: Int) {
this()
println("Storing the result of an expensive function...")
myVal1.value = new MyClass2(param)
}
def debug() = println(myVal1.value)
}
Now, if you write something like
val myClass = new MyClass(42)
myClass.debug
myClass.debug
you'll see the value is only computed once:
Storing the result of an expensive function...
MyClass2(42)
MyClass2(42)

Scala object cloning (copying) without value re-valuation

I have big object:
case class BigObject(val str: String, val number: Int) {
val someVal = ...
val someVal2 = ...
}
I'd like to copy this object without re-valuation of values. Is it possible? Right now I'm using this approach:
val newBigObject = oldBigObject.copy(str = newStr)
As I see from the logs/debugger, "someVal" and "someVal2" are re-valuated. Is it possible to avoid it? As my BigObject is really big and value re-valuation takes some time, but performance is really important for me.
Thanks for your answers!
Here's a way:
Make the someVal and someVal2 fields which are also passed to the constructor and pull out the initialization logic for those fields in the companion object.
In your case:
class BigObject private(val str: String,
val number: Int,
val someVal: SomeType,
val someVal2: SomeType) {
def copy(newStr: String = str, newNumber: Int = number) = {
new BigObject(newStr, newNumber, someVal, someVal2)
}
}
object BigObject {
def apply(str: String, number: Int): BigObject = {
val someVal = initialize() //your initialization logic here
val someVal2 = initialize2()
new BigObject(str, number, someVal, someVal2)
}
}
Now, you can copy without re-evaling the inner fields:
val bigObj = BigObject("hello", 42)
val anotherBigObj = bigObj.copy(newStr = "anotherStr")
Alternatively, if you don't like companion objects, you can make two constructors. The primary one includes all the fields (also the non visible ones) and will be private. The public one will have only the two visible parameters:
class BigObject private(val str: String,
val number: Int,
val someVal: Any,
val someVal2: Any) {
def this(str: String, number: Int) = this(str, number, initializeVal, initializeVal2)
def copy(newStr: String = str, newNumber: Int = number) = {
new BigObject(newStr, newNumber, someVal, someVal2)
}
}
Usage:
val bigObj = new BigObject("hello", 42)
val anotherBigObj = bigObj.copy(newStr = "anotherStr")

avoid explicit cast at scala's dynamic types

I add variables with Dynamic from scala 2.10.0-RC1 like this:
import language.dynamics
import scala.collection.mutable.HashMap
object Main extends Dynamic {
private val map = new HashMap[String, Any]
def selectDynamic(name: String): Any = {return map(name)}
def updateDynamic(name:String)(value: Any) = {map(name) = value}
}
val fig = new Figure(...) // has a method number
Main.figname = fig
Now, if I want to access Main.figname.number it doesn't work, because the compiler thinks it's of type Any.
But it's also Main.figname.isInstanceOf[Figure] == true, so it's Any and Figure, but doesn't have Figures abilities. Now I can cast it like, Main.figname.asInstanceOf[Figure].number and it works! This is ugly! And I can't present this to my domain users (I'd like to build a internal DSL.)
Note: If I use instead of Any the supertype of Figure it doesn't work either.
Is this a bug in scala 2.10, or a feature?
It is quite logical. You are explicitly returning instances of Any. A workaround would be to have instances of Dynamic all along:
import language.dynamics
import scala.collection.mutable.HashMap
import scala.reflect.ClassTag
trait DynamicBase extends Dynamic {
def as[T:ClassTag]: T
def selectDynamic[T](name: String): DynamicBase
def updateDynamic(name:String)(value: Any)
}
class ReflectionDynamic( val self: Any ) extends DynamicBase with Proxy {
def as[T:ClassTag]: T = { implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[T]].cast( self ) }
// TODO: cache method lookup for faster access + handle NoSuchMethodError
def selectDynamic[T](name: String): DynamicBase = {
val ref = self.asInstanceOf[AnyRef]
val clazz = ref.getClass
clazz.getMethod(name).invoke( ref ) match {
case dyn: DynamicBase => dyn
case res => new ReflectionDynamic( res )
}
}
def updateDynamic( name: String )( value: Any ) = {
val ref = self.asInstanceOf[AnyRef]
val clazz = ref.getClass
// FIXME: check parameter type, and handle overloads
clazz.getMethods.find(_.getName == name+"_=").foreach{ meth =>
meth.invoke( ref, value.asInstanceOf[AnyRef] )
}
}
}
object Main extends DynamicBase {
def as[T:ClassTag]: T = { implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[T]].cast( this ) }
private val map = new HashMap[String, DynamicBase]
def selectDynamic[T](name: String): DynamicBase = { map(name) }
def updateDynamic(name:String)(value: Any) = {
val dyn = value match {
case dyn: DynamicBase => dyn
case _ => new ReflectionDynamic( value )
}
map(name) = dyn
}
}
Usage:
scala> class Figure {
| val bla: String = "BLA"
| }
defined class Figure
scala> val fig = new Figure() // has a method number
fig: Figure = Figure#6d1fa2
scala> Main.figname = fig
Main.figname: DynamicBase = Figure#6d1fa2
scala> Main.figname.bla
res40: DynamicBase = BLA
All instances are wrapped in a Dynamic instance.
We can recover the actual type using the as method which performs a dynamic cast.
scala> val myString: String = Main.figname.bla.as[String]
myString: String = BLA
You can add any extensions or custom functionalities to Any or any predefined value classes. You can define an implicit value class like this:
implicit class CustomAny(val self: Any) extends AnyVal {
def as[T] = self.asInstanceOf[T]
}
Usage:
scala> class Figure {
| val xyz = "xyz"
| }
defined class Figure
scala> val fig = new Figure()
fig: Figure = Figure#73dce0e6
scala> Main.figname = fig
Main.figname: Any = Figure#73dce0e6
scala> Main.figname.as[Figure].xyz
res8: String = xyz
The implicit value class is not costly like like regular class. It will be optimised in compile time and it will be equivalent to a method call on a static object, rather than a method call on a newly instantiated object.
You can find more info on implicit value class here.

How do you return an Iterator in Scala?

What must I do in order to be able to return an Iterator from a method/class ? How would one add that trait to a class?
You can extend Iterator, which will require that you implement the next and hasNext methods:
class MyAnswer extends Iterator[Int] {
def hasNext = true
def next = 42
}
But, you will get more flexibility if you extend Iterable, which requires you implement elements (or iterator in 2.8):
class MyAnswer extends Iterable[Int] {
def iterator = new Iterator[Int] {
def hasNext = true
def next = 42
}
}
A common idiom seems to be to expose an iterator to some private collection, like this:
class MyStooges extends Iterable[String] {
private val stooges = List("Moe", "Larry", "Curly")
def iterator = stooges.iterator
}
For a method, just yield:
def odd(from: Int, to: Int): List[Int] =
for (i <- List.range(from, to) if i % 2 == 1) yield i
These two answers had help from the posts below and thanks #Dima.
How do I implement an iterator for an existing singly linked list?
why does this iterable implementation produce a stackoverflow?
Lets assume you have a class linked list. And the requirement is to print all the elements in the list.
trait LinkedList {
def nodeValue: Int
def tailList: LinkedList
}
class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList
object Nil extends LinkedList {
def nodeValue = throw new IllegalAccessException("head of Nil")
def tailList = throw new IllegalAccessException("tail of Nil")
}
val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)
print(chainedLinkedList)
A$A44$A$A44$Node#7b7a2c78res0: Unit = ()
Now Lets implement iterator to this class.
trait LinkedList extends Iterator[Int]{
def nodeValue: Int
def tailList: LinkedList
}
class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
var ptr: LinkedList = this
//The following two are mandatory for extending Iterator
override def hasNext: Boolean = ptr match { case Nil => false; case _=> true}
override def next(): Int = {
val result = ptr.nodeValue
ptr = ptr.tailList
result
}
}
object Nil extends LinkedList {
def nodeValue = throw new IllegalAccessException("head of Nil")
def tailList = throw new IllegalAccessException("tail of Nil")
//The following two are mandatory for extending Iterator
override def hasNext: Boolean = false
override def next(): Int = throw new IllegalAccessException("next of Nil")
}
val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)
//Printing this first Time
chainedLinkedList.foreach(println)
//Prints 2 1
//Printing second Time
chainedLinkedList.foreach(println)
//No output
In the iterator implementation, once ptr reached the end, it could did not advance back. Iterable implementation solves this.
trait LinkedList extends Iterable[Int]{
val nodeValue: Int
val tailList: LinkedList
override def toString(): String = this.mkString(" -> ")
}
class Node(val nodeValue: Int, val tailList: LinkedList) extends LinkedList {
override def iterator: Iterator[Int] = Iterator
.iterate(this: LinkedList)(_.tailList)
.takeWhile(_ != Nil)
.map(_.nodeValue)
}
object Nil extends LinkedList {
lazy val nodeValue= throw new IllegalAccessException("head of Nil")
lazy val tailList = throw new IllegalAccessException("tail of Nil")
override def iterator: Iterator[Int] = Iterator.empty
}
val singleLinkedList = new Node(1,Nil)
val chainedLinkedList = new Node(2,singleLinkedList)
//Printing this first Time
chainedLinkedList.foreach(println)
Output 2 -> 1
chainedLinkedList.foreach(println)
Output 2 -> 1