What is the difference between
def plusOne(n: Int) = n + 1
and
val plusOne = (n : Int) => n + 1
What the difference really comes down to is that the first is a "method", and the second is a "function", and in Scala these two things are surprisingly different.
You could see, for example, Difference between method and function in Scala.
Actually, both of them are functions.
The first one is a method or a local function, depending on where it is declared. The second one is a function value, which is an object instantiated at runtime. Methods, local functions, function values, and function literals are all flavors of functions in Scala.
See here for a chapter of Martin Odersky's book on this topic: http://www.artima.com/pins1ed/functions-and-closures.html
Related
I can use closure to define function like this:
def product(x: Int) = (y: Int) => x * y
val productBy3 = product(3)
println(productBy3(6)) // 18
OR, using currying:
def curriedProduct(x: Int)(y: Int) = x * y
val productBy3 = curriedProduct(3)_
println(productBy3(6)) // 18
Any advantage/disadvantage one approach has over other?
The first is an example of a method returning a function. The second is an example of a method with multiple parameter lists.
The way you use them, there is no difference.
When called as product(3)(6), the second may be a bit faster, but not to an extent that would normally be a concern.
I would use the first form when the expected way to call it would be with product(3), and use the second form if the normal way to call it would be product(3)(6).
Lastly, I'd like to suggest the possibility of
def product(i: Int, j: Int) = i * j
val productBy3 = product(3, _)
println(productBy3(6)) //18
I don't really see any upsides of using the second form instead of either this alternative or the first alternative in this situation. Using multiple parameter lists may help type inference in scala 2 (see https://docs.scala-lang.org/tour/multiple-parameter-lists.html), but there is no problematic inference here anyway.
I want to define a simple lambda, add up three integers:
(int a, int b,int c)->a+b+c
For this simple case, I have two options:
Define a functional interface. The single abstract method should be int add(int a, int b,int c), the method name and varable names don't matter.
Use method reference. I have to define a class/method or use an existing method that has the signature int add(int a, int b,int c)
In both cases, for the very simple lambda, I have to get back to the OOP world(interface, class, etc)
But in scala, it is very simple to define a function in place:
val add= (a:Int,b:Int,c:Int)=>a+b+c
In Java, you must target every lambda expression to a specific functional interface type. This is by design, and in practice it means that functions are not first-class citizens of the language.
So, yes, you have to get back to OOP world.
You can, however, use the Function built-in type to define your function in its currified form:
Function<Integer, Function<Integer, Function<Integer, Integer>>> add =
a -> b -> c -> a + b + c;
Usage:
int result = add.apply(1).apply(2).apply(3); // 6
Though I doubt this is readable at all...
Actually, defining a function in Scala works exactly the same as option 1, except 1) the functional interface scala.Function3[A1, A2, A3, B] is contained in the standard Scala library; 2) the compiler fakes supporting Int in generics (which ends up being converted to boxed java.lang.Integer.
You can't really do anything about 2) in Java, but 1) is solved trivially by using a library which defines Function3 and so on (or writing your own). There are http://www.functionaljava.org/, http://www.vavr.io/, https://mvnrepository.com/artifact/uk.org.potes.java8/java8-currying (which only has those interfaces and nothing more). Probably a few others.
Scala wins on type inference, of course, in two ways:
FunctionN is the "default" functional interface for lambda expressions, so it doesn't need to be specified.
If you specify arguments, return type can normally be inferred.
But these considerations matter more when assigning lambdas to a field or a variable, and less when passing them to a method, which is probably more common.
In your specific use case where the type of operation and operand is same both the time(a+b+c => a + (b+c)), you can make use of a BiFunction defined as:-
BiFunction<Integer, Integer, Integer> f = (x, y) -> x + y;
System.out.println(f.apply(a, f.apply(b, c))); // a + b + c
Or another alternate as suggested by #Igor would be to make use of would be to sum over an IntStream.
You’re looking for the following:
int sum = IntStream.of(a, b, c).sum();
I just wanted to clarify something about partially defined functions in Scala. I looked at the docs and it said the type of a partial function is PartialFunction[A,B], and I can define a partial function such as
val f: PartialFunction[Any, Int] = {...}
I was wondering, for the types A and B, is A a parameter, and B a return type? If I have multiple accepted types, do I use orElse to chain partial functions together?
In the set theoretic view of a function, if a function can map every value in the domain to a value in the range, we say that this function is a total function. There can be situations where a function cannot map some element(s) in the domain to the range; such functions are called partial functions.
Taking the example from the Scala docs for partial functions:
val isEven: PartialFunction[Int, String] = {
case x if x % 2 == 0 => x+" is even"
}
Here a partial function is defined since it is defined to only map an even integer to a string. So the input to the partial function is an integer and the output is a string.
val isOdd: PartialFunction[Int, String] = {
case x if x % 2 == 1 => x+" is odd"
}
isOdd is another partial function similarly defined as isEven but for odd numbers. Again, the input to the partial function is an integer and the output is a string.
If you have a list of numbers such as:
List(1,2,3,4,5)
and apply the isEven partial function on this list you will get as output
List(2 is even, 4 is even)
Notice that not all the elements in the original list have been mapped by the partial function. However, there may be situations where you want to apply another function in those cases where a partial function cannot map an element from the domain to the range. In this case we use orElse:
val numbers = sample map (isEven orElse isOdd)
And now you will get as output:
List(1 is odd, 2 is even, 3 is odd, 4 is even, 5 is odd)
If you are looking to set up a partial function that, in effect, takes multiple parameters, define the partial function over a tuple of the parameters you'll be feeding into it, eg:
val multiArgPartial: PartialFunction[(String, Long, Foo), Int] = {
case ("OK", _, Foo("bar", _)) => 0 // Use underscore to accept any value for a given parameter
}
and, of course, make sure you pass arguments to it as tuples.
In addition to other answers, if by "multiple accepted types" you mean that you want the same function accept e.g. String, Int and Boolean (and no other types), this is called "union types" and isn't supported in Scala currently (but is planned for the future, based on Dotty). The alternatives are:
Use the least common supertype (Any for the above case). This is what orElse chains will do.
Use a type like Either[String, Either[Int, Boolean]]. This is fine if you have two types, but becomes ugly quickly.
Encode union types as negation of intersection types.
In my Scala course an example has given. It was about finding a more generalized function, which can be used to define an arithmetic summation function and an arithmetic production function. Here are the functions that should be generalized.
def sum(f:Int=>Int)(a:Int,b:Int):Int ={
if(a>b) 0
else f(a) + sum(f)(a+1,b)
}
def product(f:Int=>Int)(a:Int,b:Int):Int={
if(a>b)1
else f(a)*product(f)(a+1,b)
}
To generalize these functions the teacher gave such a function :
def mapReduce(f:Int=>Int,combine: (Int,Int)=>Int, zero:Int)(a:Int,b:Int):Int ={
if(a>b) zero
else combine(f(a),mapReduce(f, combine, zero)(a+1, b))
}
So mapReduce function can be used to generalize sum and product functions as follows:
def sumGN(f:Int=>Int)(a:Int,b:Int) = mapReduce(f, (x,y)=>(x+y), 0)(a, b)
def productGN(f:Int=>Int)(a:Int,b:Int) = mapReduce(f, (x,y)=>(x*y), 1)(a, b)
I took a look at the definition of map reduce in functional programming but I have a hard time why the generalized function has been named as map reduce above. I can not grasp the relation. Any help will make my very happy.
Regards
Functional programming usually has three central operators: map, reduce (sometimes called fold), and filter.
Map takes a list and an operation and produces a list containing the operation applied to everything in the first list.
Filter takes a list and a test and produces another list containing only the elements that pass the test.
Reduce (or fold) takes a list, an operation, and an initial value and applies the operation to the initial value and the elements in the list, passing the output into itself along with the next list item, producing the operational sum of the list.
If, for example, your list is [2,3,4,5,6,7], your initial value is 1, and your operation is addition, reduction will behave in the following way:
Reduce([2,3,4,5,6,7], +, 1) = ((((((initial + 2) + 3) + 4) + 5) + 6) + 7)
Your instructor may be calling it mapReduce because this is the paradigm's name, though simply reduce would be sufficient as well.
If you're curious as to the significance of his name, you should ask him. He is your instructor and all.
This is by no means an exact explanation (names are fuzzy anyway) but here’s an alternative definition:
def mapReduce(f: Int => Int, combine: (Int, Int) => Int, zero: Int)(a: Int, b: Int): Int ={
if (a > b) zero
else (a to b).map(f).reduce(combine)
}
Do you see the link?
mapReduce's mapping function is f in the question, though there's never an example of its definition. For sum and product it would be the identity function, but if you were summing the squares then the mapping function would be the square function.
mapReduce's reducer function is combine, wherein we are reducing a tuple of accumulator+value to a new accumulator for the next recursion.
I think the missing link besides the code not being very clear is to treat numbers as collections (e.g., 3 is a collection of three 1s). This is quite unusual and I don't know what it buys you but it could be that your teacher will use the analogy between numbers and collections for something more profound later.
Is this from Odersky's coursera course?
In Scala, I can define a function with two parameter lists.
def myAdd(x :Int)(y :Int) = x + y
This makes it easy to define a partially applied function.
val plusFive = myAdd(5) _
But, I can accomplish something similar by defining and returning a nested function.
def myOtherAdd(x :Int) = {
def f(y :Int) = x + y
f _
}
Cosmetically, I've moved the underscore, but this still feels like currying.
val otherPlusFive = myOtherAdd(5)
What criteria should I use to prefer one approach over the other?
There are at least four ways to accomplish the same thing:
def myAddA(x: Int, y: Int) = x + y
val plusFiveA: Int => Int = myAddA(5,_)
def myAddB(x: Int)(y : Int) = x + y
val plusFiveB = myAddB(5) _
def myAddC(x: Int) = (y: Int) => x + y
val plusFiveC = myAddC(5)
def myAddD(x: Int) = {
def innerD(y: Int) = x + y
innerD _
}
val plusFiveD = myAddD(5)
You might want to know which is most efficient or which is the best style (for some non-performance based measure of best).
As far as efficiency goes, it turns out that all four are essentially equivalent. The first two cases actually emit exactly the same bytecode; the JVM doesn't know anything about multiple parameter lists, so once the compiler figures it out (you need to help it with a type annotation on the case A), it's all the same under the hood. The third case is also extremely close, but since it promises up front to return a function and specifies it on the spot, it can avoid one internal field. The fourth case is pretty much the same as the first two in terms of work done; it just does the conversion to Function1 inside the method instead of outside.
In terms of style, I suggest that B and C are the best ways to go, depending on what you're doing. If your primary use case is to create a function, not to call in-place with both parameter lists, then use C, because it tells you what it's going to do. (This version is also particularly familiar to people coming from Haskell, for instance.) On the other hand, if you are mostly going to call it in place but will only occasionally curry it, then use B. Again, it says more clearly what it's expected to do.
You could also do this:
def yetAnotherAdd(x: Int) = x + (_: Int)
You should choose the API based on intention. The main reason in Scala to have multiple parameter lists is to help type inference. For instance:
def f[A](x: A)(f: A => A) = ...
f(5)(_ + 5)
One can also use it to have multiple varargs, but I have never seen code like that. And, of course, there's the need for the implicit parameter list, but that's pretty much another matter.
Now, there are many ways you can have functions returning functions, which is pretty much what currying does. You should use them if the API should be thought of as a function which returns a function.
I think it is difficult to get any more precise than this.
Another benefit of having a method return a function directly (instead of using partial application) is that it leads to much cleaner code when using infix notation, allowing you to avoid a bucketload of parentheses and underscores in more complex expressions.
Consider:
val list = List(1,2,3,4)
def add1(a: Int)(b: Int) = a + b
list map { add1(5) _ }
//versus
def add2(a: Int) = a + (_: Int)
list map add2(5)