How much code does the body of an anonymous Scala function with "_" (underscore) comprise? - scala

In Scala, if you have an expression containing an underscore, this is an anonymous function with the expression as its body and the underscore as as its parameter, e.g. 2*_ is the anonymous function that doubles its argument. But how far does the function body extend? I'm missing a clear rule here that disambiguates cases like e.g. the following (tested with the Scala 2.11.7 REPL):
scala> (_: Int)+2-1 // function body up to 1 - OK
res7: Int => Int = <function1>
scala> ((_: Int)+2)-1 // function body up to 2, - applied to function is an error
<console>:11: error: value - is not a member of Int => Int
((_: Int)+2)-1
^

The definition is given in http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#placeholder-syntax-for-anonymous-functions, and it's... not that simple.
An expression e of syntactic category Expr binds an underscore section u, if the following two conditions hold: (1) e properly contains u, and (2) there is no other expression of syntactic category Expr which is properly contained in e and which itself properly contains u.
If an expression e binds underscore sections u_1 , \ldots , u_n, in this order, it is equivalent to the anonymous function (u'_1, ... u'_n) => e' where each u_i' results from u_i by replacing the underscore with a fresh identifier and e' results from e by replacing each underscore section u_i by u_i'.
And if you look at the grammar in the beginning of the section, (_: Int)+2 in (_: Int)+2-1 is not an Expr, but in ((_: Int)+2)-1 it is.

((_: Int)+2)-1 // function body up to 2, - applied to function is an error
error: value - is not a member of Int => Int
((_: Int)+2)-1
The error message from the compiler is sensible. Your additional parens have created a function literal that adds '2' to a wildcard/placeholder parameter. The compiler reads your code to mean that you have a this function value and you are trying to subtract '1' from it.
And this doesn't make sense. You can subract '1' from other numbers, but certainly not a function value. Thus, the compiler is telling you that it doesn't make sense to subtract one from a function value. Or, in compiler terms, a function of type Int => Int doesn't have a '-' function.
value - is not a member of Int => Int
Understanding this error message requires that you know that all operators in Scala ( -, *, +, etc ) are implemented as methods of types. If you look at the Scala API docs for Int, you'll see that it defines a long list of methods with common mathematical and logical operator symbols as function names.

Related

Can wildcard anonymous functions be used when parameters are repeating in the result expression?

Find Square of an integer 'x'.
Without Placeholder
var square = (x:Int) => x*x
square(3) gives desired output 9.
With Placeholder var square = (_:Int)*(_:Int)
square(3) gives Error
Not enough arguments for method apply: (v1: Int, v2: Int)Int in trait Function2.
Unspecified value parameter v2.
Internally what is happening?
No, each occurrence of _ represents the next argument in the argument list for the function.
(_:Int)*(_:Int) is a function that takes two Int arguments and multiplies them.

Apache-Spark : What is map(_._2) shorthand for?

I read a project's source code, found:
val sampleMBR = inputMBR.map(_._2).sample
inputMBR is a tuple.
the function map's definition is :
map[U classTag](f:T=>U):RDD[U]
it seems that map(_._2) is the shorthand for map(x => (x._2)).
Anyone can tell me rules of those shorthand ?
The _ syntax can be a bit confusing. When _ is used on its own it represents an argument in the anonymous function. So if we working on pairs:
map(_._2 + _._2) would be shorthand for map(x, y => x._2 + y._2). When _ is used as part of a function name (or value name) it has no special meaning. In this case x._2 returns the second element of a tuple (assuming x is a tuple).
collection.map(_._2) emits a second component of the tuple. Example from pure Scala (Spark RDDs work the same way):
scala> val zipped = (1 to 10).zip('a' to 'j')
zipped: scala.collection.immutable.IndexedSeq[(Int, Char)] = Vector((1,a), (2,b), (3,c), (4,d), (5,e), (6,f), (7,g), (8,h), (9,i), (10,j))
scala> val justLetters = zipped.map(_._2)
justLetters: scala.collection.immutable.IndexedSeq[Char] = Vector(a, b, c, d, e, f, g, h, i, j)
Two underscores in '_._2' are different.
First '_' is for placeholder of anonymous function; Second '_2' is member of case class Tuple.
Something like:
case class Tuple3 (_1: T1, _2: T2, _3: T3)
{...}
I have found the solutions.
First the underscore here is as placeholder.
To make a function literal even more concise, you can use underscores
as placeholders for one or more parameters, so long as each parameter
appears only one time within the function literal.
See more about underscore in Scala at What are all the uses of an underscore in Scala?.
The first '_' is referring what is mapped to and since what is mapped to is a tuple you might call any function within the tuple and one of the method is '_2' so what below tells us transform input into it's second attribute.

Currying in scala

w.r.t Currying in scala, partly I understood below sample code.
def product1(f:Int => Int )(a:Int, b:Int):Int = {
println()
if(a > b ) 1
else
f(a) * product1(f)(a+1, b)
}
product(x => x * x) (3, 4)
Out of it., I am bit confused with
product1(f)
in
product1(f)(a+1, b)
Just need explanation, what goes on here.... :( and how to pronounce verbally while explaining...
Thanks in advance..
product1 has two parameter lists. product1(f) is the application of f which is a function of kind Int => Int. If you were only to call product1(f) like so:
product1(f)
without the second parameter list, you'd get a so-called partially-applied function, i.e. a function which doesn't have all of its parameters bound (you'd still need to provide it with a and b)
Look at the parameter declaration:
f:Int => Int
f is a function that maps an Int to an Int -- it takes an Int as an argument and returns an Int. An example is given:
x => x * x
returns the square of its argument.
product1(x => x * x) (3, 4)
returns the product of f(3) .. f(4) = 3*3 * 4*4
BTW, this isn't really an example of currying, since all the arguments are given. Currying would be something like
val prodSquare = product1(x => x * x)
Then,
prodSquare(1, 5)
yields 1*1 * 2*2 * 3*3 * 4*4 * 5*5
For most idiomatic purposes I've seen, you may as well think of your function as having just one parameter list. Multiple parameter lists are used mostly for type inference purposes in generic functions, since type inference is done one parameter list at a time, rather than using Hindley-Milner/Algorithm W to infer the type of everything at once. Some other language features work on individual parameter lists, such as implicit parameters and implicit use of braces in place of parentheses for single-parameter parameter lists, etc.
Functions with multiple parameter lists are called in a similar way to a curried functions from a syntactic perspective, but by default, the intermediate functions aren't created. In fully curried style, each function takes only at most one argument and returns one result (which might happen to be another function, which expects on argument, and so forth). Technically, currying the function would be:
def product2(f: Int => Int): Int => Int => Int = {
a: Int => {
b: Int => {
if(a > b ) 1
else f(a) * product2(f)(a+1)(b)
}
}
}
For completeness, you can treat a function with multiple parameter lists as a curried function by using an underscore after a complete parameter list. In your original example, you'd do product1(f)_, which would return a function of type (Int, Int) => Int.
In researching this question, I came upon another SO question worth checking out to understand this aspect of the language better.

Function literal - Need help in understanding a code snippet

I'm basically new to functional programming and scala, and the following question might possibly look stupid.
val f = (a:Int) => a+1
In the above snippet, should I consider f to be a function or a variable? Coming from a C/C++ background, the first thought that occurs is that f is a variable that stores the return value of the anonymous function, but I think that's not the correct way to interpret it Any explanation would be really helpful.
(Some of the terminologies I used above might be wrong with respect to scala/functional programming, kindly bear with it)
Here, f is a variable that stores a function. It's really no different from saying any of the following:
val a = 4 // `a` is a variable storing an Int
val b = "hi" // `b` is a variable storing a String
val f = (a:Int) => a+1 // `f` is a variable storing a function
You can also confirm this with the REPL:
scala> val f = (a:Int) => a+1
f: Int => Int = <function1>
So this is telling you that f has the type Int => Int. Or in other words, f is a function that takes one argument, an Int, and returns an Int.
Since f is a variable, you can call methods on it or pass it as an argument to functions that expect its type:
a + 3 // here I'm calling the `+` method on `a`, which is an Int
f(3) // here I'm calling the `apply` method on `f`, which is a function `Int => Int`
f(a) // the function `f` expects an `Int`, which `a` is
(1 to 3).map(f) // the `map` method expects a function from Int to Int, like `f`
Yes, like dhg said, f is a variable (that can't be changed) that stores a function.
However, there's a subtlety here:
... the first thought that occurs is that f is a variable that stores the
return value of the anonymous function
f actually stores the function, not the result. So you can give it different inputs, and get different outputs. So, you can use it like f(7) and then f(5). Functions in Scala are objects, so can be assigned to variables, passed as parameters, etc.
I recently posted about function literals, which may be helpful to you.
f is a value denoting a function literal.
In the statement, the right-hand-side is a function literal. The left-hand-side binds it to a name which is then called value (the val keyword is similar to let in LISP). Now the function is associated with the symbol f, so you can refer to that function by using this symbol f.
I disagree with the other answers which suggest that f should be called a variable. f is a value, because it is fixed to the right-hand-side term which is determined only once and cannot change. On the contrary a variable, introduced with var, allows you to re-assign values to a symbol:
var f = (i: Int) => i + 1
Where var begins a variable definition, f is the name or symbol of the variable, there could be an optional : ... defining type of the variable (if you leave that out, the type is automatically inferred from the assignment), and = ... defines the value initially assigned to the variable.
So when one says value, don't confuse this with a numeric constant, it is simply an entity that doesn't change. A function can be a value too, because f then always denotes this same identical function, even if you can feed that function with different arguments which yield different results.
Now with the var you can re-assign its right-hand-side:
f(2) // --> 3
f = (i: Int) => i * 2 // assign a new function to the variable f.
f(2) // --> 4
Functional programming is all about avoiding variables (re-assignments).
It is also possible to define a function without assigning it at all (to a value or a variable). The following defines such a function and immediately calls it with argument 4:
{ i: Int => i + 1 } apply 4 // --> 5
although that is seldom useful as a statement per se, but you will see 'plain' functions often when calling a method that expects a function argument. For instance
val s = List(1, 2, 3)
s.map { (i: Int) => i + 1 } // --> List(2, 3, 4)
s.map { _ + 1 } // equivalent
s.map( _ + 1 ) // equivalent

Questions about placeholders in Scala

Consider the following definition in Scala:
val f = ((_: Int) + 1).toString()
The code assigns to f the string representation of the function literal _ + 1, which is quite natural, except that this is not i want. i intended to define a function that accepts an int argument, increments it by 1, and returns its string format.
To disambiguate, i have to write a lambda expression with explicit parameters:
val g = (x: Int) => (x + 1).toString()
So can i conclude that the placeholder syntax is not suitable for complex function literals?
Or is there some rule that states the scope of the function literal? It seems placeholders cannot be nested in parentheses(except the ones needed for defining its type) within the function literal
Yes, you are right in thinking that placeholder syntax is not useful beyond simple function literals.
For what it's worth, the particular case you mentioned can be written with a conjunction of placeholder syntax and function composition.
scala> val f = ((_: Int) + 1) andThen (_.toString)
f: Int => java.lang.String = <function1>
scala> f(34)
res14: java.lang.String = 35
It seems placeholders cannot be nested in parentheses(except the ones needed for defining its type) within the function literal
This is correct. See the rules for the placeholder syntax and a use case example.