Using FunctionX#curried - scala

I define foo:
scala> def foo(x: Int, y:Int): Int = x + y
foo: (x: Int, y: Int)Int
Then I failed to set bar equal to the curried function of foo.
scala> def bar = foo.curried
<console>:8: error: missing arguments for method foo;
follow this method with `_' if you want to treat it as a partially applied
function
def bar = foo.curried
^
What am I doing wrong?

foo is not a function, it's a method. It's not an object, it has no own methods. curried is a method on object of type FunctionN.
You have to convert it to function:
(foo _).curried
With foo _ you are creating a new object of type Function2.

Related

What does ?=> mean in Scala?

I have seen the ?=> symbol appear in Scala code and in some discussion posts about Scala 3, so I am assuming that it is a Scala 3+ symbol. Nothing appears when searching through documentation or Google, but it looks like the syntactic sugar for the Function types, so maybe it relates to types and functions. What does it mean?
The type (a: A, b: B, ..., z: Z) ?=> R basically means (using a: A, b: B, ..., z: Z) => R (I believe the latter syntax was valid at one point, but not anymore). All of those parameters become implicit parameters when you use ?=>. Similarly, a function literal (a, b, ..., z) ?=> ... makes all of the parameters to that function implicit, and they can be passed implicitly to other methods later.
Here's an example (Scastie):
case class Foo(s: String)
case class Bar(i: Int)
def baz(xyzzy: (Foo, Bar) ?=> String): Unit =
val foo = Foo("waldo")
val bar = Bar(2)
println(xyzzy(using foo, bar))
baz takes a context function. Note how xyzzy is called with the same syntax as a normal method taking a Foo and a Bar as implicit parameters (in Scala 3, blah(using bleh, bluh) is used to explicitly pass implicit arguments bleh and bluh instead of simply blah(bleh, bluh) like in Scala 2).
Here's one way we can call baz, by defining a method with implicit parameters:
def foobar(using Foo, Bar) =
val foo = summon[Foo]
val bar = summon[Bar]
s"Method - foo: $foo, bar: $bar"
baz(foobar)
We can also pass in a function literal. There are no regular parameters, so it looks a little like a by-name parameter. There are implicit instances of Foo and Bar available because of the (Foo, Bar) ?=> type of the literal.
baz {
val foo = summon[Foo]
val bar = summon[Bar]
s"Function literal - foo: $foo, bar: $bar"
}
You can also use ?=> in the function literal itself to name the implicit parameters without having to summon them and assign them to values. Since they're implicit, you can also call foobar from above because an implicit Foo and Bar are available (you can also do this in the second example despite not having named the parameters explicitly).
baz { (foo: Foo, bar: Bar) ?=>
val fromMethod = foobar
s"Explicit context function literal - foo: $foo, bar: $bar; $fromMethod"
}

What is the effect of explicitly specifying a generic apply method's type?

It's not very clear to me how adding a a Type parameter to a generic object can influence the call of its apply method. If that didn't make much sense, I have tried to formulate a simple example to express my trivial confusion.
scala> object Foo {def apply[T] = "Hello from foo"}
object Foo
scala> Foo
val res0: Foo.type = Foo$#709d6de5
scala> Foo[Int]
val res1: String = Hello from foo
Why is it only that when I specify [Int], the apply method is called, and returns "Hello from foo"
On the other hand, when I use an apply method that takes a parameter, I don't need to specify the type anymore.
scala> object Bar {def apply[T](useless: T) = "Hello from bar"}
object Bar
scala> Bar
val res2: Bar.type = Bar$#33089426
scala> Bar("Something useless")
val res3: String = Hello from bar
Why in the first case (when there were no parameters) I had to specify the type, while in the second case (when there was one useless parameter) I did not have to specify the type, for the apply to be called?
The compiler needs to know when you're referring to the object and when you're invoking the apply() method. It uses [] and/or () as the clue.
If you add an empty value parameter list to the Foo.apply then you can drop the [Int] specification.
scala> object Foo {def apply[T]() = "Hello from foo"}
defined object Foo
scala> Foo
res25: Foo.type = Foo$#332d4c4f
scala> Foo[Int]
res26: String = Hello from foo
scala> Foo()
res27: String = Hello from foo
If your apply takes no parameters, type or value, then the only way to invoke it is to specify it completely.
cala> object Baz {def apply = "Hello from Baz"}
defined object Baz
scala> Baz
res14: Baz.type = Baz$#5bd4ecec
scala> Baz()
<console>:13: error: Baz.type does not take parameters
Baz()
^
scala> Baz.apply
res16: String = Hello from Baz

Invoking Function with Implicit and Non-implicit

I'm trying to define, what I think to be a "default argument", with an implicit argument:
scala> def f(implicit x: Int, y: String) = y
f: (implicit x: Int, implicit y: String)String
Note - I tried to define implicit x: Int as the second argument, but I got a compile-time error:
scala> def f(y: String, implicit x: Int) = y
<console>:1: error: identifier expected but 'implicit' found.
def f(y: String, implicit x: Int) = y
Anyway, I define an implicit Int.
scala> implicit val x: Int = 100
x: Int = 100
Then I failed to invoke f with just a String argument:
scala> f("foo")
<console>:10: error: not enough arguments for method f:
(implicit x: Int, implicit y: String)String.
Unspecified value parameter y.
f("foo")
^
Next, I tried to invoke the f function by specifying the argument. That failed too.
scala> f(y = "foo")
<console>:10: error: not enough arguments for method f:
(implicit x: Int, implicit y: String)String.
Unspecified value parameter x.
f(y = "foo")
^
Is it possible to invoke the function f by providing an implicit and providing only a single argument for y?
Implicit parameter sections are all or nothing—either you explicitly pass every argument (assuming they don't have default values) or none of them. You need to do something like this if you want f("foo") to work:
def f(y: String)(implicit x: Int) = y
I'd be careful about this approach, though—I'm personally increasingly inclined to think that using implicits for anything except type class instances is a bad idea, and having an implicit Int value floating around is kind of scary.

Why are parenthesis required for invoking methods with default arguments?

I have a side-effect free method with default arguments that I'd like to invoke without parenthesis, e.g.:
scala> def foo(x: Int = 1) = 42
foo: (x: Int)Int
scala> foo
<console>:9: error: missing arguments for method foo in object $iw;
follow this method with `_' if you want to treat it as a partially applied function
foo
^
scala> foo()
res3: Int = 42
Is this intentional, or just a temporary limitation?
This is probably intentional so you don't get parameter blocks disappearing on you:
def foo(x: Int = 2)(y: Int = 4) = x*y
foo(3) // What does this mean???

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)