I am doing the Scala Coursera course, and lectures seem to be missing an explanation of how multiple parameter lists really work.
He makes claims like the averageDamp() function below could be called with just the first argument (f), allowing you to call it with the second later. It seems though that you need to do partial binding explicitly by following the call with "_".
However, if the partial binding call is being passed into another function that accepts a function with a signature matching the partially bound function, it will implicitly accept it, no "_" necessary.
Yet he doesn't use the term partial binding at all, just saying there is a special syntax in Scala for basically returning a closure, when in reality it is just partial binding. Or not?
scala> def averageDamp(f: Double => Double)(x: Double) = (x+f(x))/2
scala> def fixedPoint(f: Double => Double)(x: Int) = f(x)+1
scala> fixedPoint(averageDamp(x=>x+1))(2)
res29: Double = 3.5
scala> averageDamp(x=>x+1)
<console>:19: error: missing arguments for method averageDamp;
follow this method with `_' if you want to treat it as a partially applied function
averageDamp(x=>x+1)
A non-partial binding version of averageDamp might be like:
def averageDamp(f: Double => Double): (Double => Double) =
def inner(x: Double): Double =
(x+f(x))/2
inner
I guess my question is...is the multi-parameter list version of averageDamp() being passed into another function just implicit partial binding...or is this really some kind of special Scala syntax for returning an inner function/closure?
Yet he doesn't use the term partial binding at all, just saying there is a special syntax in Scala for basically returning a closure, when in reality it is just partial binding... is the multi-parameter list version of averageDamp() being passed into another function just implicit partial binding...or is this really some kind of special Scala syntax for returning an inner function/closure?
Why do you think it's one or the other? Supplying only some of parameter lists is a special syntax for partial application (not "binding", usually) of methods with multiple parameter lists.
Related
Why call to method whose all parameters has default values is not the same than calling a method without parameter in scala?
Example:
scala> def a(a:Int=1)=print(a)
a: (a: Int)Unit
scala> def b=print(1)
b: Unit
scala> a
<console>:13: error: missing argument list for method a
Unapplied methods are only converted to functions when a function type
is expected.
You can make this conversion explicit by writing `a _` or `a(_)`
instead of `a`.
a
^
scala> b
1
However
scala>a()
1
works ok.
Shouldn't be the same call?
Scala enable Arity-0(a) method to omit parentheses.
https://docs.scala-lang.org/style/method-invocation.html#arity-0
I can think of at least one problem caused by not needing to write parenthesis. Consider the following:
val xs = List(1, 2, 3, 4)
def myFunc(x: Int = 42) = 2 * x
val ys = xs.map(myFunc)
Eta expansion is happening in my example, method is lifted into function. But if it was possible to invoke function with default parameters this way, syntax would be ambigous at least in this case. (I know that here invocation would lead to wrong argument type of map function, so in theory it is possible to resolve this ambiguity here, but it would mean that type of expression would have impact on the syntax interpretation, which is handled before type-checking in any language i know)
If you don't add a parenthesis after a, that will have several meanings.
a(): Unit
a(_): Int => Unit
Which one do you mean? Hence it force you to add parenthesis.
In Scala, a method can have zero or more parameter lists, each of which has zero or more parameters. If you want to call a method, you have to supply matching argument lists with matching arguments to the parameters and parameter lists.
In your case, you defined the method with one parameter list, ergo you need to call it with one argument list.
Shouldn't be the same call?
No, they are not the same. The first call has zero argument lists, the second call has one argument list. That's different.
There are some cases where Scala lets you call methods with a single empty parameter list by supplying no argument lists. The reason for this is simple convenience: you want to call Java getters (which are defined with an empty parameter list) the same way as Scala getters (which are defined without a parameter list). But, this doesn't work in general.
I wrote the following simple program:
import java.util.{Set => JavaSet}
import java.util.Collections._
object Main extends App {
def test(set: JavaSet[String]) = ()
test(emptySet()) //fine
test(emptySet) //error
}
DEMO
And was really surprised the the final line test(emptySet) was not compiled. Why? What is the difference between test(emptySet())? I thought in Scala we could omit parenthesis freely in such cases.
See Method Conversions in Scala specification:
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 arguments are passed following the rules here.
Eta Expansion
Otherwise, if the method is not a constructor, and the expected type pt
is a function type (Ts′)⇒T′, eta-expansion 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().
The one you want is "Empty Application", but it's only applied if none of the earlier conversions are, and in this case "Eta Expansion" happens instead.
EDIT: This was wrong and #Jasper-M's comment is right. No eta-expansion is happening, "Empty Application" is just inapplicable to generic methods currently.
I'm a beginner of Scala who is struggling with Scala syntax.
I got the line of code from https://www.tutorialspoint.com/scala/higher_order_functions.htm.
I know (x: A) is an argument of layout function
( which means argument x of Type A)
But what is [A] between layout and (x: A)?
I've been googling scala function syntax, couldn't find it.
def layout[A](x: A) = "[" + x.toString() + "]"
It's a type parameter, meaning that the method is parameterised (some also say "generic"). Without it, compiler would think that x: A denotes a variable of some concrete type A, and when it wouldn't find any such type it would report a compile error.
This is a fairly common thing in statically typed languages; for example, Java has the same thing, only syntax is <A>.
Parameterized methods have rules where the types can occur which involve concepts of covariance and contravariance, denoted as [+A] and [-A]. Variance is definitely not in the scope of this question and is probably too much for you too handle right now, but it's an important concept so I figured I'd just mention it, at least to let you know what those plus and minus signs mean when you see them (and you will).
Also, type parameters can be upper or lower bounded, denoted as [A <: SomeType] and [A >: SomeType]. This means that generic parameter needs to be a subtype/supertype of another type, in this case a made-up type SomeType.
There are even more constructs that contribute extra information about the type (e.g. context bounds, denoted as [A : Foo], used for typeclass mechanism), but you'll learn about those later.
This means that the method is using a generic type as its parameter. Every type you pass that has the definition for .toString could be passed through layout.
For example, you could pass both int and string arguments to layout, since you could call .toString on both of them.
val i = 1
val s = "hi"
layout(i) // would give "[1]"
layout(s) // would give "[hi]"
Without the gereric parameter, for this example you would have to write two definitions for layout: one that accepts integers as param, and one that accepts string as param. Even worse: every time you need another type you'd have to write another definition that accepts it.
Take a look at this example here and you'll understand it better.
I also recomend you to take a look at generic classes here.
A is a type parameter. Rather than being a data type itself (Ex. case class A), it is generic to allow any data type to be accepted by the function. So both of these will work:
layout(123f) [Float datatype] will output: "[123]"
layout("hello world") [String datatype] will output: "[hello world]"
Hence, whichever datatype is passed, the function will allow. These type parameters can also specify rules. These are called contravariance and covariance. Read more about them here!
Scala appears to have different semantics for regular value assignment versus assignment during an extraction. This has created some very subtle runtime bugs for me as my codebase has migrated over time.
To illustrate:
case class Foo(s: String)
def anyRef(): AnyRef = { ... }
val Foo(x) = anyRef() // compiles but throws exception if anyRef() is not a Foo
val f: Foo = anyRef() // does not compile
I don't see why the two val assignment lines would be imbalanced with regard to compile/runtime behavior.
Some I am curious: Is there a reason for this behavior? Is it an undesirable artifact of the way the extraction is implemented?
(tested in Scala 2.11.7)
Yes, there is.
In the case of an extractor you are specifying a pattern that you expect to match at this position. This is translated to a call of an extractor method from Any to Option[String] and this method can be called with the value of type AnyRef you provide. You are just asserting, that you do indeed get a result and not "None".
In the other line you are using a type annotation, i.e. you are specifying the type of "f" explicitly. But then you are assigning an incompatible value.
Of course the compiler could add implicit type casts but making type casts so easy would not really suit a language like Scala.
You should also keep in mind that extractors have nothing to do with types. In the Pattern Foo(x) the name Foo has nothing to do with the type Foo. It is just the Name of an extractor method.
Using patterns in this way is of course a quite dynamic feature, but I think it is intentional.
From my understanding, a partially applied function are functions, which we can invoke without
passing all/some of the required arguments.
def add(x:Int, y:Int) = x + y
val paf = add(_ :Int, 3)
val paf1 = add(_ :Int, _ :Int)
In the above example, paf1 refers to partially applied function with all the arguments missing and I can invoke is using: paf1(10,20) and the original function can be invoked using add(10,20)
My question is, what is the extra benefit of creating a partially applied function with all the arguments missing, since the invocation syntax is pretty much the same? Is it just to convert methods into first class functions?
Scala's def keyword is how you define methods and methods are not functions (in Scala). So your add is not a first-class function entity the way your paf1 is, even if they're semantically equivalent in what they do with their arguments in producing a result.
Scala will automatically use partial application to turn a method into an equivalent function, which you can see by extending your example a bit:
def add(x: Int, y: Int) = x + y
...
val pa2: (Int, Int) => Int = add
pa2: (Int, Int) => Int = <function2>
This may seem of little benefit in this example, but in many cases there are non-explicit constraints indicating a function is required (or more accurately, constraints specified explicitly elsewhere) that allow you to simply give a (type-compatible) method name in a place where you need a function.
There is a difference between Methods and functions.
If you look at the declaration of List.map for example, it really expects a function. But the Scala compiler is smart enough to accept both methods and functions.
A quote from here
this trick ... for coercing a method into something where a function is expected, is so easy that even the compiler can detect and do it. In fact, this automatic coercion got an own name – it’s called Eta expansion.
On the other hand, have a look at Java 8; as far as I can tell, it's not that easy there.
Update: the question was, Why would I ever want an eta-expanded method? One of the great rhetorical strategies in the Scala bible is that they lead you to an example over many pages. I employ the Exodus metaphor below because I just saw "The Ten Commandments" with Charlton Heston. I'm not pretending that this answer is more explanatory than Randall's.
You might need someone with lesser rep to note that the big build-up in the bible's book of Exodus is to:
http://www.artima.com/pins1ed/first-steps-in-scala.html#step6
args foreach println.
The previous step among the "first steps" is, indeed,
args foreach (arg => println(arg))
but I'm guessing no one does it that way if the type inference gods are kind.
From the change log in the spec: "a partially unapplied method is now designated m _ instead
of the previous notation &m." That is, at a certain point, the notion of a "function ptr" became a partial function with no args supplied. Which is what it is. Update: "metaphorically."
I'm sure others can synthesize a bunch of use-cases for this, but really it's just a consequence of the fact that functions are values. It would be much weirder if you couldn't pass a function around as a normal value.
Scala's handling of this stuff is a little clunky. Partial application is usually combined with currying. I consider it a quirk that you can basically eta-expand any expression using _. What you're effectively doing (modulo Scala's syntactic quirks around currying) by writing add(_ : Int, _ : Int) is writing (x : Int) => (y : Int) => add(x, y). I'm sure you can think of instances where the latter definition might be useful in a program.