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

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.

Related

Is it possible in Scala to make a function that disallows the use of closures?

Say I have some function like this:
def doSomeCode(code: => Unit): Unit = {
println("Doing some code!")
code
}
It takes in a function, prints out "Doing some code!" and then calls the passed function. If for example we called it like:
doSomeCode {
println("Some code done!")
}
It would print out "Doing some code!", followed by "Some code done!".
But I would like to disallow the use of outside variables inside that code block, for example:
def otherFunction(): Unit = {
val number = 10
doSomeCode{
println("The number is " + number)
}
}
This will print out "Doing some code!", followed by "The number is 10". But I would like it to instead throw an error because I do not want number to be in the scope of doSomeCode. Is this possible to achieve in Scala?
To be clear I am not asking if this is a good idea, I just want to know if it is possible.
Edit:
The reason I want this is because I am trying to make a syntax that is perfectly functional, I want a block with no side effects. Ideally the syntax would look like:
val a = 1
val b = 2
val c = 3
val d = 4
val sum = use(a, c, d){
val total = a + c + d
total
}
This way I as a programmer know that the only variables used are a, c, and d and that sum is the only output. Trying to use anything else, eg b, would result in an error. Currently it is not possible to know at a glance what variables a block is using. I can achieve this by just making and using a function like this:
def example(): Unit = {
val a = 1
val b = 2
val c = 3
val d = 4
val sum = sum(a, c, d)
}
def sum(a: Int, b: Int, c: Int): Int = {
val total = a + b + c
total
}
This behaves exactly like how I want it to, but I would like it to be inline with the other code, not outside as an external function.
scala> def mkClosure(i: Int) = { s: String => s"$i - $s" }
mkClosure: (i: Int)String => String
scala> mkClosure(5)
res0: String => String = <function1>
Since whether the function depends on values which aren't parameters isn't encoded in the type system, there's no compiler-enforceable difference in Scala between such a function and a pure one. It's unlikely to be possible with macros: a compiler plugin is probably your best bet, especially if you want to allow certain values (e.g. println) to be used inside a block.

print string whenever variable get changed with scala macro

If I have defined a variable b val b:B. Is it possible to print the value of b each time b is assigned to a new value. Like the code below:
case class B(name:String) {
}
var b = B("123")
b = B("xxx")
println(s"b is changed to $b")
b = B("xxJJx")
println(s"b is changed to $b")
I hope the code println(s"b is changed to $b") be hidden in some sort of macro when I create B or b, like:
var b = macro_wrap(B("123"))
With plain var, you cannot do it.
The closest you can get is to create a getter-setter pair which will look like a var from outside:
object Stuff {
private var b0 = B("123")
def b: B = b0
def b_=(newb: B): Unit = {
b0 = newb
println(s"b is changed to $newb")
}
}
Then:
Stuff.b = B("xxx")
Will print the new value.
Note that the setter is a method named b_= which is treated somewhat specially by Scala compiler - an assignment Stuff.b = B("xxx") is automatically translated into Stuff.b_=(B("xxx")). This works only if setter is accompanied by a getter.

Bind type variable to element type of collection

How does one bind a polymorphic type variable to the parameter of a unary type constructor in Scala?
def f[CollectionOfE] = new Blah[...]
{
def g(a: E) =
{ ... }
}
...
val x = f[Set[Int]] // want E above to bind to Int
Within the definition of g i wish to be able to refer to the parameter type of the collection on which f has been instantiated.
I've tried:
def f[C[E]] = new Blah[...] ...
but the scope of E seems to be local to the [ ... ], if that makes any sense...
You can do this if you define E a separate parameter. E.g.
def f[E, C <: util.Collection[E]] = new Blah {
def g(a: E) = ...
}
val x = f[Int, Set[Int]].g(1) // compiles
val y = f[Int, Set[Int]].g("string") // doesn't compile
Edit
You can make it slightly more concise by calling the function with underscore:
f[Int, Set[_]].g(1)
If I understand your intention correctly, you might want something like this:
def f[E, C[_]] = new Blah[...] {
def g(e: E) = ???
}
...
f[Int, Set]
Basically, if you want to refer to a type later, you need to put it as a separate type parameter. You might also want to limit type of C[_] to some collection.

How do you call a function which takes a tuple of two as an argument and returns a tuple of two as a result in Scala?

I am very new to Scala. I have been assigned the task of coding the Fast Fibonacci algorithm. I am finding it difficult when it comes to actually calling the function. The function takes a tuple of two and returns a tuple of two as a result. I don't know if my logic for fibStep is correct but I will get to that as soon as I can actually test the function. The following is what I have so far:
def fastFib(x: Long ): Long = {
def fibStep(x:(Long, Long)): (Long, Long) = {
//setting temporary variables a and b
def a = x._1
def b = x._2
//applying the fast Fibonacci algorithm
def c = a * (b * 2 - a)
def d = a * a + b * b
if (c+d % 2 == 0) return (c,d)
else return (d, c+d)
}
def tuple = (x-1,x-2)
return fibStep(tuple)
}
I need to pass the tuple (x-1,x-2) to fibStep. How do I do it? Thanks
The problem is in return statement. You trying to return tuple, instead of Long.
Fix:
def fastFib(x: Long ): Long = {
...
return fibStep(tuple)._1 // or ._2
}
Note: I'm not sure if your algorithm is correct
You've got a number of problems here.
def is used to define functions
val should be used to define variables
return should not be used. You 'return' a result simply by it being the last value in an expression.
A tuple is defined simply using parenthesis:
val myTuple = (1,2)
With this information you should be able to make a better attempt at it.

Can I copy a closure in 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.