I've just started Scala and am tinkering in worksheets. For example:
def merp(str: String) : String = s"Merrrrrrrp $str"
val merp2 = (str: String) => s"Merrrrrrrp $str"
val merp3 = (str: String) => merp(str)
val merp4 = merp _
merp("rjkghleghe")
merp4("rjkghleghe")
And the corresponding worksheet results:
merp: merp[](val str: String) => String
merp2: String => String = <function1>
merp3: String => String = <function1>
merp4: String => String = <function1>
res0: String = Merrrrrrrp rjkghleghe
res1: String = Merrrrrrrp rjkghleghe
Saying, for example, val merp5 = merp produces an error, because apparently methods cannot be values the way functions can. But I can still pass methods as arguments. I demonstrate this in the following code snippet, adapted from a similar SO question:
def intCombiner(a: Int, b: Int) : String = s"herrrrrrp $a derrrrrrp $b"
def etaAbstractor[A, B](combineFoo: (A, B) ⇒ String, a: A, b: B) = combineFoo(a, b)
etaAbstractor(intCombiner, 15, 16)
worksheet result:
intCombiner: intCombiner[](val a: Int,val b: Int) => String
etaAbstractor: etaAbstractor[A,B](val combineFoo: (A, B) => String,val a: A,val b: B) => String
res10: String = herrrrrrp 15 derrrrrrp 16
Is methods-not-being-first-class a limitation, perhaps imposed by Scala's JVM interaction, or is it a decision in the language's design?
Why do I need to roll my own eta abstractions, as in merp3?
Is merp4 also an eta abstraction, or is it something sneakily similar?
Why does my etaAbstractor work? Is Scala quietly replacing intCombiner with intCombiner _?
Theoretical, computer sciencey answers are welcome, as are pointers to any relevant points in the language specification. Thanks!
Disclaimer: I'm not a computer scientist, but I will try to guess:
Method is a part of an object and doesn't exist outside of it. You can't pass method alone. Closure is another (equivalent?) way of encapsulating state, by converting an object method to a standalone function (which is by the way just another object with apply() method in Scala) you are creating a closure. This process is known as eta-expansion. §3.3.1, §6.26.5
You don't have to. You can also write val merp3 : (String => String) = merp. §6.26.5
Yes, merp4 is eta-expansion too. §6.7
§6.26.2
The reason it works with etaAbstractor is that the compiler can infer that a function (not a function invocation) is required.
If I had to guess why the underscore is required where a function type cannot be inferred, I'd think that it's to improve error reporting of a common class of errors (getting functions where invocations are intended). But again, that's just a guess.
In the JVM, a method is not an object, whereas a first-class function must be one. So the method must be boxed into an object to convert it to a function.
Related
I am reading example about monad transformers in scalaz. Here is a piece of code:
scala> def myName(step: String): Reader[String, String] = Reader {step + ", I am " + _}
myName: (step: String)scalaz.Reader[String,String]
scala> def localExample: Reader[String, (String, String, String)] = for {
a <- myName("First")
b <- myName("Second") >=> Reader { _ + "dy"}
c <- myName("Third")
} yield (a, b, c)
localExample: scalaz.Reader[String,(String, String, String)]
scala> localExample("Fred")
res0: (String, String, String) = (First, I am Fred,Second, I am Freddy,Third, I am Fred)
How does it happen, that localExample can take a parameter? Oo There is not any parameters list in definition
localExample: Reader[String, (String, String, String)] just return type is specified. Also the same question about
myName function, it also has more function parameters then mentioned in its definition.
The key is in the return type that is specified, which is an instance of the Reader monad. Roughly, the reader monad is like a wrapper around a function from - in the case of myName - String to String, so it is a bit like a function defined as:
def myName(step: String): String => String
For localExample, the return type is now a "wrapper around a function from String to Triple of String" (quotes used because this is something of a simplified sense of what the Reader monad is).
In both cases, the return type is - sort of - a function that can take a (String) parameter with which to generate a final result, and it is this sort-of-a function that is taking the parameter passed to localExample in the call localExample("Fred"). Essentially like calling localExample().apply("Fred").
There is more to monads like the Reader than just the above (which I'm not sure I feel expert enough to explain properly right now), but hopefully that's enough to answer your question.
I'm trying to understand every piece of the implementation of class OWritesOps explained here: http://kailuowang.blogspot.mx/2013/11/addremove-fields-to-plays-default-case.html
The way scala / play doc is structured doesn't really help (in this area Java(doc) beats Scala(doc) hands down).
Let's start with: addField:
def addField[T: Writes](fieldName: String, field: A => T): OWrites[A] =
(writes ~ (__ \ fieldName).write[T])((a: A) => (a, field(a)))
I could only guess that the ~ is an equivalent of "and" (I gather it from here: http://mandubian.com/2012/10/01/unveiling-play-2-dot-1-json-api-part2-writes-format-combinators/ )
Alright, so let's just take it this way: (writes ~ (__ \ fieldName).write[T]) create a new instance of Writes (combo).
What about (__ \ fieldName) ? After a lot of digging Play Doc, I came to a (shaky) conclusion that it produces an instance of JsPath? How did I arrive to that conclusion? It's for that .write[T] that follows; JsPath has that method.
Beside, I read somewhere that __ is a shortcut for JsPath (I forgot where, I guess it's in Play Doc as well, but using Scala doc it's almost impossible to find my way back to that page).
Ok..., so (writes ~ (__ \ fieldName).write[T]) produces an instance of OWrites. Next: what's this?: ((a: A) => (a, field(a)))
Oh..., it's for the apply the parameter to the "apply" method of OWrites; it takes an lambda function with the following signature ((A) => JsObject)
Ok...., so.... (a, field(a)) is supposed to create an instance of JsObject. So, I opened the play doc, JsObject. Hmm..., I guess it's this constructor (?): JsObject(fields: Seq[(String, JsValue)]) .... But,... I really doubt it.... I'm lost here.
Anyway, let's see an example how it is used:
val customWrites: Writes[Person] = Json.Writes[Person]. addField("isAdult", _.isAdult)
So..., _.isAdult is supposed to map to a block with the following signature: A => T ... But..., if that's really the case, I was expecting {x => x.isAdult} .... so I guess _.isAdult is a syntactic-sugar provided by Scala (?).
So... back to the definition of addField: field(a) executes the block "_.isAdult". I can infer here that a is an instance of Person then.
Can you help me decipher all this?
Scala is cool, but it's doc system (still) sucks :(
Can you help me decipher all this?
I could only guess that the ~ is an equivalent of "and"
~ is the name of a method invoked on the instance of OWrites. writes ~ (__ \ fieldName).write[T]) is the same as writes.~((__ \ fieldName).write[T])). Note the brackets around the argument of ~.
There are two things relevant to this equivalent form:
In Scala, any method with one argument can be written using infix notation. For example, if you have an instance list: java.util.ArrayList[Int], you could write list add 5.
While a method name need not be alphanumeric (as in Java), not all operators have the same precedence. For example, 1 + 5 * 2 translates to 1.+(5.*(2)) and not to 1.+(5).*(2). Here's a summary of operator precedence in Scala.
However, OWrites has no method called ~ in its interface. If you import play.api.libs.functional.syntax._, there's an implicit conversion
implicit def toFunctionalBuilderOps[M[_], A](a: M[A])(implicit fcb: FunctionalCanBuild[M]) = new FunctionalBuilderOps[M, A](a)(fcb)
and FunctionalBuilderOps defines the method
def ~[B](mb: M[B]): FunctionalBuilder[M]#CanBuild2[A, B] = {
val b = new FunctionalBuilder(fcb)
new b.CanBuild2[A, B](ma, mb)
}
and an alias for it: def and[B](mb: M[B]): FunctionalBuilder[M]#CanBuild2[A, B] = this.~(mb)
What about (__ \ fieldName) ?
The package play.api.libs.json defines a value val __ = JsPath, so the double underscores are just an alias for the singleton object JsPath. The singleton object JsPath is not to be confused with the equally-named class. This construct is called a companion object in Scala. While Java puts static members next to the regular members in a class, Scala puts them inside the companion object.
Apparently, the object JsPath is at the same time the companion object of the case class JsPath and an instance of JsPath(List.empty).
fieldName is of type String and JsPath defines a method
def \(child: String) = JsPath(path :+ KeyPathNode(child))
which is equivalent to
def \(child: String) = JsPath.apply(path :+ KeyPathNode(child))
The default apply method of a case class' companion object creates a new instance, so this is equivalent to
def \(child: String) = new JsPath(path :+ KeyPathNode(child))
As our singleton object __ is an instance of JsPath with the empty list for path, this returns us a new JsPath(KeyPathNode(child)), where child == fieldName
what's this?: ((a: A) => (a, field(a)))
It's a function taking an instance of A. The function maps the argument a to the tuple (a, field(a), where field is a function provided as argument to your method addField. It has the signature field: A => T, so it is a function that takes an instance of A and returns an instance of T.
This may be a bit confusing, so let me give you an example function that does not operate on generics. Say you want to define a function f that squares an integer number. For example, f(1) should be 1, f(3) should be 9. As it takes an integer and returns an integer, its signature is f: Int => Int. It's implementation is f = (x: Int) => x * x.
Oh..., it's for the apply the parameter to the "apply" method of OWrites; it takes an lambda function with the following signature ((A) => JsObject)
Actually, this is not correct - the signatures do not match. The given lambda function is of type A => (A, T). Also, as pointed out in the first part of the answer, the method ~ returns an instance of FunctionalBuilder#CanBuild2. Unfortunatly, I am lost on what the called apply-method does, because it is highly generic and uses implicit arguments of a generic type.
so I guess _.isAdult is a syntactic-sugar provided by Scala (?).
Yes, the underscore in lambda functions is syntactic sugar for capturing the arguments. For example, _ + _ is syntactic sugar for (x, y) => x + y, meaning the following two values are equivalent:
val f: (Int, Int) => Int = (x, y) => x + y
val g: (Int, Int) => Int = _ + _
So _.isAdult really just translates to {x => x.isAdult} and in the example, x: Person.
Update
The idea behind this write builder seems to be to provide means of defining a mapping from one of your Scala classes to JSON. Let's take a look again at the case class Person(name: String, age: Int). Now, let's assume we have an instance of Person:
val odersky = Person("Martin Odersky", 56)
and want to serialize the instance to the following JSON:
{
"name": "Martin Odersky",
"age": 56
}
The key is always a string, but the value can be of a different type. So, basically, the serialization is a function taking a Person and returning a tuple of key-value pairs where the value is always a string, i.e., Person => ((String, String), (String, Int)). Or, in the general case where we do not know what we are going to serialize, simply that it has two fields, it is A => ((String, B), (String, C)) for arbitrary types A, B, and C.
This is what CanBuild2 emulates - the 2 standing for the number of members to serialize. There's also a CanBuild3, CanBuild4 and so on.
We can instantiate a CanBuild2 that is appropriate to our example, by calling
val serializer = (__ \ "name").write[String] ~ (__ \ "age").write[Int]
Here, the type of serializer is FunctionalBuilder[OWrites]#CanBuild2[String, Int]
Now, the apply method of CanBuild2 can be used to generate an instance of the first generic argument - OWrites. The argument to the apply method is a function that maps an instance of our type to serialize (here Person) to a tuple of the desired value types, here String and Int (representing name and age).
val personWriter: OWrites[Person] = serializer((p: Person) => (p.name, p.age))
This writer can now be used to generate a JSON string from any instance of Person. So we can pass our person and get the desired output:
println(toJson(odersky)(personWriter))
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between method and function in Scala
Two ways of defining functions in Scala. What is the difference?
There are 2 ways to define a function.
scala> def a : (Int, Int) => Int = {(s:Int, t:Int) => s + t}
a: (Int, Int) => Int
scala> a
res15: (Int, Int) => Int = <function2>
scala> def b(s:Int, t:Int) : Int = s+t
b: (s: Int, t: Int)Int
scala> b
<console>:9: error: missing arguments for method b in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
b
^
scala> b(3,4)
res17: Int = 7
scala> a(3,4)
res18: Int = 7
Is there any difference in how I define functions a and b? Why do I have missing arguments error with b?
b is not a function, but a method. You can however turn b into a function by adding the _ as the compiler mentions. val f = b _. But you should only do this, if you want to pass a method of an object to a method/function that takes a function as parameter. If you just want to define a function go the normal way.
But to answer your question, there is another way:
val f = new Function2[Int,Int,Int] {
def apply(x: Int, y: Int) = x + y
}
Object Oriented languages (e.g. java) typically have classes and classes have methods, while functions are not "first-class citizens", meaning you can't assign a function directly to a variable or put a few functions in a list or send them as arguments to other functions.
If you want to send a function around in java, you have to create a class with a method and send the class around.
For instance, if you want to have a function that calculates the double of its input, you have to put it in a class, like this:
class Doubler
{
public int apply(int a)
{
return a * 2;
}
}
In functional programming languages, like Haskell, functions are "first-class", and you can store them in variables and send them around.
doubleIt :: Integer -> Integer
doubleIt x = 2 * x
As a beautiful combination of functional and object oriented, scala has both methods and functions.
// a function like in haskell
val doubleIt = (x:Int) => x * 2
// a method in an object like in java
object Doubler {
def apply(x:Int) = x * 2
}
In scala def always defines a method. Note that the REPL wraps everything you write in an object with a main (in order to be able to compile and execute it on the fly), but writing a def something not wrapped in a class/object/trait in a program would not compile.
Scala also has a few more perks to offer, to decrease the disconnect between object and first-class functions.
For one thing, the "apply" method over there in the Doubler object definition in scala is sort of magic.
Given the definition above, you can write Doubler(2) and scala's compiler will transform this into Doubler.apply(2) and happily return 4.
So you can sort of use objects as functions.
But also, you can (by putting a _ sign after the call to a method) transform the method into a real function and (say) assign it to a val.
scala> val d = Doubler.apply _
d: Int => Int = <function1>
scala> d(2)
res1: Int = 4
On the other hand, the way scala makes a function like val doubleIt = (x:Int) => x * 2 into a first class "thing" is by turning it into something like this behind your back.
object Doubler extends Function[Int, Int] {
def apply(x: Int) = x*2
}
val doubleIt = Doubler
So, yeah... a function is actually still a class with a method, more or less like in java. Except that scala does it for you and gives you a lot of syntactic sugar to use that generated class as you would use an actual function.
To make things even more interesting, since functions are first-class, one of the things you can do with them in scala is use them as return values from other functions or methods.
So when you wrote def a : (Int, Int) => Int = {(s:Int, t:Int) => s + t} you actually defined a method, called a that returns a function. It may be confusing at first (and at second, and at third....) but around the fourth time around it will probably start looking beautiful. At least that's what it did for me.
I need to parse some messages. The first 4 bytes of a message identify the type of message, so, using that, I can instantiate an object of the proper type. To make this an efficient operation, I thought I would create a hash map where they key is the first 4 bytes, and the value is the object constructor. I can just look up the constructor and invoke it.
After all, constructors are just functions, and there shouldn't be any problem putting functions in a map. It turns out that I am having some difficulty with this because I don't know how to express the reference to the constructor properly.
To get concrete with a simplified example, suppose we have a message base class, MsgBase, and a couple subclasses, MsgA and MsgB. If I create a companion object for each of the messages and put a factory function into it, I can make the array without any problem using those functions.
Here is a simplified sample which takes the message as a string.
class MsgBase(message: String) { }
class MsgA(message: String) extends MsgBase(message) { }
object MsgA { def makeIt(message: String): MsgA = new MsgA(message) }
and where MsgB is similar. Then I can make the map:
val cm = Map[String, (String) => MsgBase]("a" -> MsgA.makeIt, "b" -> MsgB.makeIt)
val myMsg = cm("a")("a.This is the message")
It seems like I should be able to refer to the message object constructor directly in the expression building the map, rather than using the trivial function in the companion object, but I haven't figured out any way to express that. Is there a way?
Try
"a" -> (new MsgA(_))
(all parentheses are needed).
Even if this didn't work, you could of course always define the function explicitly:
"a" -> ( (s: String) => new MsgA(s) )
For this case it would be better to use case classes, which automatically provide you functions for creating new objects.
scala> case class MsgA(message: String) extends MsgBase(message)
scala> case class MsgB(message: String) extends MsgBase(message)
So you can refer them just by name, without any syntactical overhead
scala> val m = Map("a"->MsgA, "b"->MsgB)
m: scala.collection.immutable.Map[java.lang.String,scala.runtime.AbstractFunction1[java.lang.String,Product with MsgBase]] = Map((a,<function1>), (b,<function1>))
scala> m("a")("qqq")
res1: Product with MsgBase = MsgA(qqq)
As an alternative approach you can create companion object with overrided apply method by hand. For details see Programming scala, chapter 6
val cm = Map[String, (String) => MsgBase]("a" -> (new MsgA(_)), "b" -> (new MsgB(_)))
I read Scala Functions (part of Another tour of Scala). In that post he stated:
Methods and functions are not the same thing
But he didn't explain anything about it. What was he trying to say?
Jim has got this pretty much covered in his blog post, but I'm posting a briefing here for reference.
First, let's see what the Scala Specification tell us. Chapter 3 (types) tell us about Function Types (3.2.9) and Method Types (3.3.1). Chapter 4 (basic declarations) speaks of Value Declaration and Definitions (4.1), Variable Declaration and Definitions (4.2) and Functions Declarations and Definitions (4.6). Chapter 6 (expressions) speaks of Anonymous Functions (6.23) and Method Values (6.7). Curiously, function values is spoken of one time on 3.2.9, and no where else.
A Function Type is (roughly) a type of the form (T1, ..., Tn) => U, which is a shorthand for the trait FunctionN in the standard library. Anonymous Functions and Method Values have function types, and function types can be used as part of value, variable and function declarations and definitions. In fact, it can be part of a method type.
A Method Type is a non-value type. That means there is no value - no object, no instance - with a method type. As mentioned above, a Method Value actually has a Function Type. A method type is a def declaration - everything about a def except its body.
Value Declarations and Definitions and Variable Declarations and Definitions are val and var declarations, including both type and value - which can be, respectively, Function Type and Anonymous Functions or Method Values. Note that, on the JVM, these (method values) are implemented with what Java calls "methods".
A Function Declaration is a def declaration, including type and body. The type part is the Method Type, and the body is an expression or a block. This is also implemented on the JVM with what Java calls "methods".
Finally, an Anonymous Function is an instance of a Function Type (ie, an instance of the trait FunctionN), and a Method Value is the same thing! The distinction is that a Method Value is created from methods, either by postfixing an underscore (m _ is a method value corresponding to the "function declaration" (def) m), or by a process called eta-expansion, which is like an automatic cast from method to function.
That is what the specs say, so let me put this up-front: we do not use that terminology! It leads to too much confusion between so-called "function declaration", which is a part of the program (chapter 4 -- basic declarations) and "anonymous function", which is an expression, and "function type", which is, well a type -- a trait.
The terminology below, and used by experienced Scala programmers, makes one change from the terminology of the specification: instead of saying function declaration, we say method. Or even method declaration. Furthermore, we note that value declarations and variable declarations are also methods for practical purposes.
So, given the above change in terminology, here's a practical explanation of the distinction.
A function is an object that includes one of the FunctionX traits, such as Function0, Function1, Function2, etc. It might be including PartialFunction as well, which actually extends Function1.
Let's see the type signature for one of these traits:
trait Function2[-T1, -T2, +R] extends AnyRef
This trait has one abstract method (it has a few concrete methods as well):
def apply(v1: T1, v2: T2): R
And that tell us all that there is to know about it. A function has an apply method which receives N parameters of types T1, T2, ..., TN, and returns something of type R. It is contra-variant on the parameters it receives, and co-variant on the result.
That variance means that a Function1[Seq[T], String] is a subtype of Function1[List[T], AnyRef]. Being a subtype means it can be used in place of it. One can easily see that if I'm going to call f(List(1, 2, 3)) and expect an AnyRef back, either of the two types above would work.
Now, what is the similarity of a method and a function? Well, if f is a function and m is a method local to the scope, then both can be called like this:
val o1 = f(List(1, 2, 3))
val o2 = m(List(1, 2, 3))
These calls are actually different, because the first one is just a syntactic sugar. Scala expands it to:
val o1 = f.apply(List(1, 2, 3))
Which, of course, is a method call on object f. Functions also have other syntactic sugars to its advantage: function literals (two of them, actually) and (T1, T2) => R type signatures. For example:
val f = (l: List[Int]) => l mkString ""
val g: (AnyVal) => String = {
case i: Int => "Int"
case d: Double => "Double"
case o => "Other"
}
Another similarity between a method and a function is that the former can be easily converted into the latter:
val f = m _
Scala will expand that, assuming m type is (List[Int])AnyRef into (Scala 2.7):
val f = new AnyRef with Function1[List[Int], AnyRef] {
def apply(x$1: List[Int]) = this.m(x$1)
}
On Scala 2.8, it actually uses an AbstractFunction1 class to reduce class sizes.
Notice that one can't convert the other way around -- from a function to a method.
Methods, however, have one big advantage (well, two -- they can be slightly faster): they can receive type parameters. For instance, while f above can necessarily specify the type of List it receives (List[Int] in the example), m can parameterize it:
def m[T](l: List[T]): String = l mkString ""
I think this pretty much covers everything, but I'll be happy to complement this with answers to any questions that may remain.
One big practical difference between a method and a function is what return means. return only ever returns from a method. For example:
scala> val f = () => { return "test" }
<console>:4: error: return outside method definition
val f = () => { return "test" }
^
Returning from a function defined in a method does a non-local return:
scala> def f: String = {
| val g = () => { return "test" }
| g()
| "not this"
| }
f: String
scala> f
res4: String = test
Whereas returning from a local method only returns from that method.
scala> def f2: String = {
| def g(): String = { return "test" }
| g()
| "is this"
| }
f2: String
scala> f2
res5: String = is this
function A function can be invoked with a list of arguments to produce a
result. A function has a parameter list, a body, and a result type.
Functions that are members of a class, trait, or singleton object are
called methods. Functions defined inside other functions are called
local functions. Functions with the result type of Unit are called procedures.
Anonymous functions in source code are called function literals.
At run time, function literals are instantiated into objects called
function values.
Programming in Scala Second Edition.
Martin Odersky - Lex Spoon - Bill Venners
Let Say you have a List
scala> val x =List.range(10,20)
x: List[Int] = List(10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
Define a Method
scala> def m1(i:Int)=i+2
m1: (i: Int)Int
Define a Function
scala> (i:Int)=>i+2
res0: Int => Int = <function1>
scala> x.map((x)=>x+2)
res2: List[Int] = List(12, 13, 14, 15, 16, 17, 18, 19, 20, 21)
Method Accepting Argument
scala> m1(2)
res3: Int = 4
Defining Function with val
scala> val p =(i:Int)=>i+2
p: Int => Int = <function1>
Argument to function is Optional
scala> p(2)
res4: Int = 4
scala> p
res5: Int => Int = <function1>
Argument to Method is Mandatory
scala> m1
<console>:9: error: missing arguments for method m1;
follow this method with `_' if you want to treat it as a partially applied function
Check the following Tutorial that explains passing other differences with examples like other example of diff with Method Vs Function, Using function as Variables, creating function that returned function
Functions don't support parameter defaults. Methods do. Converting from a method to a function loses parameter defaults. (Scala 2.8.1)
There is a nice article here from which most of my descriptions are taken.
Just a short comparison of Functions and Methods regarding my understanding. Hope it helps:
Functions:
They are basically an object. More precisely, functions are objects with an apply method; Therefore, they are a little bit slower than methods because of their overhead. It is similar to static methods in the sense that they are independent of an object to be invoked.
A simple example of a function is just like bellow:
val f1 = (x: Int) => x + x
f1(2) // 4
The line above is nothing except assigning one object to another like object1 = object2. Actually the object2 in our example is an anonymous function and the left side gets the type of an object because of that. Therefore, now f1 is an object(Function). The anonymous function is actually an instance of Function1[Int, Int] that means a function with 1 parameter of type Int and return value of type Int.
Calling f1 without the arguments will give us the signature of the anonymous function (Int => Int = )
Methods:
They are not objects but assigned to an instance of a class,i.e., an object. Exactly the same as method in java or member functions in c++ (as Raffi Khatchadourian pointed out in a comment to this question) and etc.
A simple example of a method is just like bellow:
def m1(x: Int) = x + x
m1(2) // 4
The line above is not a simple value assignment but a definition of a method. When you invoke this method with the value 2 like the second line, the x is substituted with 2 and the result will be calculated and you get 4 as an output. Here you will get an error if just simply write m1 because it is method and need the input value. By using _ you can assign a method to a function like bellow:
val f2 = m1 _ // Int => Int = <function1>
Here is a great post by Rob Norris which explains the difference, here is a TL;DR
Methods in Scala are not values, but functions are. You can construct a function that delegates to a method via η-expansion (triggered by the trailing underscore thingy).
with the following definition:
a method is something defined with def and a value is something you can assign to a val
In a nutshell (extract from the blog):
When we define a method we see that we cannot assign it to a val.
scala> def add1(n: Int): Int = n + 1
add1: (n: Int)Int
scala> val f = add1
<console>:8: error: missing arguments for method add1;
follow this method with `_' if you want to treat it as a partially applied function
val f = add1
Note also the type of add1, which doesn’t look normal; you can’t declare a variable of type (n: Int)Int. Methods are not values.
However, by adding the η-expansion postfix operator (η is pronounced “eta”), we can turn the method into a function value. Note the type of f.
scala> val f = add1 _
f: Int => Int = <function1>
scala> f(3)
res0: Int = 4
The effect of _ is to perform the equivalent of the following: we construct a Function1 instance that delegates to our method.
scala> val g = new Function1[Int, Int] { def apply(n: Int): Int = add1(n) }
g: Int => Int = <function1>
scala> g(3)
res18: Int = 4
Practically, a Scala programmer only needs to know the following three rules to use functions and methods properly:
Methods defined by def and function literals defined by => are functions. It is defined in page 143, Chapter 8 in the book of Programming in Scala, 4th edition.
Function values are objects that can be passed around as any values. Function literals and partially applied functions are function values.
You can leave off the underscore of a partially applied function if a function value is required at a point in the code. For example: someNumber.foreach(println)
After four editions of Programming in Scala, it is still an issue for people to differentiate the two important concepts: function and function value because all editions don't give a clear explanation. The language specification is too complicated. I found the above rules are simple and accurate.
In Scala 2.13, unlike functions, methods can take/return
type parameters (polymorphic methods)
implicit parameters
dependent types
However, these restrictions are lifted in dotty (Scala 3) by Polymorphic function types #4672, for example, dotty version 0.23.0-RC1 enables the following syntax
Type parameters
def fmet[T](x: List[T]) = x.map(e => (e, e))
val ffun = [T] => (x: List[T]) => x.map(e => (e, e))
Implicit parameters (context parameters)
def gmet[T](implicit num: Numeric[T]): T = num.zero
val gfun: [T] => Numeric[T] ?=> T = [T] => (using num: Numeric[T]) => num.zero
Dependent types
class A { class B }
def hmet(a: A): a.B = new a.B
val hfun: (a: A) => a.B = hmet
For more examples, see tests/run/polymorphic-functions.scala
The difference is subtle but substantial and it is related to the type system in use (besides the nomenclature coming from Object Oriented or Functional paradigm).
When we talk about a function, we talk about the type Function: it being a type, an instance of it can be passed around as input or output to other functions (at least in the case of Scala).
When we talk about a method (of a class), we are actually talking about the type represented by the class it is part of: that is, the method is just a component of a larger type, and cannot be passed around by itself. It must be passed around with the instance of the type it is part of (i.e. the instance of the class).
A method belongs to an object (usually the class, trait or object in which you define it), whereas a function is by itself a value, and because in Scala every value is an object, therefore, a function is an object.
For example, given a method and a function below:
def timesTwoMethod(x :Int): Int = x * 2
def timesTwoFunction = (x: Int) => x * 2
The second def is an object of type Int => Int (the syntactic sugar for Function1[Int, Int]).
Scala made functions objects so they could be used as first-class entities. This way you can pass functions to other functions as arguments.
However, Scala can also treat methods as functions via a mechanism called Eta Expansion.
For example, the higher-order function map defined on List, receives another function f: A => B as its only parameter. The next two lines are equivalent:
List(1, 2, 3).map(timesTwoMethod)
List(1, 2, 3).map(timesTwoFunction)
When the compiler sees a def given in a place where a function is needed, it automatically converts the method into an equivalent function.
A method operates on an object but a function doesn't.
Scala and C++ has Fuction but in JAVA, you have to imitate them with static methods.