Function Literal referencing by val and def - scala

I'm trying to understand the crucial difference between these two approaches of referencing / defining Function Literal (reference to anonymous function):
By val
scala> val v2 = new Function[Int, Int] {
| def apply(a: Int): Int = a + 1
| }
v2: Int => Int = <function1>
And by def
scala> def f2 = new Function[Int, Int] {
| def apply(a: Int): Int = a + 1
| }
f2: Int => Int
It seems that it pretty much the same in terms of use. I either can pass v2 or f2 to the function that accepts (Int) => Int as an argument. Passing arguments to its..
I guess or the case of v2 it creates an Function1 object that refers to the Function1 object.. like a proxy?
Ok.. My question is: what is advantage and disadvantages of 1th and 2nd approach?
And of it is defined by def, is it still Function Literal?

First of all, neither of your examples are actually function literals—you're creating a Function instance in the plain old sugar-free way, and in fact you could use this approach (new Function { ... }) to create an instance of scala.Function from Java code.
The following are both function literals, and are exactly equivalent to your definitions:
val v2 = (a: Int) => a + 1
def f2 = (a: Int) => a + 1
The only real difference here is that the val will create a single instance once and for all, no matter how many times you use v2 (and even if you never use it), while the def will create a new instance every time (or not at all, if you never use it). So you'll generally want to go with a val.
There are cases, however, where you need to use def. Consider the following:
def myIdentity[A] = (a: A) => a
There's no way we could write this as a val, since Scala doesn't have polymorphic functions in this sense (for any instance of Function[A, B], A and B have to be concrete types). But we can define a polymorphic method that returns a function, and when we write e.g. myIndentity(1), the A will be inferred to be Int, and we'll create (and apply) a Function[Int, Int] exactly as you'd expect.

Related

How is a function a value but a method id not?

Why are functions values but methods are not, or what makes a function a value in particular? What would allow me to decipher that methods do not contain that characteristic?
Scala is an object-oriented language. In object-oriented languages, every value is an object, and every object is a value.
Methods are bound to objects. It is awkward to have methods at the same time be a building block of objects and be objects themselves. It is easier to have them not be objects.
A function in Scala is, in some sense, just an object with an apply method. If there is no method named foo in scope, then foo() is simply syntactic sugar for foo.apply(). So, functions are values because they are objects.
While any object that has an apply method can be called as if it were a function, when we talk about "functions" in Scala, we usually mean something more specific: an instance of one of the FunctionN traits such as Function2[-T1, -T2, +R]. In particular, the function literal syntax
val add = (a: Int, b: Int) => a + b
is syntactic sugar for
val add = new Function2[Int, Int, Int] {
override def apply(a: Int, b: Int) = a + b
}
And the function type
type F = (Int, String, Long) => Boolean
is syntactic sugar for
type F = Function3[Int, String, Long, Boolean]
[Scastie link]
where each of the FunctionN traits is defined like this:
package scala
trait Function0[+R] {
def apply: R
override def toString = "<function>"
}
trait Function1[-T, +R] {
def apply(x: T): R
override def toString = "<function>"
}
trait Function2[-T1, -T2, +R] {
def apply(x1: T1, x2: T2): R
override def toString = "<function>"
}
trait Function3[-T1, -T2, -T3, +R] {
def apply(x1: T1, x2: T2, x3: T3): R
override def toString = "<function>"
}
and so on.
It is possible to convert a method into a function value using η-expansion. This can be done explicitly using a trailing underscore:
val f = println _
or in some cases, when it is clear that a function value is required, even by just using the bare name of the method:
val it = Iterable(1, 2, 3)
it.foreach(println)
[Scastie link]
Note that this is not much different from other languages. In Java, C#, and Ruby, for example, it is the same thing: methods are defined as part of classes (or structs in C# and modules in Ruby) and are bound to objects, but aren't objects themselves. Instead, you have a separate notion of a function (instance of a SAM interface / functional interface in Java, Action or Func in C#, Proc in Ruby), which is an object.
In Ruby, you can create a proxy object for a method that is bound to an object which has the same interface as Proc.
Other languages make different choices, i.e. in ECMAScript and Python, methods are objects / values, but they are not as tightly bound to objects as they are in Scala, Java, C#, and Ruby. Instead, methods are basically normal functions that are assigned to fields of the object.
One of the defining characteristics of a value is that it can be assigned to a variable. A method, technically speaking, cannot be assigned to a variable, for example
def m(i: Int): Int = i + 1
val f = m // error
However there is a process called eta expansion that converts a method to a function value. In Scala 2, we can trigger it by providing type ascription to a variable
val f: Int => Int = m
or by using underscore _
val f = m _
However this restriction has been lifted in Scala 3 (Dotty) which now provides automatic eta expansion so the following compiles successfully
scala> def f(i: Int): Int = i + 1
| val x = f
def f(i: Int): Int
val x: Int => Int = Lambda$1218/158882051#62cf6a84

Infinite curryable add function

I was wondering how one would implement an infinite curried add function, for the case of explanation i would stick to scala.
I know how to prepare a simple curry like
def add(a: Int): Int => Int = {
def iadd(b: Int): Int = {
a + b
}
iadd
}
add(4)(5) // 9
How would i got about implementing add(5)(4)(x1)(x2)..(xn)
The Smart Way
The question is the comments is well-posed: when do you stop the currying and produce a result?
One solution is to stop the recursion by calling the function with zero arguments. Scala's overloading with let us do this.
add(1)(2)(3)(4)() // The () indicates that we're done currying
This is relatively straightforward. We just need a class with an apply that returns a new instance of itself
// A class with an apply method is callable like a function
class Adder(val acc: Int) {
def apply(a: Int): Adder =
new Adder(acc + a)
def apply(): Int =
acc
}
def add: Adder = new Adder(0)
println(add(1)(2)(3)(4)()) // 10
If you ever had a real reason to do this, this would be the way I would recommend. It's simple, easy to read, and adds very little boilerplate on top of the currying.
The Slightly Unhinged Way
But what fun is simple and logical? Let's get rid of those silly parentheses at the end, eh? We can do it with Scala's implicit conversions. First, we'll need to import the feature, so that Scala will stop warning us that what we're doing is silly and not a good idea.
import scala.language.implicitConversions
Then we make it so that Adder can be converted to Int
// Don't do this in real code
implicit def adderToInt(adder: Adder): Int =
adder()
Now, we don't need those parentheses at the end. We do, however, need to indicate to the type system that we want an Int.
val result: Int = add(1)(2)(3)(4)
println(result) // 10
Passing the result to a function which takes an Int, for instance, would also suffice.
Comments
Since you mentioned functional programming in general, I will note that you can do similar tricks in Haskell, using typeclasses. You can see this in action in the standard library with Text.PrintF. Note that since Haskell functions always take one argument, you'll need to have a sentinel value to indicate the "end" of the arguments (() may suffice, depending on how generic your argument types are).
If you want to reinterpret every integer n as function n.+, then just do it:
implicit class Add(val x: Int) extends AnyVal { def apply(i: Int) = x + i }
val add = 0
or even shorter (with implicit conversions):
implicit def asAdd(n: Int): Int => Int = n.+
val add = 0
Example:
add(1)(2)(3)(4) // res1: Int = 10
There is no such thing as "infinitely curryable", it's not a meaningful notion.
Well, this is not exactly infinite currying, but it gives you the something similar.
final class InfiniteCurrying[A, B] private (acc: A, op: (A, B) => A) {
final val run: A = acc
final def apply(b: B): InfiniteCurrying[A, B] =
new InfiniteCurrying(
acc = op(acc, b),
op,
)
}
object InfiniteCurrying {
def add(initial: Int): InfiniteCurrying[Int, Int] =
new InfiniteCurrying(
acc = initial,
op = (acc, b) => acc + b
)
}
import InfiniteCurrying._
val r = add(10)(20)(30)
r.run // res: Int = 60

Scala: defining a function with parameters and callable

I was wondering how it works if I want to defining a function that takes one or more parameters and a callable (a function), and why the annotation is like this.
I will take the code from this answer as example:
// Returning T, throwing the exception on failure
#annotation.tailrec
final def retry[T](n: Int)(fn: => T): T = {
util.Try { fn } match {
case util.Success(x) => x
case _ if n > 1 => retry(n - 1)(fn)
case util.Failure(e) => throw e
}
}
In this function there are a few interesting things:
The annotation tailrec.
Generic type function retry[T]
Parameter int
callable fn
My question is on point 4. Why and how the definition of this function takes two round brackets. If you want to pass a callable function to any function should you always use a round brackets next to the "list" of optional parameter? Why not put together with the parameters?
Thank you in advance
You can have multiple parameter lists in function declaration. It is mostly the same as merging all the parameters into one list (def foo(a: Int)(b: Int) is more or less equivalent to def foo(a: Int, b: Int)) with a few differences:
You can reference parameters from previous list(s) in declaration: def foo(a : Int, b: Int = a + 1) does not work, but def foo(a: Int)(b: Int = a +1) does.
Type parameters can be inferred between parameter lists: def foo[T](x: T, f: T => String): String ; foo(1, _.toString) doesn't work (you'd have to write foo[Int](1, _.toString), but def foo[T](x: T)(f: T => String); foo(1)(_.toString) does.
You can only declare the entire list as implicit, so, multiple lists are helpful when you need some parameters to be implicit, and not the others: def foo(a: Int)(implicit b: Configuration)
Then, there are some syntactical advantages - things you could do with the single list, but they'd just look uglier:
Currying:
def foo(a: Int)(b: Int): String
val bar: Int => String = foo(1)
You could write this with the single list too, but it wouldn't look as nice:
def foo(a: Int, b: Int): String
val bar: Int => String = foo(1, _)
Finally, to your question:
def retry[T](n: Int)(f: => T)
is nice, because parenthesis are optional around lists with just a single argument. So, this lets you write things like
retry(3) {
val c = createConnection
doStuff(c)
closeConnection(c)
}
which would look a lot uglier if f was merged into the same list.
Also, currying is useful:
val transformer = retry[Int](3)
Seq(1,2,3).map { n => transformer(n + 1) }
Seq(4,5,6).map { n => transformer(n * 2) }
To be honest you don't have to use multiple parameter lists in order to pass function as an argument. E.g.
def pass(string: String, fn: String => Unit): Unit = fn(string)
would totally work. However, how would you call it?
pass("test", s => println(s))
Some would find it clumsy. You would rather want to pass it like:
pass("test")(s => println(s))
or even
pass("test") { s =>
println(s)
}
to make it look as if function is a block appended to the pass called with one parameter.
With single parameter list you will be forced to write it like:
pass("test", println)
pass("test", s => println(s))
pass("test", { s => println(s) })
With last parameter curried you just get more comfortable syntax. In languages like Haskell, where currying happens automatically, you don't have to bother with syntactic design decisions like this one. Unfortunately Scala requires that you made these decisions explicitly.
If you want to pass a callable function to any function should you
always use a round brackets next to the "list" of optional parameter?
Why not put together with the parameters?
There is no such obligation, it's (mostly) a matter of style. IMO, it also leads to cleaner syntax. With two parameter lists, where the second one is the function yielding the result, we can call the retry method:
val res: Try[Int] retry(3) {
42
}
Instead, of we used a single parameter list, our method call would look like this:
val res: Try[Int] = retry(3, () => {
42
})
I find the first syntax cleaner, which also allows you to use retry as a curried method when only supplying the first parameter list
However, if we think of a more advanced use case, Scala type inference works between parameter lists, not inside them. That means that if we have a method:
def mapFun[T, U](xs: List[T])(f: T => U): List[U] = ???
We would be able to call our method without specifying the type of T or U at the call site:
val res: List[Int] = mapFun(List.empty[Int])(i => i + 1)
But if we used a single parameter list,
def mapFun2[T, U](xs: List[T], f: T => U): List[U] = ???
This won't compile:
val res2 = mapFun2(List.empty[Int], i => i + 1)
Instead, we'd need to write:
val res2 = mapFun2[Int, Int](List.empty[Int], i => i + 1)
To aid the compiler at choosing the right types.

What is the eta expansion in Scala?

I am new to Scala. I just heard the term "eta expansion" and roughly know that it means to expand a method to a function object. But I find few resources in SO that systematically introduce it.
I am curious about how eta expansion works in Scala. What are the scenarios that eta expansion are needed? And how eta expansion is implemented in Scala?
I roughly know that in cases like this:
def someMethod(x: Int): Int = x * x
someMethod _ will roughly be translated to a new function object like this:
new Function1[Int, Int] {
def apply(x: Int): Int = x * x
}
Is it all that Scala does?
The definition, and some examples, are given in http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#method-values.
someMethod _ will roughly be translated to a new function object like this:
Not quite: it's actually
new Function1[Int, Int] {
def apply(x: Int): Int = someMethod(x)
}
The difference matters e.g. if someMethod is overridden somewhere.
Is it all that Scala does?
You also need to take into account what happens if the method takes multiple parameter lists (you get a function which returns a function) or by-name parameters.
What are the scenarios that eta expansion are needed?
When you specifically ask for it (e.g. someMethod _).
When you use a method (with parameters) where a value of a function type (or a SAM type in Scala 2.12) is expected. E.g.
def foo(f: Int => Int) = ???
foo(someMethod)
That's it.
Note that using eta-expansion and an anonymous function with placeholders (someMethod(_)) can behave differently due to type inference, implicits, etc.
Eta expansion In high level, is a process of translating methods into functions. Why? What? Aren't them the same? Let's explain:
A method in scala is what we know as def someMethodName(SomePramList): SomeReturnType. It starts with def. It may have parameter list, or even maybe more then 1. For example:
def numAdder(num1: Int)(num2: Int): Int =
num1 + num2
A function, or lambda function looks something like: (SomeParams) => SomeReturnType. For example:
val aFunction: Int => Int => Int = (num1: Int) => (num2: Int) => num1 + num2
Important to understand about functions is that this syntax is basically a syntactic sugar to FunctionN.apply method.
What are the scenarios that eta expansion are needed?
Some examples:
Example1 - Applying a method inside map (or filter, flatMap etc)
Writing such code:
def addPlus1(x: Int): Int = x + 1
List(1,2,3).map(addPlus1)
The compiler needs to have a function inside the map. So, it transforms the method given into a function:
List(1,2,3).map(x => addPlus1(x)). This is Eta expansion.
Example2 - currying
When defining curried method, for example:
def numAdder(num1: Int)(num2: Int): Int =
num1 + num2
And them creating a function like:
val curriedFunction: Int => Int = numAdder(4)
//or
val curriedFunction2 = numAdder(4) _
We defined a function out of a method. This is Eta expansion.
Some more examples
Defined a method which accepts a function value:
def someMethod(f: () => Int): Int = f()
def method(): Int = 10
And then run:
someMethod(method)
will transform the method method into a function. This is Eta expansion

How two abstract the number of parameters of a function with type parameters in Scala?

There is a Wrapper class for arbitrary functions. I tried to abstract the input and output (return value) of the function with the two type parameters [I, O] (for input and output).
class Wrapper[I, O](protected val f: I => O {
protected def doIt(input: I): O = f(input)
}
As this should be a wrapper for arbitrary functions, I have a problem with functions that take multiple parameters.
val multiplyFunction = (a: Int, b: Int) => a * b
val multiplyWrapper = new Wrapper[(Int, Int), Int](multiplyFunction)
The second line does not compile, because the wrapper expects a function which takes a Tuple with two Ints as the only parameter.
Is there a way to rewrite this, so that I can abstract the function's parameters no matter how many parameters there are? Ideally the solution would be type safe, by the compiler.
Maybe I there is an alternative to using a tuple to specify the types for the wrapper when creating an instance it.
I hope I don't have to write it like the Tuple classe Tuple2 to TupleN or Function2 to FunctionN. I don't know all the details about this, but that does look more like a workaround and is not a abstract / generic solution.
You could use tupled method on function: new Wrapper(multiplyFunction.tupled).
If you want to make this transparent to the wrapper class's user you could use duck typing:
object Wrapper {
def apply[I, O](e: { def tupled: I => O }) = new Wrapper(e.tupled)
def apply[I, O](e: I => O) = new Wrapper(e)
}
scala> Wrapper( (a: Int) => a )
res0: Wrapper[Int,Int] = Wrapper#29d03e78
scala> Wrapper( (a: Int, b: Int) => a * b )
res1: Wrapper[(Int, Int),Int] = Wrapper#581cdfc2
You'll get some overhead due to reflection.