given:
val m = Map[String, Int]("a" -> 1, "b" -> 2, "c" -> 3)
m.foreach((key: String, value: Int) => println(">>> key=" + key + ", value=" + value))
why does the compiler complain
error: type mismatch
found : (String, Int) => Unit
required: (String, Int) => ?
I'm not sure about the error, but you can achieve what you want as follows:
m.foreach(p => println(">>> key=" + p._1 + ", value=" + p._2))
That is, foreach takes a function that takes a pair and returns Unit, not a function that takes two arguments: here, p has type (String, Int).
Another way to write it is:
m.foreach { case (key, value) => println(">>> key=" + key + ", value=" + value) }
In this case, the { case ... } block is a partial function.
oops, read the doco wrong, map.foreach expects a function literal with a tuple argument!
so
m.foreach((e: (String, Int)) => println(e._1 + "=" + e._2))
works
You need to patter-match on the Tuple2 argument to assign variables to its subparts key, value. You can do with very few changes:
m.foreach{ case (key: String, value: Int) => println(">>> key=" + key + ", value=" + value)}
The confusing error message is a compiler bug, which should be fixed in 2.9.2:
Excellent question!
Even when explicitly typing the foreach method, it still gives that very unclear compile error. There are ways around it, but I can't understand why this example does not work.
scala> m.foreach[Unit] {(key: String, value: Int) => println(">>> key=" + key + ", value=" + value)}
<console>:16: error: type mismatch;
found : (String, Int) => Unit
required: (String, Int) => Unit
m.foreach[Unit] {(key: String, value: Int) => println(">>> key=" + key + ", value=" + value)}
^
Docs says argument is tuple -> unit, so We can easily do this
Map(1 -> 1, 2 -> 2).foreach(tuple => println(tuple._1 +" " + tuple._2)))
Yet another way:
Map(1 -> 1, 2 -> 2).foreach(((x: Int, y: Int) => ???).tupled)
However it requires explicit type annotations, so I prefer partial functions.
Related
I'm getting problems to understand the currying concept, or at least the SCALA currying notation.
wikipedia says that currying is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions, each with a single argument.
Following this explanation, are the two next lines the same for scala?
def addCurr(a: String)(b: String): String = {a + " " + b}
def add(a:String): String => String = {b => a + " " + b}
I've run both lines with the same strings a and b getting the same result, but I don't know if they are different under the hood
My way of thinking about addCurr (and currying itself) is that it is a function that receives a string parameter a, and returns another function that also receives a string parameter b and returns the string a + " " + b?
So if I'm getting right, addCurr is only syntactic sugar of the function add and both are curryed functions?
According to the previous example, the next functions are also equivalent for scala?
def add(a: String)(b: String)(c: String):String = { a + " " + b + " " + c}
def add1(a: String)(b: String): String => String = {c => a + " " + b + " " + c}
def add2(a:String): (String => (String => String)) = {b => (c => a + " " + b + " " + c)}
They have a bit different semantics, but their use-cases are mostly the same, both practically and how it looks in the code.
Currying
Currying a function in Scala in that mathematical sense is a very straightforward:
val function = (x: Int, y: Int, z: Int) => 0
// function: (Int, Int, Int) => Int = <function3>
function.curried
// res0: Int => (Int => (Int => Int)) = <function1>
Functions & methods
You seem to be confused by the fact that in Scala, (=>) functions are not the same as (def) methods. Method isn't a first-class object, while function is (i.e. it has curried and tupled methods, and Function1 has even more goodness).
Methods, however, can be lifted to functions by an operation known as eta expansion. See this SO answer for some details. You can trigger it manually by writing methodName _, or it will be done implicitly if you give a method to where a function type is expected.
def sumAndAdd4(i: Int, j: Int) = i + j + 4
// sumAndAdd4.curried // <- won't compile
val asFunction = sumAndAdd4 _ // trigger eta expansion
// asFunction: (Int, Int) => Int = <function2>
val asFunction2: (Int, Int) => Int = sumAndAdd4
// asFunction2: (Int, Int) => Int = <function2>
val asFunction3 = sumAndAdd4: (Int, Int) => Int
// asFunction3: (Int, Int) => Int = <function2>
asFunction.curried
// res0: Int => (Int => Int) = <function1>
asFunction2.curried
// res1: Int => (Int => Int) = <function1>
asFunction3.curried
// res2: Int => (Int => Int) = <function1>
{sumAndAdd4 _}.tupled // you can do it inline too
// res3: Int => (Int => Int) = <function1>
Eta expansion of multiple parameter list
Like you might expect, eta expansion lifts every parameter list to its own function
def singleArgumentList(x: Int, y: Int) = x + y
def twoArgumentLists(x: Int)(y: Int) = x + y
singleArgumentList _ // (Int, Int) => Int
twoArgumentLists _ // Int => (Int => Int) - curried!
val testSubject = List(1, 2, 3)
testSubject.reduce(singleArgumentList) // Int (6)
testSubject.map(twoArgumentLists) // List[Int => Int]
// testSubject.map(singleArgumentList) // does not compile, map needs Int => A
// testSubject.reduce(twoArgumentLists) // does not compile, reduce needs (Int, Int) => Int
But it's not that currying in mathematical sense:
def hmm(i: Int, j: Int)(s: String, t: String) = s"$i, $j; $s - $t"
{hmm _} // (Int, Int) => (String, String) => String
Here, we get a function of two arguments, returning another function of two arguments.
And it's not that straightforward to specify only some of its argume
val function = hmm(5, 6) _ // <- still need that underscore!
Where as with functions, you get back a function without any fuss:
val alreadyFunction = (i: Int, j: Int) => (k: Int) => i + j + k
val f = alreadyFunction(4, 5) // Int => Int
Do which way you like it - Scala is fairly un-opinionated about many things. I prefer multiple parameter lists, personally, because more often than not I'll need to partially apply a function and then pass it somewhere, where the remaining parameters will be given, so I don't need to explicitly do eta-expansion, and I get to enjoy a terser syntax at method definition site.
Curried methods are syntactic sugar, you were right about this part. But this syntactic sugar is a bit different. Consider following example:
def addCur(a: String)(b: String): String = { a + b }
def add(a: String): String => String = { b => a + b }
val functionFirst: String => String = add("34")
val functionFirst2 = add("34")_
val functionSecond: String => String = add("34")
Generaly speaking curried methods allows for partial application and are necessary for the scala implicits mechanism to work. In the example above i provided examples of usage, as you can see in the second one we have to use underscore sign to allow compiler to do the "trick". If it was not present you would receive error similar to the following one:
Error:(75, 19) missing argument list for method curried in object XXX
Unapplied methods are only converted to functions when a function type
is expected. You can make this conversion explicit by writing curried_ or curried(_)(_) instead of curried.
Your question interested me so I tried this out my self. They actually desugar down to some very different constructs. Using
def addCurr(a: String)(b: String): String = {a + " " + b}
This actually compiles to
def addCurr(a: String, b: String): String = {a + " " + b}
So it completely removes any currying effect, making it a regular arity-2 method. Eta expansion is used to allow you to curry it.
def add(a:String): String => String = {b => a + " " + b}
This one works as you would expect, compiling to a method that returns a Function1[String,String]
I´m trying to convert a Map[String, Any] which Any contains as well sometimes a Map[String, Any] and so on, into Json String format.
I´ve found this external library http://json4s.org/ but amaze me that Scala core does not contain a native library to achieve this.
Any idea?
Regards.
Scala has not built-in feature, but it has amazing sintax... Here you have it, in 8 idiomatic lines:
def toJson(query: Any): String = query match {
case m: Map[String, Any] => s"{${m.map(toJson(_)).mkString(",")}}"
case t: (String, Any) => s""""${t._1}":${toJson(t._2)}"""
case ss: Seq[Any] => s"""[${ss.map(toJson(_)).mkString(",")}]"""
case s: String => s""""$s""""
case null => "null"
case _ => query.toString
}
Well JSON is an interchange format (albeit a popular one at present), but then so is XML etc etc. The core library arguably shouldn't concern itself with dealing with a long list of data formats - at least this is what I understand is the reason around limiting such support in Scala core, as in other languages.
There are quite a few libraries that will help you achieve this.
I currently use Argonaut for all things JSON in Scala projects, unless I am using Play, in which case it also provides pretty good JSON support. Have a look at Argonaut, you can achieve what you want to quite easily with it.
As far as I understood i thought that you are using your custom implementation for Json which is: Map[String, Any]
So here is custom implementation of function that will return String of your map
def show(json: Map[String, Any]) : String = {
def parse(elem: (String, Any)): String = elem match {
case (a: String, b: Map[String, _]) => "\"" + a + "\"" + ":" + show(b) + ""
case (a: String, b: Boolean) => "\"" + a + "\"" + ":" + b.toString
case (a: String, b: Int) => "\"" + a + "\"" + ":" + b.toString
case (a: String, b: Double) => "\"" + a + "\"" + ":" + b.toString
case (a: String, b: String) => "\"" + a + "\"" + ":\"" + b + "\""
}
val assocs = json.map {
case(key, value) => parse((key,value))
}
"{\n" + assocs.mkString(", \n")+ "}"
}
for such Map:
val mapJson = Map("root" ->
Map("field1" -> 1,
"field2" -> Map("field1" -> true,
"field2" -> 2.03),
"field3" -> "Test"))
it will print:
String = {
"root":{
"field1":1,
"field2":{
"field1":true,
"field2":2.03},
"field3":"Test"}}
I'm trying to pass a tuple as an argument to function. Unfortunately i can't do this. Can you give me some tips?
val t = Tuple3(3, "abc", 5.5);
def fun(x: (Int, String, Double) = {
x.productIterator.foreach(i => println("Value: " + i));
}
def(t);
There's a missing closing parenthese and you called def(t) instead of fun(t). Note that you don't need to indicate the constructor Tuple3 :
val t = (3, "abc", 5.5);
def fun(x: (Int, String, Double)) = {
x.productIterator.foreach(i => println("Value: " + i));
}
fun(t);
You are missing a bracket after your method declaration. Also you need to run using fun(t).
val t = Tuple3(3, "abc", 5.5)
def fun(x: (Int, String, Double)) = {
x.productIterator.foreach(i => println("Value: " + i))
}
fun(t)
Given the function type alias:
type Func = (Int, Double) => String
and I want to define one such function, one way of doing it would be
val foo: Func = (n: Int, d: Double) => n.toString + " " + d.toString
However I am trying to understand if there is a less verbose way akin to accessing a tuple, without naming the arguments explicitly again when the type is known, such as (hypothetically)
val foo: Func = _1.toString + " " + _2.toString
Is there anything at all that accomplishes this? It would save me an immense amount of typing and would make my code much more readable.
You can always use ordinary shorthand notation which iterates through the parameters in order:
val foo: Func = _ + " " + _
If that is not general enough, you need only name the parameters, not supply their types again:
val foo: Func = (x,y) => (x + (x + y*y)).toString
Yep.
val foo: Func = _.toString + " " + _.toString
You have to realize that the arguments n and d don't form a Tuple, but are independent. To be a tuple, the type should have been ((Int, Double)) => String , note the additional parenthesis.
Compiler telling me "missing parameter type" on the p when I do this:
case class MapResult(input: Any, output: Map[_ <: Any, Any]) {
override def toString = output.map(p => input + " " + p._1 + " " + p._2 ).mkString("\n")
}
Then it tells me
identifier expected but string literal found.
[error] override def toString = output.map(p: (Any, Any) => input + " " + p._1 + " " + p._2 ).mkString("\n")
^
for the below:
case class MapResult(input: Any, output: Map[_ <: Any, Any]) {
override def toString = output.map(p: (Any, Any) => input + " " + p._1 + " " + p._2 ).mkString("\n")
}
As soon as you specify the type parameter types in a function literal, you need to use curly braces instead of parentheses:
case class MapResult(input: Any, output: Map[_ <: Any, Any]) {
override def toString = output.map{p: (Any, Any) => input + " " + p._1 + " " + p._2 }.mkString("\n")
}
UPDATE: you could also wrap the parameter list in parentheses, which makes the parser happy even without curly braces:
case class MapResult(input: Any, output: Map[_ <: Any, Any]) {
override def toString = output.map( (p: (Any, Any)) => input + " " + p._1 + " " + p._2 ).mkString("\n")
}
Here you could also use pattern matching:
case class MapResult(input: Any, output: Map[_ <: Any, Any]) {
override def toString = output.map{ case (k: Any, v: Any) => input + " " + k + " " + v }.mkString("\n")
}
As for the reason why the compiler forces you to specify the parameter type here, I honestly have no idea. I could not reproduce it in scala 2.10-RC1.