What method conversion has been applied to this example? - scala

In the spec of scala 6.26.2, there are 4 kind of conversions for methods:
MethodConversions
The following four implicit conversions can be applied to methods which are not applied to some argument list.
Evaluation. A parameterless method m of type => T is always converted to type T by evaluating the expression to which m is bound.
Implicit Application. If the method takes only implicit parameters, implicit argu- ments are passed following the rules of §7.2.
Eta Expansion. Otherwise, if the method is not a constructor, and the expected type pt is a function type (Ts′) ⇒ T′, eta-expansion (§6.26.5) is performed on the expression e.
Empty Application. Otherwise, if e has method type ()T , it is implicitly applied to the empty argument list, yielding e().
Some scala code:
def hello(): String = "abc"
def world1(s: String) = s
def world2(s: => String) = s
def world3(s: () => String) = s
world1(hello)
world2(hello)
world3(hello)
My question is, for world1, world2 and world3, which conversion rule is applied to each of them?

def world1(s: String) = s
world1(hello)
Empty application: hello is evaluated as hello() and then passed as the argument of world1
def world2(s: => String) = s
world2(hello)
Eta-expansion + Evaluation: hello is expanded into a function and evaluated lazily.
def world3(s: () => String) = s
world3(hello)
Eta-expansion: hello is expanded to a Function0[String]
Eta-expansion is necessary because methods and functions are two different things, even though the scala compiler is very good at hiding this difference.
The difference comes from the fact that methods are a JVM concept, whereas first-class functions are a scala-specific concept.
You can try this out in a REPL. First, let's define a method hello
scala> def hello(s: String) = s"hello $s"
hello: (s: String)String
scala> hello.hashCode
<console>:9: error: missing arguments for method hello;
follow this method with `_' if you want to treat it as a partially applied function
hello.hashCode
^
Woops, hello is not a value (in the JVM sense)! Not having an hashcode is a proof of it.
Let's get a Function1 out of the hello method
scala> hello _
res10: String => String = <function1>
scala> (hello _).hashCode
res11: Int = 1710358635
A function is a value, so it has an hashcode.

Related

meaning of String* in scala [duplicate]

I have the following method:
def m(a: String*) = { // ... }
I'm wondering what the use is of the asterisk (*) symbol in this syntax? I'm obviously new to Scala. I googled but am probably googling the wrong thing. Any help is appreciated.
Cheers!
Its called as "var args" (variable arguments).
def concat(strs: String*): String = strs.foldLeft("")(_ ++ _)
Scala REPL
scala> def concat(strs: String*): String = strs.foldLeft("")(_ ++ _)
concat: (strs: String*)String
scala> concat()
res6: String = ""
scala> concat("foo")
res7: String = foo
scala> concat("foo", " ", "bar")
res8: String = foo bar
This is called a repeated parameter (see Section 4.6.3 of the Scala Language Specification).
Repeated Parameters allow a method to take an unspecified number of arguments of the same type T, which are accessible inside the method body bound to a parameter of type Seq[T].
In your case, inside the method m, the parameter a will be bound to a Seq[String].
That's the syntax to define a method that take a variable number of arguments.
Your m method can take 0, 1 or more arguments and these are all valid invocations:
m()
m("hello")
m("hello", "world")
You can also pass a collection to that method if you use the appropriate type hint:
val words = Seq("hello", "world")
m(words: _*)
You can play around with this code here on Scastie (where I implemented m as the concatenation of the input strings).

Scala String* type (in function args)

I have the following method:
def m(a: String*) = { // ... }
I'm wondering what the use is of the asterisk (*) symbol in this syntax? I'm obviously new to Scala. I googled but am probably googling the wrong thing. Any help is appreciated.
Cheers!
Its called as "var args" (variable arguments).
def concat(strs: String*): String = strs.foldLeft("")(_ ++ _)
Scala REPL
scala> def concat(strs: String*): String = strs.foldLeft("")(_ ++ _)
concat: (strs: String*)String
scala> concat()
res6: String = ""
scala> concat("foo")
res7: String = foo
scala> concat("foo", " ", "bar")
res8: String = foo bar
This is called a repeated parameter (see Section 4.6.3 of the Scala Language Specification).
Repeated Parameters allow a method to take an unspecified number of arguments of the same type T, which are accessible inside the method body bound to a parameter of type Seq[T].
In your case, inside the method m, the parameter a will be bound to a Seq[String].
That's the syntax to define a method that take a variable number of arguments.
Your m method can take 0, 1 or more arguments and these are all valid invocations:
m()
m("hello")
m("hello", "world")
You can also pass a collection to that method if you use the appropriate type hint:
val words = Seq("hello", "world")
m(words: _*)
You can play around with this code here on Scastie (where I implemented m as the concatenation of the input strings).

Why can't I reuse "unapply" without repeating the method signature

The following Scala code compiles fine:
val f = (input: String) => Some("result")
object Extract {
def unapply(input: String): Option[String] = f(input)
}
val Extract(result) = "a string"
But if I replace the extractor by:
object Extract {
def unapply = f
}
Then compilation fails with:
error: an unapply result must have a member `def isEmpty: Boolean
val Extract(result) = "a string"
^
Why? Where does def isEmpty: Boolean come from?
In Scala 2.10 (and before) unapply had to always return an Option or a Boolean. Since 2.11, it can return any type, so far as it has def isEmpty: Boolean and def get: <some type> methods (like Option does). See https://hseeberger.wordpress.com/2013/10/04/name-based-extractors-in-scala-2-11/ for an explanation why it's useful.
But your unapply returns a String => Some[String], which doesn't have either, and that's what the error says.
To answer your first question - isEmpty comes from internals of Option type.
def unapply = f means - create a parameterless method that returns a function. This is not a method by itself and thus you have an error.
You can further read about difference between function and method in Scala there: Difference between method and function in Scala

Class constructor declaration... Two ways of declaring the same thing?

I would like an explanation of difference for example between this declaration:
class Clazz(param1: String, param2: Integer)
and this one:
class Clazz(param1: String)(param2: Integer)
Does second declaration affect just the way of instantiating the objects or is there any deeper reason I don't know about.
One reason I thought about would be multiple variable length of parameters for example:
class Clazz(param1: String*)(param2: Integer*)
So are there any others?
#1 Type inference. It goes from left to right and is done per parameter list.
scala> class Foo[A](x: A, y: A => Unit)
defined class Foo
scala> new Foo(2, x => println(x))
<console>:24: error: missing parameter type
new Foo(2, x => println(x))
^
scala> class Foo[A](x: A)(y: A => Unit)
defined class Foo
scala> new Foo(2)(x => println(x))
res22: Foo[Int] = Foo#4dc1e4
#2 Implicit parameter list.
scala> class Foo[A](x: A)(implicit ord: scala.Ordering[A]) {
| def compare(y: A) = ord.compare(x, y)
| }
defined class Foo
scala> new Foo(3)
res23: Foo[Int] = Foo#965701
scala> res23 compare 7
res24: Int = -1
scala> new Foo(new {})
<console>:24: error: No implicit Ordering defined for java.lang.Object.
new Foo(new {})
^
In the second version you are declaring a curried primary constructor for Clazz. So the difference between the two versions is the same as difference between "normal" and curried functions in Scala, i.e.
def foo(param1: String, param2: Int)
def foo(param1: String)(param2: Int)
Most of the time both declarations can be used interchangeably but if you often need to curry function then it makes more sense to declare it in curried form. Note you can also convert a normal function or even constructor into a curried form, for e.g you could transform your normal Clazz constructor into curried form using this:
(new Clazz(_, _)).curried
You also need multiple parameter lists if you are passing an implicit value (as the keyword implicit applies to the complete parameter list)

What is the difference between def foo = {} and def foo() = {} in Scala?

Given the following constructs for defining a function in Scala, can you explain what the difference is, and what the implications will be?
def foo = {}
vs.
def foo() = {}
Update
Thanks for the quick responses. These are great. The only question that remains for me is:
If I omit the parenthesis, is there still a way to pass the function around? This is what I get in the repl:
scala> def foo = {}
foo: Unit
scala> def baz() = {}
baz: ()Unit
scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit
scala> test(foo)
<console>:10: error: type mismatch;
found : Unit
required: () => Unit
test(foo)
^
scala> test(baz)
res1: () => Unit = <function0>
Update 2012-09-14
Here are some similar questions I noticed:
Difference between function with parentheses and without
Scala methods with no arguments
If you include the parentheses in the definition you can optionally omit them when you call the method. If you omit them in the definition you can't use them when you call the method.
scala> def foo() {}
foo: ()Unit
scala> def bar {}
bar: Unit
scala> foo
scala> bar()
<console>:12: error: Unit does not take parameters
bar()
^
Additionally, you can do something similar with your higher order functions:
scala> def baz(f: () => Unit) {}
baz: (f: () => Unit)Unit
scala> def bat(f: => Unit) {}
bat: (f: => Unit)Unit
scala> baz(foo)
scala> baz(bar)
<console>:13: error: type mismatch;
found : Unit
required: () => Unit
baz(bar)
^
scala> bat(foo)
scala> bat(bar) // both ok
Here baz will only take foo() and not bar. What use this is, I don't know. But it does show that the types are distinct.
Let me copy my answer I posted on a duplicated question:
A Scala 2.x method of 0-arity can be defined with or without parentheses (). This is used to signal the user that the method has some kind of side-effect (like printing out to std out or destroying data), as opposed to the one without, which can later be implemented as val.
See Programming in Scala:
Such parameterless methods are quite common in Scala. By contrast, methods defined with empty parentheses, such as def height(): Int, are called empty-paren methods. The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state).
This convention supports the uniform access principle [...]
To summarize, it is encouraged style in Scala to define methods that take no parameters and have no side effects as parameterless methods, i.e., leaving off the empty parentheses. On the other hand, you should never define a method that has side-effects without parentheses, because then invocations of that method would look like a field selection.
Terminology
There are some confusing terminology around 0-arity methods, so I'll create a table here:
Programming in Scala
scala/scala jargon
def foo: Int
parameterless methods
nullary method
def foo(): Int
empty-paren methods
nilary method
I sounds cool to say "nullary method", but often people say it wrong and the readers will also be confused, so I suggest sticking with parameterless vs empty-paren methods, unless you're on a pull request where people are already using the jargons.
() is no longer optional in Scala 2.13 or 3.0
In The great () insert, Martin Odersky made change to Scala 3 to require () to call a method defined with (). This is documented in Scala 3 Migration Guide as:
Auto-application is the syntax of calling a nullary method without passing an empty argument list.
Note: Migration document gets the term wrong. It should read as:
Auto-application is the syntax of calling a empty-paren (or "nilary") method without passing an empty argument list.
Scala 2.13, followed Scala 3.x and deprecated the auto application of empty-paren methods in Eta-expand 0-arity method if expected type is Function0. A notable exception to this rule is Java-defined methods. We can continue to call Java methods such as toString without ().
To answer your second question, just add an _:
scala> def foo = println("foo!")
foo: Unit
scala> def test(arg: () => Unit) = { arg }
test: (arg: () => Unit)() => Unit
scala> test(foo _)
res10: () => Unit = <function0>
scala> test(foo _)()
foo!
scala>
I would recommend always start definition with a function like:
def bar {}
and only in cases, when you are forced, to change it to:
def bar() {}
Reason: Let's consider these 2 functions from a point of possible usage. How they can be infoked AND where they can be passed.
I would not call this a function at all:
def bar {}
It can be invoked as:
bar
but not as a function:
bar()
We can use this bar when we define a higher-order function with a call-by-name parameter:
def bat(f: => Unit) {
f //you must not use (), it will fail f()
}
We should remember, that => Unit - is not even a function. You absolutely cannot work with a thunk as if it's a function insofar as you cannot choose to treat it as Function value to be stored or passed around. You can only trigger evaluations of the actual argument expression (any number of them).
Scala: passing function as block of code between curly braces
A function, defined with () has a bigger scope for usage. It can be used exactly, in the same context, as bar:
def foo() = {}
//invokation:
foo
//or as a function:
foo()
It can be passed into a function with a call-by-name parameter:
bat(foo)
Additionally, if we define a higher-order function, that accepts not a call-by-name pamameter, but a real function:
def baz(f: () => Unit) {}
We can also pass foo to the baz:
baz(foo)
As we can see standard functions like foo have a bigger scope for usage. But using a functions defined without () plus defining higher-order functions, that accept call-by-name parameter, let us use more clear syntax.
If you do not try to archive a better, more readable code, or if you need ability to pass your piece of code both to function defined with a call-by-name parameter and to a function defined with a real function, then define your function as standard one:
def foo() {}
If you prefer to write more clear and readable code, AND your function has no side-effects, define a function as:
def bar {}
PLUS try to define your higher-order function to accept a call-by-name parameter, but not a function.
Only when you are forced, only in this case use the previous option.