Can I copy a closure in Scala? - scala

This is perhaps a half-baked idea, but can I copy the environment of an expression? Consider the following example:
class foo[T](block: => T) {
var data = { () => block }
def run() = { data() }
}
var a = 5
var b = new foo({ a += 1; println(a) })
var c = new foo({ a += 1; println(a) })
b.run()
c.run()
b.run()
c.run()
I get the following output:
6
7
8
9
But what I really want is the following:
6
6
7
7
In short, I want foo to have copies of the variables in the block instead of referring to them, once the initial value has been resolved. Can this be done? scala.util.DynamicVariable seems promising, but I'm having a hard time understanding how I might use it in the example above.

If you want to make a copy, then why not make a copy?
var c = new foo({ var aa = a + 1; println(aa) })
If you want to take an existing closure that refers to a variable, and turn it into a closure that refers to a copy of that variable, then I'm afraid it's not possible.
In any case, mutable variables should not be used except in very rare circumstances and in a very controlled manner. That is, not juggling their references.

I think your problem is that you're closing over a (and thus changing its value as your program runs), rather than closing over a different variable initialized from a. You might want to try something more like this:
class bar[T](block: (T) => T, a: T) {
var cur = a
def run() = { cur = block(cur); cur }
}
var a = 5
var b = new bar((r: Int) => { val q = r + 1; println(q); q }, a)
var c = new bar((r: Int) => { val q = r + 1; println(q); q }, a)
b.run()
c.run()
b.run()
c.run()
Output:
6
6
7
7
However, note that unlike your code, this will not affect the value of the a variable as it runs.

1) As n.m. already mentioned, you should prefer immutable concepts when using closures.
2) On the other hand this is exactly what closures are for. They don't capture the value of the variabe, they capture the variable itself! Your question is kinda upside-down. You actually are capturing the environment - the environment of your variable. If you don't need the same variable than copy it as n.m. or Ian McLaird respectively suggested.

Related

How can I assign previously declared variables based on pattern matching?

Say I have some code of the sort:
var (nodes, d, p) = someFunction()
Then I have a few more instructions and I need to refresh the values of nodes, d and p. My current code is something like
val aux = someFunction(); nodes = aux._1; d = aux._2; p = aux._3
Which is obviously unnecessarily ugly. Ideally I'd want to do something like
(nodes, d, p) = someFunction()
Where the variables have been already declared before, but Scala doesn't allow me.
Any ideas on how to "solve" this?
You can write a helper function in the local context that takes the tuple that is returned from someFunction() and mutate needed variables.
Like this:
def someEnclosingFunctionOrCodeBlock = {
var nodes, d, p;
def mutateVars(tuple: (TypeNodes, TypeD, TypeP)): Unit = {
nodes = tuple._1
d = tuple._2
p = tuple._3
}
mutateVars(someFunction())
// ..
mutateVars(someFunction())
}
Additionally, you can fold it into 1 function that is something like callSomeFunctionAndMutateVars().
You can do it 2 ways - using the previous helper function
def callSomeFunctionAndMutateVars() = mutateVars(someFunction())
Or changing the previous helper function to
def callSomeFunctionAndMutateVars(): Unit = {
val tuple = someFunction()
nodes = tuple._1
d = tuple._2
p = tuple._3
}
PS: Honestly, you should consider changing it to immutable structures and an explicit composition of evaluations.

Returning code block in Scala

I was trying to implement the closure example in Scala, from Neal Ford's Functional Thinking presentation which is in Groovy. Refer slide # 43 & 44 https://sea.ucar.edu/sites/default/files/Functional_Thinking.pdf
def makeCounter : Unit = {
var localVar = 0
return { localVar += 1 }
}
This code returns an anonymous function. Now I want to increment the localVar by invoking this anonymous function.
I have two questions:
1. How do I invoke the anonymous function?
2. After invoking it how do I check if the value of localVar is incremented or not?
First I tried this -
val c1 = makeCounter(). It threw below error:
error: makeCounter of type Unit does not take parameters
Then I tried this.
val c1 = makeCounter
This didn't give any error. Only printed c1: Unit = ().
Then,
print(c1) printed (), whereas c1() gave the same error.
First of all. Don't use return, its semantics is completely different in Scala than in Java or Groovy.
The Unit type isn't a synonym for anonymous function. It's more like a indication of side-effects.
The type for an anonymous function is () => A. In your case you want a function that doesn't return any thing, but causes a side-effect. So its type should be () => Unit.
Let's see some code:
def makeCounter : () => Unit = {
var x = 0
{ () => x = x + 1 }
}
val counter = makeCounter
counter(); counter(); counter()
Great! We made makeCounter give us a fresh counter!
There is only one problem. x is a local variable in the method makeCounter and since it's never returned we can't see its value! Ever! We could, for example, remove x from the method, making it public in the outer scope. But it's not very functional. Instead let's make the function return it:
def makeCounter : () => Int = { // Notice now, instead of Unit we use Int
var x = 0
{ () => x = x + 1; x }
}
val counter = makeCounter
println(counter(), counter(), counter())
val counter2 = makeCounter
println(counter2(), counter2(), counter2())
You will see "1,2,3" twice. Once for each counter.
I didn't look at the presentation, so I don't know if this is functional thinking or just one of the slides on the road to functional thinking, but:
scala> def f: () => Int = {
| var v = 0
| () => v += 1 ; v }
f: () => Int
scala> val g = f
g: () => Int = <function0>
scala> g()
res0: Int = 1
scala> g()
res1: Int = 2
scala> g()
res2: Int = 3
The function literal returned by f is, of course, everything after the parens.

how do I increment an integer variable I passed into a function in Scala?

I declared a variable outside the function like this:
var s: Int = 0
passed it such as this:
def function(s: Int): Boolean={
s += 1
return true
}
but the error lines wont go away under the "s +=" for the life of me. I tried everything. I am new to Scala btw.
First of all, I will repeat my words of caution: solution below is both obscure and inefficient, if it possible try to stick with values.
implicit class MutableInt(var value: Int) {
def inc() = { value+=1 }
}
def function(s: MutableInt): Boolean={
s.inc() // parentheses here to denote that method has side effects
return true
}
And here is code in action:
scala> val x: MutableInt = 0
x: MutableInt = MutableInt#44e70ff
scala> function(x)
res0: Boolean = true
scala> x.value
res1: Int = 1
If you just want continuously increasing integers, you can use a Stream.
val numberStream = Stream.iterate(0)(_ + 1).iterator
That creates an iterator over a never-ending stream of number, starting at zero. Then, to get the next number, call
val number: Int = numberStream.next
I have also just started using Scala this was my work around.
var s: Int = 0
def function(s: Int): Boolean={
var newS = s
newS = newS + 1
s = newS
return true
}
From What i read you are not passing the same "s" into your function as is in the rest of the code. I am sure there is a even better way but this is working for me.
You don't.
A var is a name that refers to a reference which might be changed. When you call a function, you pass the reference itself, and a new name gets bound to it.
So, to change what reference the name points to, you need a reference to whatever contains the name. If it is an object, that's easy enough. If it is a local variable, then it is not possible.
See also call by reference, though I don't think this question is a true duplicate.
If you just want to increment a variable starting with 3
val nextId = { var i = 3; () => { i += 1; i } }
then invoke it:
nextId()

What does "code: => Unit" mean in scala?

Does anyone know the type of => Unit in scala? I don't know the meaning of => Unit and how to use it. I defined a function like below:
def test(code: => Unit){
print("start ...")
code
print("end ....")
}
test(print(1))
Does it means a function with any arguments returning Unit?
Thanks
This kind of parameter are called by-name parameter
=> B represents a block a of code which return a B value, their purpose is that they are evaluated only when you call the parameter.
def foo(code: => Int) {
println("Not yet evaluated")
val result = code
println("parameter evaluated %s, is it an int ? %s " format (
result, result.isInstanceOf[Int]) )
}
And you can call foo in the following way :
foo(1)
or
val a = 3
val b = 5
foo {
val c = a * a
c * b
}
The other style of passing parameter is by-value : parameters are evaluated before they are sent to the method
def foo(code : Int) {
println("Parameter already evaluated")
val result = code
println("parameter evaluated : " + result)
}
References
Extract from the Book Functionnal Programming in Scala
More differences between by-name parameter and by-value parameter illustrated
In x: => Type the x is a call by name parameter. That's different than taking an argument which is a function taking no arguments: x: () => Type
This is called a by name parameter, as related to call-by-name parameter evaluation strategy. Please see the linked wikipedia article for similar, but not identical, ways of passing parameters.
To explain it better, let's consider first the two most common parameter evaluation strategies: call by value and call by reference.
Call by value is by far the most common evaluation strategy. It is the sole strategy in Java, for instance, and the default strategy in C. Consider, for instance, this simple Java program:
public class ByValue {
static public void inc(int y) {
y++;
}
static public void main(String... args) {
int x = 0;
inc(x);
System.out.println(x);
}
}
It will print 0, because x's value is copied to y, so that when y is incremented it doesn't change the original value in x. Contrast this with this C++ program with call-by-reference:
#include <stdio.h>
void inc(int &y) {
y++;
}
int main() {
int x = 0;
inc(x);
printf("%d\n", x);
}
This will print 1, because the reference to x is passed to inc, instead of x's value.
Note that Java passes objects references by value, which leads some to claim it does call by reference. This is not true, to the extent that if you were to assign a new object to a parameter of a function, it would not be reflected in the function's caller.
So, what does a call by name looks like? In a call by name, neither value nor reference is passed. Instead, the whole code is passed, and everywhere the parameter is used, the code is executed and its result used. For example:
object ByName {
def incIfZero(y: => Int): Int = if (y == 0) y + 1 else y
def main(args: Array[String]) {
var x = 0
x = incIfZero( { val tmp = x; x += 1; tmp } )
println(x)
}
}
This example prints 2 instead of 1, because the block of code passed as parameter is evaluted twice. When executing, it's as if the second line in the main was written like this:
x = if ({ val tmp = x; x += 1; tmp }) { val tmp = x; x += 1; tmp } + 1 else { val tmp = x; x += 1; tmp }
Now, by name parameters have at least three interesting uses:
It can be used to delay the execution of something until the proper time.
It can be used to avoid the execution in some situations.
It can be used to execute some block of code multiple times.
The first and last cases are pretty obvious, I think. Here's an example of the second case:
implicit def fromBoolean(b: Boolean) = new {
def and(that: => Boolean): Boolean = if (b) that else b }
val x = 0
(x > 0) and (10 / x > 0)
If that was not a by name parameter, there would be an exception thrown at the last line. As it is, it will just return false.
It means call-by-name, which basically means that the value is calculated when used in your function. As opposed to call-by-value which is default in Java (and Scala with regular type syntax), where the value is calculated before the method is called. A Unit type would not make much sense in call-by-value I guess..
This is typically used to create functions that behave as custom control structures, or things like timing or logging as in your example. Stuff you often use AOP to do in Java.

initialise a var in scala

I have a class where I like to initialize my var by reading a configfile, which produces intermediate objects/vals, which I would like to group and hide in a method.
Here is the bare minimum of the problem - I call the ctor with a param i, in reality a File to parse, and the init-method generates the String s, in reality more complicated than here, with a lot of intermediate objects being created:
class Foo (val i: Int) {
var s : String;
def init () {
s = "" + i
}
init ()
}
This will produce the error: class Foo needs to be abstract, since variable s is not defined. In this example it is easy to solve by setting the String to "": var s = "";, but in reality the object is more complex than String, without an apropriate Null-implementation.
I know, I can use an Option, which works for more complicated things than String too:
var s : Option [String] = None
def init () {
s = Some ("" + i)
}
or I can dispense with my methodcall. Using an Option will force me to write Some over and over again, without much benefit, since there is no need for a None else than to initialize it that way I thought I could.
Is there another way to achieve my goal?
var s : Whatever = _ will initialize s to the default value for Whatever (null for reference types, 0 for numbers, false for bools etc.)
Instead of creating separate methods for initialization, you should perform the initialization using the following way :
class Foo(val i: Int) {
var s: String = {
var s0 = " "
s0 += i
// do some more stuff with s0
s0
}
var dashedDate = {
val dashed = new SimpleDateFormat("yy-MM-dd")
dashed.format(updated)
}
// Initializing more than one field:
var (x, y, z) = {
var x0, y0, z0 = 0
// some calculations
(x0, y0, z0)
}
}
Honestly, why are you using var? Why not just do:
val rootObject = readFile(filename)
This would make the most sense to me.