Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Scala, why can't I partially apply a function without explicitly specifying its argument types?

Tags:

scala

This produces an anonymous function, as you would expect (f is a function with three arguments):

f(_, _, _) 

What I don't understand is why this doesn't compile, instead giving a "missing parameter type" error:

f(_, _, 27) 

Instead, I need to specify the types of the underscores explicitly. Shouldn't Scala be able to infer them given that it knows what the function f's parameter types are?

like image 518
vt. Avatar asked Mar 02 '10 12:03

vt.


People also ask

What is partially applied function in Scala?

The Partially applied functions are the functions which are not applied on all the arguments defined by the stated function i.e, while invoking a function, we can supply some of the arguments and the left arguments are supplied when required.

What does => mean in Scala?

=> is syntactic sugar for creating instances of functions. Recall that every function in scala is an instance of a class. For example, the type Int => String , is equivalent to the type Function1[Int,String] i.e. a function that takes an argument of type Int and returns a String .

What is an argument in Scala?

Scala - Functions with Named Arguments Named arguments allow you to pass arguments to a function in a different order. The syntax is simply that each argument is preceded by a parameter name and an equals sign. Try the following program, it is a simple example to show the functions with named arguments.


2 Answers

References below are to the Scala Language Specification

Consider the following method:

def foo(a: Int, b: Int) = 0 

Eta Expansion can convert this to a value of type (Int, Int) => Int. This expansion is invoked if:

a) _ is used in place of the argument list (Method Value (§6.7))

val f = foo _ 

b) the argument list is omitted, and expected type of expression is a function type (§6.25.2):

val f: (Int, Int) => Int = foo 

c) each of the arguments is _ (a special case of the 'Placeholder Syntax for Anonymous Functions' (§6.23))

val f = foo(_, _)    

The expression, foo(_, 1) doesn't qualify for Eta Expansion; it just expands to (a) => foo(a, 1) (§6.23). Regular type inference doesn't attempt to figure out that a: Int.

like image 65
retronym Avatar answered Sep 17 '22 18:09

retronym


If you are thinking about partial application, I thought that this was only possible with multiple parameter lists (whereas you only have one):

def plus(x: Int)(y: Int) = x + y //x and y in different parameter lists  val plus10 = plus(10) _ //_ indicates partial application  println(plus10(2)) //prints 12 

Your example is interesting though as I was completely unaware of the syntax you describe and it appears you can have partial application with a single parameter list:

scala> def plus2(x: Int, y: Int) = x + y plus2: (x: Int,y: Int)Int  scala> val anon = plus2(_,_) anon: (Int, Int) => Int = <function2>  scala> anon(3, 4) res1: Int = 7 

So the compiler can clearly infer the type Int!

scala> val anon2 = plus2(20,_) <console>:5: error: missing parameter type for expanded function ((x$1) => plus2(20, x$1))        val anon2 = plus2(20,_)                             ^ 

Hmmm, strange! I don't seem to be able to do partial application with a single parameter list. But then if I declare the type of the second parameter, I can have partial application!

scala> val anon2 = plus2(20,_: Int) anon2: (Int) => Int = <function1>  scala> anon2(24) res2: Int = 44 

EDIT - one thing I would observe is that it seems like the following two shortenings are equivalent, in which case it's a bit more obvious that this is not a "partial application" but more like a "function pointer"

val anon1 = plus2(_,_) val anon2 = plus2 _ 
like image 24
oxbow_lakes Avatar answered Sep 18 '22 18:09

oxbow_lakes