Multi variable assignment in Scala - scala

I am reading a book in scala and one of the exercises is as follows:
Come up with one situation where the assignment x = y = 1 is valid in Scala. (Hint: Pick a suitable type for x.)
The 2 solutions I could come up with are:
val x, y : Int = 1
val x, y = (1, 2)
Have I missed another way that the exercise is looking for?

"valid" and "useful" don't necessarily mean the same thing :)
scala> var y = 2
y: Int = 2
scala> val x = y = 1
x: Unit = ()
scala>

Related

How to find roots of function in Scala?

I'm writing a program in Scala and i want to find the roots of the equation: 2*x^3 + x*(1-2*l + 2*H)-m = 0, where l, H and m are constants, calculated earlier.
In Python, i know there is brentq for such cases but i can't find anything similar in Scala. Is there anything similar or should try find other way of solving this?
There's spire which is a numeric library for Scala. I don't know it very well, but this seems to work in Spire 0.16.0:
scala> val m = 1
m: Int = 1
scala> val l = 2
l: Int = 2
scala> val H = 3
H: Int = 3
scala> import spire.implicits._
import spire.implicits._
scala> import spire.math.Number
import spire.math.Number
scala> val f = poly"2x^3 + ${1-2*l + 2*H}x - $m"
f: spire.math.Polynomial[spire.math.Rational] = (2x³ + 3x - 1)
scala> f.map(Number(_)).roots
res1: spire.math.poly.Roots[spire.math.Number] = Roots(0.3129084094792333580059444668826417)
I do not know of any comprehensive math library in scala. There is one in Java though that you could call from your scala code.
You could have a look at Apache commons math and in particular at section 4.3, root finding.
If l, H and m are constants then this is just
x^3 + ax + b = 0
Where
a = 1/2 - l + H
b = -m/2
There is a very hairy analytical solution to this, see Wolfram Alpha:
https://www.wolframalpha.com/input/?i=solve+x%5E3+%2B+ax+%2B+b+%3D+0
Expressing this in Scala is left as an exercise for the reader :)
As a previous solution commented, use Java's Commons Math! You just import the dependency and you can:
val polynomial: PolynomialFunction = new PolynomialFunction(Array[Double](-m, 1-2*l + 2*H, 2)
val laguerreSolver = new LaguerreSolver()
laguerreSolver.solve(100, polynomial, -100, 100)
This is way faster than spire.
You may also wish to look at Breeze, which I think would also have some routines to help you.

Updating a 2d table of counts

Suppose I want a Scala data structure that implements a 2-dimensional table of counts that can change over time (i.e., individual cells in the table can be incremented or decremented). What should I be using to do this?
I could use a 2-dimensional array:
val x = Array.fill[Int](1, 2) = 0
x(1)(2) += 1
But Arrays are mutable, and I guess I should slightly prefer immutable data structures.
So I thought about using a 2-dimensional Vector:
val x = Vector.fill[Int](1, 2) = 0
// how do I update this? I want to write something like val newX : Vector[Vector[Int]] = x.add((1, 2), 1)
// but I'm not sure how
But I'm not sure how to get a new vector with only a single element changed.
What's the best approach?
Best depends on what your criteria are. The simplest immutable variant is to use a map from (Int,Int) to your count:
var c = (for (i <- 0 to 99; j <- 0 to 99) yield (i,j) -> 0).toMap
Then you access your values with c(i,j) and set them with c += ((i,j) -> n); c += ((i,j) -> (c(i,j)+1)) is a little bit annoying, but it's not too bad.
Faster is to use nested Vectors--by about a factor of 2 to 3, depending on whether you tend to re-set the same element over and over or not--but it has an ugly update method:
var v = Vector.fill(100,100)(0)
v(82)(49) // Easy enough
v = v.updated(82, v(82).updated(49, v(82)(49)+1) // Ouch!
Faster yet (by about 2x) is to have only one vector which you index into:
var u = Vector.fill(100*100)(0)
u(82*100 + 49) // Um, you think I can always remember to do this right?
u = u.updated(82*100 + 49, u(82*100 + 49)+1) // Well, that's actually better
If you don't need immutability and your table size isn't going to change, just use an array as you've shown. It's ~200x faster than the fastest vector solution if all you're doing is incrementing and decrementing an integer.
If you want to do this in a very general and functional (but not necessarily performant) way, you can use lenses. Here's an example of how you could use Scalaz 7's implementation, for example:
import scalaz._
def at[A](i: Int): Lens[Seq[A], A] = Lens.lensg(a => a.updated(i, _), (_(i)))
def at2d[A](i: Int, j: Int) = at[Seq[A]](i) andThen at(j)
And a little bit of setup:
val table = Vector.tabulate(3, 4)(_ + _)
def show[A](t: Seq[Seq[A]]) = t.map(_ mkString " ") mkString "\n"
Which gives us:
scala> show(table)
res0: String =
0 1 2 3
1 2 3 4
2 3 4 5
We can use our lens like this:
scala> show(at2d(1, 2).set(table, 9))
res1: String =
0 1 2 3
1 2 9 4
2 3 4 5
Or we can just get the value at a given cell:
scala> val v: Int = at2d(2, 3).get(table)
v: Int = 5
Or do a lot of more complex things, like apply a function to a particular cell:
scala> show(at2d(2, 2).mod(((_: Int) * 2), table))
res8: String =
0 1 2 3
1 2 3 4
2 3 8 5
And so on.
There isn't a built-in method for this, perhaps because it would require the Vector to know that it contains Vectors, or Vectors or Vectors etc, whereas most methods are generic, and it would require a separate method for each number of dimensions, because you need to specify a co-ordinate arg for each dimension.
However, you can add these yourself; the following will take you up to 4D, although you could just add the bits for 2D if that's all you need:
object UpdatableVector {
implicit def vectorToUpdatableVector2[T](v: Vector[Vector[T]]) = new UpdatableVector2(v)
implicit def vectorToUpdatableVector3[T](v: Vector[Vector[Vector[T]]]) = new UpdatableVector3(v)
implicit def vectorToUpdatableVector4[T](v: Vector[Vector[Vector[Vector[T]]]]) = new UpdatableVector4(v)
class UpdatableVector2[T](v: Vector[Vector[T]]) {
def updated2(c1: Int, c2: Int)(newVal: T) =
v.updated(c1, v(c1).updated(c2, newVal))
}
class UpdatableVector3[T](v: Vector[Vector[Vector[T]]]) {
def updated3(c1: Int, c2: Int, c3: Int)(newVal: T) =
v.updated(c1, v(c1).updated2(c2, c3)(newVal))
}
class UpdatableVector4[T](v: Vector[Vector[Vector[Vector[T]]]]) {
def updated4(c1: Int, c2: Int, c3: Int, c4: Int)(newVal: T) =
v.updated(c1, v(c1).updated3(c2, c3, c4)(newVal))
}
}
In Scala 2.10 you don't need the implicit defs and can just add the implicit keyword to the class definitions.
Test:
import UpdatableVector._
val v2 = Vector.fill(2,2)(0)
val r2 = v2.updated2(1,1)(42)
println(r2) // Vector(Vector(0, 0), Vector(0, 42))
val v3 = Vector.fill(2,2,2)(0)
val r3 = v3.updated3(1,1,1)(42)
println(r3) // etc
Hope that's useful.

Scala: is it possible to make a method "+" work like this: x + y = z?

I have a graph, with each vertex connected to 6 neighbors.
While constructing the graph and making declarations of the connections, I would like to use a syntax like this:
1. val vertex1, vertex2 = new Vertex
2. val index = 3 // a number between 0 and 5
3. vertex1 + index = vertex2
The result should be that vertex2 be declared assigned as index-th neighbor of vertex1, equivalent to:
4. vertex1.neighbors(index) = vertex2
While frobbing with the implementation of Vertex.+, I came up with the following:
5. def +(idx: Int) = neighbors(idx)
which, very surprisingly indeed, did not cause line 3 to be underlined red by my IDE (IntelliJIdea, BTW).
However, compilation of line 3 offsprang the following message:
error: missing arguments for method + in class Vertex;
follow this method with `_' if you want to treat it as a partially applied function
Next, I tried with an extractor, but actually, that doesn't seem to fit the case very well.
Does anybody have any clue if what I'm trying to achieve is anywhat feasible?
Thank you
You probably can achieve what you want by using := instead of =. Take a look at this illustrating repl session:
scala> class X { def +(x:X) = x; def :=(x:X) = x }
defined class X
scala> val a = new X;
a: X = X#7d283b68
scala> val b = new X;
b: X = X#44a06d88
scala> val c = new X;
c: X = X#fb88599
scala> a + b := c
res8: X = X#fb88599
As one of the comments stated, the custom = requires two parameter, for example vertex1(i)=vertex2 is dessugared to vertext.update(i,vertex2) thus forbidding the exact syntax you proposed. On the other hand := is a regular custom operator and a:=b will dessugar to a.:=(b).
Now we still have one consideration to do. Is the precedence going to work as you intent? The answer is yes, according to the Language Specification section 6.12.3. + has higher precedence than :=, so it ends up working as (a+b):=c.
Not exactly what you want, just playing with right-associativity:
scala> class Vertex {
| val neighbors = new Array[Vertex](6)
| def :=< (n: Int) = (this, n)
| def >=: (conn: (Vertex, Int)) {
| val (that, n) = conn
| that.neighbors(n) = this
| this.neighbors((n+3)%6) = that
| }
| }
defined class Vertex
scala> val a, b, c, d = new Vertex
a: Vertex = Vertex#c42aea
b: Vertex = Vertex#dd9f68
c: Vertex = Vertex#ca0c9
d: Vertex = Vertex#10fed2c
scala> a :=<0>=: b ; a :=<1>=: c ; d :=<5>=: a
scala> a.neighbors
res25: Array[Vertex] = Array(Vertex#dd9f68, Vertex#ca0c9, Vertex#10fed2c, null, null, null)

x = y =1 in Scala?

While going through the book Scala for the Impatient, I came across this question:
Come up with one situation where the assignment x = y = 1 is valid in
Scala. (Hint: Pick a suitable type for x.)
I am not sure what exactly the author means by this question. The assignment doesn't return a value, so something like var x = y = 1 should return Unit() as the value of x. Can somebody point out what might I be missing here?
Thanks
In fact, x is Unit in this case:
var y = 2
var x = y = 1
can be read as:
var y = 2
var x = (y = 1)
and finally:
var x: Unit = ()
You can get to the point of being able to type x=y=1 in the REPL shell with no error thus:
var x:Unit = {}
var y = 0
x = y = 1
Here’s another less known case where the setter method returns its argument. Note that the type of x is actually Int here:
object AssignY {
private var _y: Int = _
def y = _y
def y_=(i: Int) = { _y = i; i }
}
import AssignY._
var x = y = 1
(This feature is used in the XScalaWT library, and was discussed in that question.)
BTW if assigning of the same value to both variables still required then use:
scala> var x#y = 1
x: Int = 1
y: Int = 1
It's valid, but not sensible, this make confusion.
scala> var x=y=1
x: Unit = ()
scala> y
res60: Int = 1
scala> var x#y = 1
x: Int = 1
y: Int = 1

Scala Tuple Deconstruction

I am new to Scala, and ran across a small hiccup that has been annoying me.
Initializing two vars in parallel works great: var (x,y) = (1,2)
However I can't find a way to assign new values in parallel: (x,y) = (x+y,y-x) //invalid syntax
I end up writing something like this: val xtmp = x+y; y = x-y; x = xtmp
I realize writing functional code is one way of avoiding this, but there are certain situations where vars just make more sense.
I have two questions:
1) Is there a better way of doing this? Am I missing something?
2) What is the reason for not allowing true parallel assignment?
Unfortunately, you cannot do multiple assignments in Scala. But you may use tuples, if they fit your problem:
scala> var xy = (1,2)
xy: (Int, Int) = (1,2)
scala> xy = (xy._1 + xy._2, xy._2 - xy._1)
xy: (Int, Int) = (3,1)
This way, xy is one tuple with two values. The first value can be accessed using xy._1, the second one using xy._2.
Scala has 2 types of variables: vals and vars. Vals are similar to Java's final variables, so as far as I understand from what you're asking, the only way to assign new values in parallel to vals is by:
scala> val (x, y) = (1, 2);
or
scala> val s = (3, 4);
s: (Int, Int) = (3,4)
scala> s._1
res1: Int = 3
scala> s._2
res2: Int = 4