scala > val a = (x:Int)=>x+1
res0: Int => Int = <function1>
scala > val b = a.getClass
b: Class[_ <: Int => Int] = class $anonfun$1
scala > b.getName.replaceFirst("^.*\\.", "") + ".class"
//Why there is a prefix '$read$'
res2: String = $read$$anonfun$1.class
I'm confusing about the res2. I think the res2 should be '$anonfun$1.class'.
This one was fun.
scala> val a = ((x: Int) => x).getClass.getName
a: String = $anonfun$1
scala> a == "$anonfun$1"
res2: Boolean = false
Wait, what?
scala> a.getBytes.map(_.toChar)
res3: Array[Char] = Array($, l, i, n, e, 4, ., $, r, e, a, d, $, $, i, w, $, $, i, w, $, $, a, n, o, n, f, u, n, $, 1)
So the name of the class is actually $line4.$read$$iw$$iw$$anonfun$1, not $anonfun$1. But why does Scala REPL print it like this? All executable Scala code must be inside a class, trait, or object definition. So when you enter a line in REPL which isn't, it gets wrapped inside an object. And apparently when printing an answer, REPL suppresses anything which looks like part of this object's generated name, even if it isn't where it comes from:
scala> "a$$iw$$b"
res7: String = a$$b
And $line4.$read$ qualifies for this suppression, but $read$ by itself doesn't.
Related
I came from What is the formal difference in Scala between braces and parentheses, and when should they be used?
, so still I am not clear understand the scala method call syntax trick. I think the lcn's answer in the link is clear but what does these mean:
val r = List(1, 2, 3).foldLeft(0) _+_ //r: String => String = $Lambda$1642/1200068083#562c1af9
val l = r{"hello"} //l: String = $Lambda$1643/1458648440#23ae6386hello
why r is a function? and call it return another function l and can not call l?
are there some official doc for method call in () and {}?
This has to do with operator precedence:
val r = List(1, 2, 3).foldLeft(0) _+_
Is equivalent to:
val r = (List(1, 2, 3).foldLeft(0) _) + _
Which means - we take the partially applied foldLeft function, List(1, 2, 3).foldLeft(0) _, which has the type ((Int, Int) => Int) => Int), and we call + _ on it.
Now - Scala compiler tries to figure out what the + operator should mean for a Function, and since Function does not define such an operator, it does the best it can to find a suitable implicit conversion, and finds that indeed the Function can be converted to a String using its toString method, so that the + _ means "a new anonymous function that appends any input String passed to the String representation of the List(1, 2, 3).foldLeft(0) _ function".
So we end up with a String => String function, that appends the input to the toString result of the function List(1, 2, 3).foldLeft(0) _, which is "<function1>":
scala> val r = List(1, 2, 3).foldLeft(0) _ + _
r: String => String = <function1>
scala> r("a")
res5: String = <function1>a
scala> r(" bbbb")
res6: String = <function1> bbbb
I tried to make my own map method in Scala and this is the result:
def map[A, B](f: A => B)(as: List[A]): List[B] =
for (i <- as) yield f(i)
And if I try to convert a List[Int] to a List[String]:
val list = List(1, 2, 3, 4, 5) //> list : List[Int] = List(1, 2, 3, 4, 5)
map(toString()) (list) //> res0: List[Char] = List(e, b, u, n, g)
I get the same result if I try:
list.map(toString()) //> res1: List[Char] = List(e, b, u, n, g)
My Question: Why gives toString() not a List("1","2"...)?
You're calling toString() on the current object (which apparently returns something like "?ebung...") and passing the resulting string as an argument to map.
So you might expect that to produce a type error because map expects a function, but you're passing a string. However strings count as functions too (because RichString implements the Function1[Int, Char] trait) that take an integer and return the character at that index. So that's why you get a list containing those characters.
To do what you meant to do (create a function that calls toString on its argument), you can either use x => x.toString or _.toString for short.
I've encountered a strange question on scala String split
here is my code:
scala> val s1 = "oauth_token=FOO&oauth_token_secret=BAR&oauth_expires_in=3600"
s1: String = oauth_token=FOO&oauth_token_secret=BAR&oauth_expires_in=3600
scala> s1.split("&")
res3: Array[String] = Array(oauth_token=FOO, oauth_token_secret=BAR, oauth_expires_in=3600)
so far, the split method works well, but..
scala> val s2 = "oauth_token=FOO|oauth_token_secret=BAR|oauth_expires_in=3600"
s2: String = oauth_token=FOO|oauth_token_secret=BAR|oauth_expires_in=3600
scala> s2.split("|")
res4: Array[String] = Array("", o, a, u, t, h, _, t, o, k, e, n, =, F, O, O, |, o, a, u, t, h, _, t, o, k, e, n, _, s, e, c, r, e, t, =, B, A, R, |, o, a, u, t, h, _, e, x, p, i, r, e, s, _, i, n, =, 3, 6, 0, 0)
the method actually splits out every character, even strangely, an empty string appears at the front.
I have tried other delimiters such as %, ,, the method still works well. It seems that split does not work correctly when | serve as delimiter?
split() expects a regular expression, and in regex-land | means "OR", so you're splitting on the empty string OR on the empty string, which is what you're seeing.
You can use an escape to split on literal |s:
scala> val s2 = "oauth_token=FOO|oauth_token_secret=BAR|oauth_expires_in=3600"
s2: String = oauth_token=FOO|oauth_token_secret=BAR|oauth_expires_in=3600
scala> s2.split("\\|")
res0: Array[String] = Array(oauth_token=FOO, oauth_token_secret=BAR, oauth_expires_in=3600)
Scala has an implicit conversion which provides split() method on strings that accepts char:
scala> val s2 = "oauth_token=FOO|oauth_token_secret=BAR|oauth_expires_in=3600"
s2: String = oauth_token=FOO|oauth_token_secret=BAR|oauth_expires_in=3600
scala> s2.split('|')
res0: Array[String] = Array(oauth_token=FOO, oauth_token_secret=BAR, oauth_expires_in=3600)
Naturally, this only works if your splitter is a single character. If it is a multi-character string, you need to keep track of regex-specific characters yourself.
Is the following a good example of currying?
def sum(a: Int, b: Int) : (Int => Int) = {
def go(a: Int) : Int = {
a + b;
}
go
}
I half understand the below results, but how could I write (or maybe how I should've written) sum() in a curried way?
scala> sum(3,4) res0: Int => Int = <function1>
scala> sum(3,4).apply(2) res1: Int = 6
scala> sum(3,4).apply(3) res2: Int = 7
Currying mechanism was introduced in Scala to support type inference. For example foldLeft function in the standard lib:
def foldLeft[B](z: B)(op: (B, A) => B): B
Without currying you must provide types explicitly:
def foldLeft[B](z: B, op: (B, A) => B): B
List("").foldLeft(0, (b: Int, a: String) => a + b.length)
List("").foldLeft[Int](0, _ + _.length)
There are three ways to write a curried function:
1) Write it in currying form:
def sum(a: Int)(b: Int) = a + b
which is just syntactic sugar for:
def sum(a: Int): Int => Int = b => a + b
2) Call curried on the function object (sum _).curried and check the types:
sum: (a: Int, b: Int)Int
res10: Int => (Int => Int) = <function1>
In your example, you can use Scala type inference to reduce the amount of code and change your code:
def sum(a: Int, b: Int) : (Int => Int) = {
def go(a: Int) : Int = {
a + b;
}
go
}
into:
def sum(a: Int, b: Int) : (Int => Int) = c => a + b + c
semantically these are the same, because you explicitly provided the return type, so Scala knows that you will return a function wich takes an Int argument and return an Int
Also a more complete answer about curring was given by retronym
In the lambda calculus, you have something called a lambda abstraction λx.term1 which when applied to another term (λx.term1)(term2), corresponds to the concept of applying a function to term2. The lambda calculus is the theoritical basis for functional programming. In lambda calculus, you don't have lambda abstraction taking multiple parameters. So how you do you represent functions of two arguments? The answer is to return a function that will take the other argument and then return the result on both argument.
So in Scala, if you have a var a in scope, you can return a function that will add its argument b to a:
scala> var a = 1
a: Int = 1
scala> val adda = (b: Int) => a + b
adda: Int => Int = <function1>
scala> adda(3)
res1: Int = 4
Now if you have an argument a in scope it works just as well:
scala> val sum = (a: Int) => (b: Int) => a + b
sum: Int => Int => Int = <function1>
scala> sum(3)(5)
res2: Int = 8
So without having access to a syntax that lets you define a function of two arguments, you just basically achieve that with a function sum taking an argument a returning a function equivalent to adda that takes a argument b and returns a + b. And that's called currying.
As an exercise, define a function using currying that will let you work on 3 arguments. For instance val sum3: Int => Int => Int => Int = ???, and fill in what goes into the question marks.
Disclaimer: I'm pretty new to Scala, so treat this with a grain of salt
In purely functional languages like Haskell currying plays very important role in function composition, e.g. if I want to find sum of squares I would write in Haskell (sorry for too much Haskell, but syntax has similarities with Scala and it's not that hard to guess)
without currying:
sum_of_squares xs = foldl (\x y -> x + y) 0 (map (\x -> x * x) xs)
with curring (. is a function composition):
sum_of_squares = (foldl (\x y -> x + y) 0) . (map (\x -> x * x))
which allows me to operate with functions instead of operating with arguments. It may not be that clear from previous example, but consider this:
sum_of_anything f = (foldl (\x y -> x + y) 0) . (map f)
here f is an arbitrary function and I can rewrite the first example as:
sum_of_squares = sum_of_anything (\x -> x * x)
Now let's go back to Scala. Scala is OO language, so usually xs will be a receiver:
def sum_of_squares(xs: List[Int]): Int = {
xs.map(x => x * x).foldLeft(0)((x, y) => x + y)
}
sum_of_squares(List(1,2,3))
def sum_of_anything(f: (Int, Int) => Int)(xs: List[Int]): Int = {
xs.map(x => x * x).foldLeft(0)(f)
}
sum_of_anything((x, y) => x + y)(List(1, 2, 3))
which means I can't omit xs. I can probably rewrite it with lambdas, but I won't be able to use map and foldLeft without adding more boilerplate. So as other people mentioned in Scala "currying" is probably mostly used to support type inference.
Meanwhile in your particular example I have a feeling that you don't need outer a, it's shadowed anyway, you probably meant:
def sum(b: Int) : (Int => Int) = {
def go(a: Int) : Int = {
a + b;
}
go
}
But in this simple example you can use partial application (given that you will probably pass sum to higher order functions):
List(1, 2, 3).map(sum(2)) //> res0: List[Int] = List(3, 4, 5)
List(1, 2, 3).map(_ + 2) //> res1: List[Int] = List(3, 4, 5)
For this kind of application sum can be shorter because sum(2) will be implicitly expanded to Int => Int:
def sum(b: Int)(a: Int): Int = a + b
This form is not valid for val sum2 = sum(2) though, you will have to write val sum2 = sum(2) _.
Scalaz provides a method named fold for various ADTs such as Boolean, Option[_], Validation[_, _], Either[_, _] etc. This method basically takes functions corresponding to all possible cases for that given ADT. In other words, a pattern match shown below:
x match {
case Case1(a, b, c) => f(a, b, c)
case Case2(a, b) => g(a, b)
.
.
case CaseN => z
}
is equivalent to:
x.fold(f, g, ..., z)
Some examples:
scala> (9 == 8).fold("foo", "bar")
res0: java.lang.String = bar
scala> 5.some.fold(2 *, 2)
res1: Int = 10
scala> 5.left[String].fold(2 +, "[" +)
res2: Any = 7
scala> 5.fail[String].fold(2 +, "[" +)
res6: Any = 7
At the same time, there is an operation with the same name for the Traversable[_] types, which traverses over the collection performing certain operation on its elements, and accumulating the result value. For example,
scala> List(2, 90, 11).foldLeft("Contents: ")(_ + _.toString + " ")
res9: java.lang.String = "Contents: 2 90 11 "
scala> List(2, 90, 11).fold(0)(_ + _)
res10: Int = 103
scala> List(2, 90, 11).fold(1)(_ * _)
res11: Int = 1980
Why are these two operations identified with the same name - fold/catamorphism? I fail to see any similarities/relation between the two. What am I missing?
I think the problem you are having is that you see these things based on their implementation, not their types. Consider this simple representation of types:
List[A] = Nil
| Cons head: A tail: List[A]
Option[A] = None
| Some el: A
Now, let's consider Option's fold:
fold[B] = (noneCase: => B, someCase: A => B) => B
So, on Option, it reduces every possible case to some value in B, and return that. Now, let's see the same thing for List:
fold[B] = (nilCase: => B, consCase: (A, List[A]) => B) => B
Note, however, that we have a recursive call there, on List[A]. We have to fold that somehow, but we know fold[B] on a List[A] will always return B, so we can rewrite it like this:
fold[B] = (nilCase: => B, consCase: (A, B) => B) => B
In other words, we replaced List[A] by B, because folding it will always return a B, given the type signature of fold. Now, let's see Scala's (use case) type signature for foldRight:
foldRight[B](z: B)(f: (A, B) ⇒ B): B
Say, does that remind you of something?
If you think of "folding" as "condensing all the values in a container through an operation, with a seed value", and you think of an Option as a container that can can have at most one value, then this starts to make sense.
In fact, foldLeft has the same signature and gives you exactly the same results if you use it on an empty list vs None, and on a list with only one element vs Some:
scala> val opt : Option[Int] = Some(10)
opt: Option[Int] = Some(10)
scala> val lst : List[Int] = List(10)
lst: List[Int] = List(10)
scala> opt.foldLeft(1)((a, b) => a + b)
res11: Int = 11
scala> lst.foldLeft(1)((a, b) => a + b)
res12: Int = 11
fold is also defined on both List and Option in the Scala standard library, with the same signature (I believe they both inherit it from a trait, in fact). And again, you get the same results on a singleton list as on Some:
scala> opt.fold(1)((a, b) => a * b)
res25: Int = 10
scala> lst.fold(1)((a, b) => a * b)
res26: Int = 10
I'm not 100% sure about the fold from Scalaz on Option/Either/etc, you raise a good point there. It seems to have quite a different signature and operation from the "folding" I'm used to.