I'm trying to have curried apply and update methods like this:
def apply(i: Int)(j: Int) = matrix(i)(j)
def update(i: Int, j: Int, value: Int) =
new Matrix(n, m, (x, y) => if ((i,j) == (x,y)) value else matrix(x)(y))
Apply method works correctly, but update method complains:
scala> matrix(2)(1) = 1
<console>:16: error: missing arguments for method apply in class Matrix;
follow this method with `_' if you want to treat it as a partially applied function
matrix(2)(1) = 1
Calling directly update(2)(1)(1) works, so it is a conversion to update method that doesn't work properly. Where is my mistake?
The desugaring of assignment syntax into invocations of update maps the concatenation of a single argument list on the LHS of the assignment with the value on the RHS of the assignment to the first parameter block of the update method definition, irrespective of how many other parameter blocks the update method definition has. Whilst this transformation in a sense splits a single parameter block into two (one on the LHS, one on the RHS of the assignment), it will not further split the left parameter block in the way that you want.
I also think you're mistaken about the example of the explicit invocation of update that you show. This doesn't compile with the definition of update that you've given,
scala> class Matrix { def update(i: Int, j: Int, value: Int) = (i, j, value) }
defined class Matrix
scala> val m = new Matrix
m: Matrix = Matrix#37176bc4
scala> m.update(1)(2)(3)
<console>:10: error: not enough arguments for method update: (i: Int, j: Int, value: Int)(Int, Int, Int).
Unspecified value parameters j, value.
m.update(1)(2)(3)
^
I suspect that during your experimentation you actually defined update like so,
scala> class Matrix { def update(i: Int)(j: Int)(value: Int) = (i, j, value) }
defined class Matrix
The update desugaring does apply to this definition, but probably not in the way that you expect: as described above, it only applies to the first argument list, which leads to constructs like,
scala> val m = new Matrix
m: Matrix = Matrix#39741f43
scala> (m() = 1)(2)(3)
res0: (Int, Int, Int) = (1,2,3)
Here the initial one-place parameter block is split to an empty parameter block on the LHS of the assignment (ie. the ()) and a one argument parameter block on the RHS (ie. the 1). The remainder of the parameter blocks from the original definition then follow.
If you're surprised by this behaviour you won't be the first.
The syntax you're after is achievable via a slightly different route,
scala> class Matrix {
| class MatrixAux(i : Int) {
| def apply(j : Int) = 23
| def update(j: Int, value: Int) = (i, j, value)
| }
|
| def apply(i: Int) = new MatrixAux(i)
| }
defined class Matrix
scala> val m = new Matrix
m: Matrix = Matrix#3af30087
scala> m(1)(2) // invokes MatrixAux.apply
res0: Int = 23
scala> m(1)(2) = 3 // invokes MatrixAux.update
res1: (Int, Int, Int) = (1,2,3)
My guess is, that it is simply not supported. Probably not due to an explicit design decision, because I don't see why it shouldn't work in principle.
The translation concerned with apply, i.e., the one performed when converting m(i)(j) into m.apply(i, j) seems to be able to cope with currying. Run scala -print on your program to see the code resulting from the translation.
The translation concerned with update, on the other hand, doesn't seem to be able to cope with currying. Since the error message is missing arguments for method apply, it even looks as if the currying confuses the translator such that it tries to translate m(i)(j) = v into m.apply, but then screws up the number of required arguments. scala -print unfortunately won't help here, because the type checker terminates the translation too early.
Here is what the language specs (Scala 2.9, "6.15 Assignments") say about assignments. Since currying is not mentioned, I assume that it is not explicitly supported. I couldn't find the corresponding paragraph for apply, but I guess it is purely coincidental that currying works there.
An assignment f(args) = e with a function application to the left of
the ‘=’ operator is interpreted as f.update(args, e), i.e. the
invocation of an update function defined by f.
Related
I’m learning scala and read this concept called ‘currying’. I know it is used to divide the parameters in a function and pass them one by one. So from what I understood I tried creating a simple basic currying function below:
def add_num(a:Int,b:Int)(c:Int):Int={a+b+c}
add_num(10,20)
add_num(10)
But it gives me an error when I call the function with values 10 and 20. What i understood is it will remember the values and then I can pass the third value as 10 separately. I’m unable to understand this concept. Can someone help me in understanding this concept in most basic terms.
Error is missing argument list for method add_num. Unsupplied methods are only converted to functions when a function type is executed.
A curried function is applied to multiple argument lists, instead of just
one. An example of a non-curried function, which adds two Int parameters, x and y:
scala> def plainOldSum(x: Int, y: Int) = x + y
plainOldSum: (x: Int, y: Int)Int
scala> plainOldSum(1, 2)
res4: Int = 3
A similar function that’s curried:
scala> def curriedSum(x: Int)(y: Int) = x + y
curriedSum: (x: Int)(y: Int)Int
scala> curriedSum(1)(2)
res5: Int = 3
What's happening here is that when you invoke curriedSum, you actually
get two traditional function invocations back-to-back. The first function
invocation takes a single Int parameter named x, and returns a function
value for the second function. This second function takes the Int parameter
y.
Here's a function named first that does in spirit what the first traditional
function invocation of curriedSum would do:
scala> def first(x: Int) = (y: Int) => x + y
first: (x: Int)Int => Int
Applying the first function to 1—in other words, invoking the first function
and passing in 1—yields the second function:
scala> val second = first(1)
second: Int => Int = <function1>
Applying the second function to 2 yields the result:
scala> second(2)
res6: Int = 3
These first and second functions are just an illustration of the currying
process. They are not directly connected to the curriedSum function. Nevertheless,
there is a way to get an actual reference to curriedSum's "second"
function. You can use the placeholder notation to use curriedSum in a partially
applied function expression, like this:
scala> val onePlus = curriedSum(1)_
onePlus: Int => Int = <function1>
The underscore in curriedSum(1)_ is a placeholder for the second parameter
list.2 The result is a reference to a function which, when invoked, adds one
to its sole Int argument and returns the result:
scala> onePlus(2)
res7: Int = 3
And here's how you'd get a function that adds two to its sole Int argument:
scala> val twoPlus = curriedSum(2)_
twoPlus: Int => Int = <function1>
scala> twoPlus(2)
res8: Int = 4
This question already has answers here:
Understanding Currying in Scala
(3 answers)
Closed 4 years ago.
def sum(f: Int => Int): (Int, Int) => Int = {
def sumF(a: Int, b: Int): Int =
if (a > b) 0
else f(a) + sumF(a + 1, b)
sumF
}
def sumCubes = sum(a => a * a * a)
sumCubes // output Function2
sumCubes(1,10) // output 3025.
sumCubes() // doesn't work
I feel I dont understand currying well enough. In the first statement , we are calling sumCubes without parameters , hence sum gets called with the anonymous function as parameter and returns a function2.
Whats really happening in 2nd and 3rd invocation ,
Why are we able to do
sum(a => a * a * a)(1,10)
but not
sumCubes()(1,10)
My understanding is that in sum(a => a * a * a)(1,10) , we are partially applying sum to the anonymous function, which returns a Function2 ,which is applied to the second pair of parameters (1,10) and hence we are getting 3025,
However the same should happen in case of sumCubes()(1,10) , invoking sumCubes without parameters first , would inturn invoke sum with the anonymous function and the Function2 returned would be applied to (1,10)
Why does sumCubes(1,10) work but not sumCubes()(1,10) , shouldn't sumCubes and sumCubes() mean the same thing , invocation of function sumCubes. Also if a simple reference sumCubes is invoking it , how can I pass it around. I feel like I am not understanding something fundamental about Scala.
Scala's methods can have multiple argument lists.
For example, here is a method foo that has ten argument lists, of which the first seven are empty:
def foo()()()()()()()(a: Int)(b: Int)(c: Int): Int = a + b + c
You can invoke it as follows:
println(foo()()()()()()()(1)(20)(300))
and it will print 321.
Note that when you invoke a method, the number of argument lists, as well as the number of arguments in each list (and also their types) have to match the declaration.
Another example. The following method has two argument lists:
def bar(i: Int)(f: Int => Int) = f(i)
you can invoke it as follows:
bar(42)(x => x * x)
but not as
bar()(x => x * x)
bar()(42)(x => x * x)
bar(42)()
or anything like it.
Completely analogously, if you have defined a method with zero argument lists
def baz = (x: Int) => x * x
then you must invoke it with zero argument lists too:
baz
Since it returns an Int => Int function, you can of course apply the result to an Int:
baz(42)
which is the same as (baz)(42), but you cannot do the following:
baz()(42)
because baz itself has no argument lists, and () does not contain a single integer argument.
Note that all of the above is actually a simplification: under certain circumstances, methods that have an empty argument list can be called without parentheses, i.e. def foo(): Unit = ... can be invoked as foo, without (). This is a somewhat strange feature, and I can't say exactly why it's there. My best guess would be: it has something to do with java-interop, where you really want to omit parentheses on zero-ary getters.
I am working on spark and not an expert in scala. I have got the two variants of map function. Could you please explain the difference between them.?
first variant and known format.
first variant
val.map( (x,y) => x.size())
Second variant -> This has been applied on tuple
val.map({case (x, y) => y.toString()});
The type of val is RDD[(IntWritable, Text)]. When i tried with first function, it gave error as below.
type mismatch;
found : (org.apache.hadoop.io.IntWritable, org.apache.hadoop.io.Text) ⇒ Unit
required: ((org.apache.hadoop.io.IntWritable, org.apache.hadoop.io.Text)) ⇒ Unit
When I added extra parenthesis it said,
Tuples cannot be directly destructured in method or function parameters.
Well you say:
The type of val is RDD[(IntWritable, Text)]
so it is a tuple of arity 2 with IntWritable and Text as components.
If you say
val.map( (x,y) => x.size())
what you're doing is you are essentially passing in a Function2, a function with two arguments to the map function. This will never compile because map wants a function with one argument. What you can do is the following:
val.map((xy: (IntWritable, Text)) => xy._2.toString)
using ._2 to get the second part of the tuple which is passed in as xy (the type annotation is not required but makes it more clear).
Now the second variant (you can leave out the outer parens):
val.map { case (x, y) => y.toString() }
this is special scala syntax for creating a PartialFunction that immediately matches on the tuple that is passed in to access the x and y parts. This is possible because PartialFunction extends from the regular Function1 class (Function1[A,B] can be written as A => B) with one argument.
Hope that makes it more clear :)
I try this in repl:
scala> val l = List(("firstname", "tom"), ("secondname", "kate"))
l: List[(String, String)] = List((firstname,tom), (secondname,kate))
scala> l.map((x, y) => x.size)
<console>:9: error: missing parameter type
Note: The expected type requires a one-argument function accepting a 2-Tuple.
Consider a pattern matching anonymous function, `{ case (x, y) => ... }`
l.map((x, y) => x.size)
maybe can give you some inspire.
Your first example is a function that takes two arguments and returns a String. This is similar to this example:
scala> val f = (x:Int,y:Int) => x + y
f: (Int, Int) => Int = <function2>
You can see that the type of f is (Int,Int) => Int (just slightly changed this to be returning an int instead of a string). Meaning that this is a function that takes two Int as arguments and returns an Int as a result.
Now the second example you have is a syntactic sugar (a shortcut) for writing something like this:
scala> val g = (k: (Int, Int)) => k match { case (x: Int, y: Int) => x + y }
g: ((Int, Int)) => Int = <function1>
You see that the return type of function g is now ((Int, Int)) => Int. Can you spot the difference? The input type of g has two parentheses. This shows that g takes one argument and that argument must be a Tuple[Int,Int] (or (Int,Int) for short).
Going back to your RDD, what you have is an Collection of Tuple[IntWritable, Text] so the second function will work, whereas the first one will not work.
Being new to Scala (2.9.1), I have a List[Event] and would like to copy it into a Queue[Event], but the following Syntax yields a Queue[List[Event]] instead:
val eventQueue = Queue(events)
For some reason, the following works:
val eventQueue = Queue(events : _*)
But I would like to understand what it does, and why it works? I already looked at the signature of the Queue.apply function:
def apply[A](elems: A*)
And I understand why the first attempt doesn't work, but what's the meaning of the second one? What is :, and _* in this case, and why doesn't the apply function just take an Iterable[A] ?
a: A is type ascription; see What is the purpose of type ascriptions in Scala?
: _* is a special instance of type ascription which tells the compiler to treat a single argument of a sequence type as a variable argument sequence, i.e. varargs.
It is completely valid to create a Queue using Queue.apply that has a single element which is a sequence or iterable, so this is exactly what happens when you give a single Iterable[A].
This is a special notation that tells the compiler to pass each element as its own argument, rather than all of it as a single argument. See here.
It is a type annotation that indicates a sequence argument and is mentioned as an "exception" to the general rule in section 4.6.2 of the language spec, "Repeated Parameters".
It is useful when a function takes a variable number of arguments, e.g. a function such as def sum(args: Int*), which can be invoked as sum(1), sum(1,2) etc. If you have a list such as xs = List(1,2,3), you can't pass xs itself, because it is a List rather than an Int, but you can pass its elements using sum(xs: _*).
For Python folks:
Scala's _* operator is more or less the equivalent of Python's *-operator.
Example
Converting the scala example from the link provided by Luigi Plinge:
def echo(args: String*) =
for (arg <- args) println(arg)
val arr = Array("What's", "up", "doc?")
echo(arr: _*)
to Python would look like:
def echo(*args):
for arg in args:
print "%s" % arg
arr = ["What's", "up", "doc?"]
echo(*arr)
and both give the following output:
What's
up
doc?
The Difference: unpacking positional parameters
While Python's *-operator can also deal with unpacking of positional parameters/parameters for fixed-arity functions:
def multiply (x, y):
return x * y
operands = (2, 4)
multiply(*operands)
8
Doing the same with Scala:
def multiply(x:Int, y:Int) = {
x * y;
}
val operands = (2, 4)
multiply (operands : _*)
will fail:
not enough arguments for method multiply: (x: Int, y: Int)Int.
Unspecified value parameter y.
But it is possible to achieve the same with scala:
def multiply(x:Int, y:Int) = {
x*y;
}
val operands = (2, 4)
multiply _ tupled operands
According to Lorrin Nelson this is how it works:
The first part, f _, is the syntax for a partially applied function in which none of the arguments have been specified. This works as a mechanism to get a hold of the function object. tupled returns a new function which of arity-1 that takes a single arity-n tuple.
Futher reading:
stackoverflow.com - scala tuple unpacking
We have partially applied functions in Scala-
def sum(a:Int,b:Int,c:Int) = a+b+c
val partial1 = sum(1,_:Int,8)
I was wondering what are the advantages of using Partially applied functions. Or is it just a syntactical addition?
About partially applied function in general, the book "Programming in Scala, 2nd edition" mentions:
Another way to think about this kind of expression, in which an underscore
is used to represent an entire parameter list, is as a way to transform a
def into a function value.
For example, if you have a local function, such as sum(a: Int, b: Int, c: Int): Int, you can “wrap” it in a function value whose apply method has the same parameter list and result types.
scala> def sum(a: Int, b: Int, c: Int) = a + b + c
sum: (a: Int,b: Int,c: Int)Int
scala> val a = sum _
a: (Int, Int, Int) => Int = <function3>
(Here, a(1, 2, 3) is a short form for:
scala> a.apply(1, 2, 3)
res12: Int = 6
)
Although you can’t assign a method or nested function to a variable, or pass it as an argument to another function, you can do these things if you wrap the method or nested function in a function value by placing an underscore after its name.
The advantage is that sum(1,_,8) is less to type and read than x => sum(1,x,8).
That's all there is to it.
sum(1,_,8) is less to type and read than x => sum(1,x,8)
However, neither is legal; you must provide the parameter type.