Does scala maintains the values of variable by copy or reference?
For example, in Ruby "the closure will actually extend the lifetime of all the variables that it needs. It will not copy them, but will retain a reference to them and the variables themselves will not be eligible for garbage collection (if the language has garbage collection) while the closure is around". [SKORKIN]
Scala Closures are functions which uses one or more free variables and the return value of this function is dependent of these variable. The free variables are defined outside of the Closure Function and is not included as a parameter of this function.
The choice of closure type depends entirely on the degree of drainage, the existing amount of tissue for wound closure and infection status at the site of wound closure.
Java and Scala both use call by value exclusively, except that the value is either a primitive or a pointer to an object. If your object contains mutable fields, then there is very little substantive difference between this and call by reference.
Delta Lake with Apache Spark using Scala A closure is a function, whose return value depends on the value of one or more variables declared outside this function. The following piece of code with anonymous function. val multiplier = (i:Int) => i * 10.
The jvm has no closures, it has only object. The scala compiler generate anonymous classes implementing the appropriate Function trait (depending of the argument and result type of the signature) for each occurence of a closure in the code.
For instance, if for some l : List[Int]
, you write l.map(i => i + 1)
, it will be converted to
class SomeFreshName extends Function[Int, Int] {
def apply(i: Int) = i + 1
}
l.map(new SomeFreshName())
In this case, there is no real closure, as in i => i + 1, there is no free variable, only the argument i and constant.
If you close over some local vals, or equivalently a parameter of the function, they will have to be passed as constructor parameter to the closure-implementing class :
for l.map(i => s + i)
where s is a string parameter or a local of the method, it will do
class SomeFreshName(s: String) extends Function[Int, String] {
def apply(i: Int) = s + i
}
l.map(new SomeFreshName(s))
passing as many parameter in the constructor as needed.
Note : If s was a field of the class instead of a local of the method, then s + i
would be in fact this.s + i
, and this
would be passed to anonymous class.
There is nothing special in the garbage collector (again, the jvm does not know of closures), simply, as the closure object has a reference to s, s will live at least as long as the closure object.
Note that exactly the same thing happens in the java language with anonymous classes. When an anonymous class uses locals of the enclosing method, those locals are silently added as fields of the anonymous classes, and passed at constructor.
In java, this is allowed only if the local are final
, which is equivalent of scala val
, as opposed to var
.
Indeed, with this implementation, as soon as the closure is created, it has its own copy of the variable it closes other. If it modifies them, those modification will not be reflected in the method. If they are modified in the closure, this will not be reflected in the method.
Suppose you write
var i = 0
l.foreach{a => println(i + ": " + a); i = i + 1}
println("There are " + i + " elements in the list")
The implementation described before would be
class SomeFreshName(var i: Int) extends Int => Unit {
def apply(a: Int) = println(i + ": " + a); i = i + 1
}
var i = 0
l.foreach(new SomeFreshName(i)
println("There are " + i + " elements in the list")
Doing that, there would be two variable i
, the one in the method, and the one in SomeFreshName
. Only the one in SomeFreshName would be modified, and the last println would always report 0 elements.
Scala solve his problem by replacing var taken in the closure by reference objects. Given a class
class Ref[A](var content: A)
the code is first replaced by
val iRef = new Ref[Int](0)
l.foreach{a =>
println(iRef.content + ": " + a);
iRef.content += iRef.content + 1
}
println("There are " + i + " elements in the list")
This is done of course only to var that happens to be taken by a closure, not to every var. Doing that, the var has been replaced by a val, the actual variable value has been moved into the heap. Now, the closure can be done as usual, and it works
class SomeFreshName(iRef: Ref[Int]) ...
Closures in Scala also don't deep copy objects, they'll only keep a reference to the object. Moreover, a closure does not get it's own lexical scope, but instead, it uses the surrounding lexical scope.
class Cell(var x: Int)
var c = new Cell(1)
val f1 = () => c.x /* Create a closure that uses c */
def foo(e: Cell) = () => e.x
/* foo is a closure generator with its own scope */
val f2 = foo(c) /* Create another closure that uses c */
val d = c /* Alias c as d */
c = new Cell(10) /* Let c point to a new object */
d.x = d.x + 1 /* Increase d.x (i.e., the former c.x) */
println(f1()) /* Prints 10 */
println(f2()) /* Prints 2 */
I can't comment on garbage collection, but I assume that the JVM's garbage collector will not remove objects that are referenced by a closure, as long as the closure is still referenced.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With