Consider the following code that counts the frequency of each string in the list and stores the results in the mutable map. This works great, but I don't understand where the += method is defined?! Is this some weird implicit conversion thing or what? I saw this code somewhere but it didn't include an explanation for the +=.
val list = List("a", "b", "a")
val counts = new scala.collection.mutable.HashMap[String, Int]().withDefaultValue(0)
list.foreach(counts(_) += 1)
counts
//> res7: scala.collection.mutable.Map[String,Int] = Map(a -> 2, b -> 1)
The apply of map returns an Int, but Int doesn't have a += and this method updates the map with a new value, so it looks as if the apply returns a mutable integer that has a += method...
This is not an implicit conversion - it is a desugaring.
Writing:
x += 1
desugars to:
x = x + 1
if the class of x does not have a += method defined on it.
In the same way:
counts("a") += 1
desugars to:
counts("a") = counts("a") + 1
because counts("a") is an Int, and Int does not have a += method defined.
On the other hand, writing:
x(expression1) = expression2
desugars to a call to the update method in Scala:
x.update(expression1, expression2)
Every mutable Map has an update method defined - it allows setting keys in the map.
So the entire expression is desugared to:
list.foreach(x => counts.update(x, counts(x) + 1))
This += is not to be confused with the += method on mutable.Maps in Scala. That method updates the entry in the map if that key already existed, or adds a new key-value pair. It returns the this reference, that is, the same map, so you can chain += calls. See ScalaDoc or the source code.
For these moments where you wonder what compiler magic is happening in a part of your code, scalac -print is your best friend (see this question).
If you do a scalac -print C.scala where C.scala is
package test
class C {
def myMethod() {
val counts = new scala.collection.mutable.HashMap[String, Int]().withDefaultValue(0)
counts("a") += 1
}
}
you get
package test {
class C extends Object {
def myMethod(): Unit = {
val counts: collection.mutable.Map = new collection.mutable.HashMap().withDefaultValue(scala.Int.box(0));
counts.update("a", scala.Int.box(scala.Int.unbox(counts.apply("a")).+(1)))
};
def <init>(): test.C = {
C.super.<init>();
()
}
}
It came as a surprise for me also, but apparently scalac will transform
map(key) =<op> rhs
to
map.update(key, map.apply(key) <op> rhs)
Related
I have the following Scala code:
object Solution {
def getBestSolution(sumList: List[Int]): Int = {
return 0
}
def main(args: Array[String]) {
val t = readInt()
(0 until t).foreach({
val n = readInt()
val a = readLine().split(" ").map(_.toInt).toList
val sumList = a.scanLeft(0)(_ + _).tail.toList
//println(classOf[sumList])
println(sumList)
println(getBestSolution(sumList))
})
}
}
For it, I am getting this error:
file.scala:16: error: type mismatch;
found : Unit
required: Int => ?
println(getBestSolution(sumList))
^
one error found
Any idea what is causing this?
The argument you are passing to foreach is the result of executing the code block (which is a Unit), not a function.
Remove the outer parentheses (they do not really hurt anything, but are unnecessary and look ugly), and add _ => in the beginning:
(0 to t).foreach { _ =>
...
println(getBestSolution(sumList))
}
This is the proper syntax for creating an unnamed function. The stuff before => is the parameter list that the function accepts. In your case, you can just put an underscore there, because you do not need the value of the parameter. Or you could give it a name if you needed to do something with it, e.g.: (0 to t).foreach { x => println(x*x) }
you could have done it with simple for comprehension too instead of foreach
for(x <- 0 to t){
val n = readInt()
val a = readLine().split(" ").map(_.toInt).toList
val sumList = a.scanLeft(0)(_ + _).tail.toList
//println(classOf[sumList])
println(sumList)
println(getBestSolution(sumList))
}
To sum up, Programming in Scala book has pointed that Scala provides the for comprehension, which provides syntactically pleasing nesting of map, flatMap, and filter ... The for comprehension is not a looping construct, but is a syntactic construct the compiler reduces to map, flatMap, and filter.
I wrote this simple program in my attempt to learn how Cats Writer works
import cats.data.Writer
import cats.syntax.applicative._
import cats.syntax.writer._
import cats.instances.vector._
object WriterTest extends App {
type Logged2[A] = Writer[Vector[String], A]
Vector("started the program").tell
val output1 = calculate1(10)
val foo = new Foo()
val output2 = foo.calculate2(20)
val (log, sum) = (output1 + output2).pure[Logged2].run
println(log)
println(sum)
def calculate1(x : Int) : Int = {
Vector("came inside calculate1").tell
val output = 10 + x
Vector(s"Calculated value ${output}").tell
output
}
}
class Foo {
def calculate2(x: Int) : Int = {
Vector("came inside calculate 2").tell
val output = 10 + x
Vector(s"calculated ${output}").tell
output
}
}
The program works and the output is
> run-main WriterTest
[info] Compiling 1 Scala source to /Users/Cats/target/scala-2.11/classes...
[info] Running WriterTest
Vector()
50
[success] Total time: 1 s, completed Jan 21, 2017 8:14:19 AM
But why is the vector empty? Shouldn't it contain all the strings on which I used the "tell" method?
When you call tell on your Vectors, each time you create a Writer[Vector[String], Unit]. However, you never actually do anything with your Writers, you just discard them. Further, you call pure to create your final Writer, which simply creates a Writer with an empty Vector. You have to combine the writers together in a chain that carries your value and message around.
type Logged[A] = Writer[Vector[String], A]
val (log, sum) = (for {
_ <- Vector("started the program").tell
output1 <- calculate1(10)
foo = new Foo()
output2 <- foo.calculate2(20)
} yield output1 + output2).run
def calculate1(x: Int): Logged[Int] = for {
_ <- Vector("came inside calculate1").tell
output = 10 + x
_ <- Vector(s"Calculated value ${output}").tell
} yield output
class Foo {
def calculate2(x: Int): Logged[Int] = for {
_ <- Vector("came inside calculate2").tell
output = 10 + x
_ <- Vector(s"calculated ${output}").tell
} yield output
}
Note the use of for notation. The definition of calculate1 is really
def calculate1(x: Int): Logged[Int] = Vector("came inside calculate1").tell.flatMap { _ =>
val output = 10 + x
Vector(s"calculated ${output}").tell.map { _ => output }
}
flatMap is the monadic bind operation, which means it understands how to take two monadic values (in this case Writer) and join them together to get a new one. In this case, it makes a Writer containing the concatenation of the logs and the value of the one on the right.
Note how there are no side effects. There is no global state by which Writer can remember all your calls to tell. You instead make many Writers and join them together with flatMap to get one big one at the end.
The problem with your example code is that you're not using the result of the tell method.
If you take a look at its signature, you'll see this:
final class WriterIdSyntax[A](val a: A) extends AnyVal {
def tell: Writer[A, Unit] = Writer(a, ())
}
it is clear that tell returns a Writer[A, Unit] result which is immediately discarded because you didn't assign it to a value.
The proper way to use a Writer (and any monad in Scala) is through its flatMap method. It would look similar to this:
println(
Vector("started the program").tell.flatMap { _ =>
15.pure[Logged2].flatMap { i =>
Writer(Vector("ended program"), i)
}
}
)
The code above, when executed will give you this:
WriterT((Vector(started the program, ended program),15))
As you can see, both messages and the int are stored in the result.
Now this is a bit ugly, and Scala actually provides a better way to do this: for-comprehensions. For-comprehension are a bit of syntactic sugar that allows us to write the same code in this way:
println(
for {
_ <- Vector("started the program").tell
i <- 15.pure[Logged2]
_ <- Vector("ended program").tell
} yield i
)
Now going back to your example, what I would recommend is for you to change the return type of compute1 and compute2 to be Writer[Vector[String], Int] and then try to make your application compile using what I wrote above.
Does Scala provide a means of accessing primitives by reference (e.g., on the heap) out of the box? E.g., is there an idiomatic way of making the following code return 1?:
import scala.collection.mutable
val m = new mutable.HashMap[String, Int]
var x = m.getOrElseUpdate("foo", 0)
x += 1
m.get("foo") // The map value should be 1 after the preceding update.
I expect I should be able to use a wrapper class like the following as the map's value type (thus storing pointers to the WrappedInts):
class WrappedInt(var theInt:Int)
...but I'm wondering if I'm missing a language or standard library feature.
You can't do that with primitives or their non-primitives counter parts in Java nor Scala. Don't see any other way but use the WrappedInt.
If your goal is to increment map values by key, than you can use some nicer solutions instead of wrapper.
val key = "foo"
val v = m.put(key, m.getOrElse(key, 0) + 1)
or another approach would be to set a default value 0 for the map:
val m2 = m.withDefault(_ => 0)
val v = m2.put(key, m2(key) + 1)
or add extension method updatedWith
implicit class MapExtensions[K, V](val map: Map[K, V]) extends AnyVal {
def updatedWith(key: K, default: V)(f: V => V) = {
map.put(key, f(map.getOrElse(key, default)))
}
}
val m3 = m.updatedWith("foo", 0) { _ + 1 }
I'm trying to create a class that has a map of keys -> function calls, and the following code is not behaving as I would like it to.
class MyClass {
val rnd = scala.util.Random
def method1():Double = {
rnd.nextDouble
}
def method2():Double = {
rnd.nextDouble
}
def method3():Double = {
rnd.nextDouble
}
def method4():Double = {
rnd.nextDouble
}
def method5():Double = {
rnd.nextDouble
}
var m = Map[String,Double]()
m += {"key1"-> method1}
m += {"key2"-> method2}
m += {"key3"-> method3}
m += {"key4"-> method4}
m += {"key5"-> method5}
def computeValues(keyList:List[String]):Map[String,Double] = {
var map = Map[String,Double]()
keyList.foreach(factor => {
val value = m(factor)
map += {factor -> value}
})
map
}
}
object Test {
def main(args : Array[String]) {
val b = new MyClass
for(i<-0 until 3) {
val computedValues = b.computeValues(List("key1","key4"))
computedValues.foreach(element => println(element._2))
}
}
}
The following output
0.022303440910331762
0.8557634244639081
0.022303440910331762
0.8557634244639081
0.022303440910331762
0.8557634244639081
indicates that once the function is placed in the map, it's a frozen instance (each key producing the same value for each pass). The behavior I would like to see is that the key would refer to a function call, generating a new random value rather than just returning the instance held in the map.
The problem is with the signature of your map m. You described that you wanted to put functions in the map; however you've declared it as Map[String, Double] which is just a map of strings to doubles. The correct type would be Map[String, () => Double].
Because brackets are optional on no-arg method invocations, the difference in types here is very important. When the map is being populated, the methods are invoked at insertion time in order to match the type signature (I believe this is done by an implicit conversion but I'm not 100% sure).
By simply changing the declared signature of your map, the functions are inserted as you desire, and can be evaluated during computeValues (requires a change on line 35 to map += {factor -> value()}), resulting in the following output (tested on Scala 2.8):
0.662682479130198
0.5106611727782306
0.6939805749938253
0.763581022199048
0.8785861039613938
0.9310533868752249
You need to map the keys to functions, not to the answer that the function would give you. Try this:
var m = Map[String,() => Double]()
m += /* etc. */
m.values.foreach(println(x => x()))
m.values.foreach(println(x => x()))
I would use scala's type inference to define the map.
There's no need to define the methods separately, if they're only used via the map.
Also you can use an immutable val, instead of a mutable var.
val m = Map( "key1" -> {() => rnd.nextDouble},
"key2" -> {() => rnd.nextDouble},
"key3" -> {() => rnd.nextDouble},
"key4" -> {() => rnd.nextDouble},
"key5" -> {() => rnd.nextDouble})
You also need to change line 35 to value()
Is there any reason for Scala not support the ++ operator to increment primitive types by default?
For example, you can not write:
var i=0
i++
Thanks
My guess is this was omitted because it would only work for mutable variables, and it would not make sense for immutable values. Perhaps it was decided that the ++ operator doesn't scream assignment, so including it may lead to mistakes with regard to whether or not you are mutating the variable.
I feel that something like this is safe to do (on one line):
i++
but this would be a bad practice (in any language):
var x = i++
You don't want to mix assignment statements and side effects/mutation.
I like Craig's answer, but I think the point has to be more strongly made.
There are no "primitives" -- if Int can do it, then so can a user-made Complex (for example).
Basic usage of ++ would be like this:
var x = 1 // or Complex(1, 0)
x++
How do you implement ++ in class Complex? Assuming that, like Int, the object is immutable, then the ++ method needs to return a new object, but that new object has to be assigned.
It would require a new language feature. For instance, let's say we create an assign keyword. The type signature would need to be changed as well, to indicate that ++ is not returning a Complex, but assigning it to whatever field is holding the present object. In Scala spirit of not intruding in the programmers namespace, let's say we do that by prefixing the type with #.
Then it could be like this:
case class Complex(real: Double = 0, imaginary: Double = 0) {
def ++: #Complex = {
assign copy(real = real + 1)
// instead of return copy(real = real + 1)
}
The next problem is that postfix operators suck with Scala rules. For instance:
def inc(x: Int) = {
x++
x
}
Because of Scala rules, that is the same thing as:
def inc(x: Int) = { x ++ x }
Which wasn't the intent. Now, Scala privileges a flowing style: obj method param method param method param .... That mixes well C++/Java traditional syntax of object method parameter with functional programming concept of pipelining an input through multiple functions to get the end result. This style has been recently called "fluent interfaces" as well.
The problem is that, by privileging that style, it cripples postfix operators (and prefix ones, but Scala barely has them anyway). So, in the end, Scala would have to make big changes, and it would be able to measure up to the elegance of C/Java's increment and decrement operators anyway -- unless it really departed from the kind of thing it does support.
In Scala, ++ is a valid method, and no method implies assignment. Only = can do that.
A longer answer is that languages like C++ and Java treat ++ specially, and Scala treats = specially, and in an inconsistent way.
In Scala when you write i += 1 the compiler first looks for a method called += on the Int. It's not there so next it does it's magic on = and tries to compile the line as if it read i = i + 1. If you write i++ then Scala will call the method ++ on i and assign the result to... nothing. Because only = means assignment. You could write i ++= 1 but that kind of defeats the purpose.
The fact that Scala supports method names like += is already controversial and some people think it's operator overloading. They could have added special behavior for ++ but then it would no longer be a valid method name (like =) and it would be one more thing to remember.
I think the reasoning in part is that +=1 is only one more character, and ++ is used pretty heavily in the collections code for concatenation. So it keeps the code cleaner.
Also, Scala encourages immutable variables, and ++ is intrinsically a mutating operation. If you require +=, at least you can force all your mutations to go through a common assignment procedure (e.g. def a_=).
The primary reason is that there is not the need in Scala, as in C. In C you are constantly:
for(i = 0, i < 10; i++)
{
//Do stuff
}
C++ has added higher level methods for avoiding for explicit loops, but Scala has much gone further providing foreach, map, flatMap foldLeft etc. Even if you actually want to operate on a sequence of Integers rather than just cycling though a collection of non integer objects, you can use Scala range.
(1 to 5) map (_ * 3) //Vector(3, 6, 9, 12, 15)
(1 to 10 by 3) map (_ + 5)//Vector(6, 9, 12, 15)
Because the ++ operator is used by the collection library, I feel its better to avoid its use in non collection classes. I used to use ++ as a value returning method in my Util package package object as so:
implicit class RichInt2(n: Int)
{
def isOdd: Boolean = if (n % 2 == 1) true else false
def isEven: Boolean = if (n % 2 == 0) true else false
def ++ : Int = n + 1
def -- : Int = n - 1
}
But I removed it. Most of the times when I have used ++ or + 1 on an integer, I have later found a better way, which doesn't require it.
It is possible if you define you own class which can simulate the desired output however it may be a pain if you want to use normal "Int" methods as well since you would have to always use *()
import scala.language.postfixOps //otherwise it will throw warning when trying to do num++
/*
* my custom int class which can do ++ and --
*/
class int(value: Int) {
var mValue = value
//Post-increment
def ++(): int = {
val toReturn = new int(mValue)
mValue += 1
return toReturn
}
//Post-decrement
def --(): int = {
val toReturn = new int(mValue)
mValue -= 1
return toReturn
}
//a readable toString
override def toString(): String = {
return mValue.toString
}
}
//Pre-increment
def ++(n: int): int = {
n.mValue += 1
return n;
}
//Pre-decrement
def --(n: int): int = {
n.mValue -= 1
return n;
}
//Something to get normal Int
def *(n: int): Int = {
return n.mValue
}
Some possible test cases
scala>var num = new int(4)
num: int = 4
scala>num++
res0: int = 4
scala>num
res1: int = 5 // it works although scala always makes new resources
scala>++(num) //parentheses are required
res2: int = 6
scala>num
res3: int = 6
scala>++(num)++ //complex function
res4: int = 7
scala>num
res5: int = 8
scala>*(num) + *(num) //testing operator_*
res6: Int = 16
Of course you can have that in Scala, if you really want:
import scalaz._
import Scalaz._
case class IncLens[S,N](lens: Lens[S,N], num : Numeric[N]) {
def ++ = lens.mods(num.plus(_, num.one))
}
implicit def incLens[S,N:Numeric](lens: Lens[S,N]) =
IncLens[S,N](lens, implicitly[Numeric[N]])
val i = Lens[Int,Int](identity, (x, y) => y)
val imperativeProgram = for {
_ <- i := 0;
_ <- i++;
_ <- i++;
x <- i++
} yield x
def runProgram = imperativeProgram ! 0
And here you go:
scala> runProgram
runProgram: Int = 3
It isn't included because Scala developers thought it make the specification more complex while achieving only negligible benefits and because Scala doesn't have operators at all.
You could write your own one like this:
class PlusPlusInt(i: Int){
def ++ = i+1
}
implicit def int2PlusPlusInt(i: Int) = new PlusPlusInt(i)
val a = 5++
// a is 6
But I'm sure you will get into some trouble with precedence not working as you expect. Additionally if i++ would be added, people would ask for ++i too, which doesn't really fit into Scala's syntax.
Lets define a var:
var i = 0
++i is already short enough:
{i+=1;i}
Now i++ can look like this:
i(i+=1)
To use above syntax, define somewhere inside a package object, and then import:
class IntPostOp(val i: Int) { def apply(op: Unit) = { op; i } }
implicit def int2IntPostOp(i: Int): IntPostOp = new IntPostOp(i)
Operators chaining is also possible:
i(i+=1)(i%=array.size)(i&=3)
The above example is similar to this Java (C++?) code:
i=(i=i++ %array.length)&3;
The style could depend, of course.