scala> def sum(a:Int)={a} //I have defined the function with a single parameter
sum: (a: Int)Int
sum{val b=10+20} //passing the parameter as expression block
Getting error
scala> sum{val b=10+20}
<console>:9: error: type mismatch;
found : Unit
required: Int
sum{val b=10+20}
Why is it expecting Unit here?
The error is that {val b = 10 + 20} is of type Unit while sum is expecting an Int.
You can either call sum directly without assigning the variable:
sum(10 + 20)
> 30
Or make the block return an Int, like:
sum{
val b = 10 + 20
b // return b, which is an Int
}
> 30
You do not pass an expression but a block with one declaration. Try:
sum(10+20)
You are experiencing a weird combination of syntax error and type-system convention.
The curly braces mark a block (see e.g. the body of your sum function declaration). Function arguments can be passed in juxtaposition or using parenthesis. That is your syntax error.
The type system convention allows languages with side-effects to gently insert these effects into basically any expression. This happens by treating the composition of statements (i.e. the semicolon) as "evaluate these expression but do nothing with the result, then evaluate the next expression". The nothing as result part is combined with the unit type for statements that do not compute anything.
def sum(a:Int)={a}
What this statement does is create a method that takes one Int-typed parameter and returns it.
sum{val b=10+20}
Here you pass a value to your defined method sum. What you're passing is an expression. Scala will, effectively, 'rewrite' that expression before applying it to sum. If we write the expression being passed (val b=10+20) in the REPL we will see what it gets rewritten to:
scala> val b=10+20
b: Int = 30
But this is only part of the story, because the assignment of a value to a name returns nothing. We can see this by putting brackets around the assignment:
scala> { val b=10+20 }
Note that the REPL displays nothing when this happens.
Because the re-written expression includes this evaluation, you're actually passing a scope to the function, in which b is defined. However, that scope doesn't 'return' an Int to be bound to a. To return the result of the b assignment, you have to do one of two things. Either you have to have a call to the variable be the last call in the expression, or have the last call be the calculation itself, and don't assign that to a variable:
sum{ val b=10+20; b } // Explicitly call the bound variable
sum{ 10 + 20 } // Don't assign the variable
Related
Find Square of an integer 'x'.
Without Placeholder
var square = (x:Int) => x*x
square(3) gives desired output 9.
With Placeholder var square = (_:Int)*(_:Int)
square(3) gives Error
Not enough arguments for method apply: (v1: Int, v2: Int)Int in trait Function2.
Unspecified value parameter v2.
Internally what is happening?
No, each occurrence of _ represents the next argument in the argument list for the function.
(_:Int)*(_:Int) is a function that takes two Int arguments and multiplies them.
I have the following Code.
import scala.collection.mutable.MutableList
val x = MutableList[Int]()
(1 to 10).foreach(x+=1)
I get the java.lang.IndexOutOfBoundsException: 1 error.
but,
(1 to 10).foreach(println) this does not throw any error.
the indexOutOfBoundException can be solved by using lambda Operator as follows:
(1 to 10).foreach(_ => x+=1)
Everything works fine with this.
My questions are :
1. Why do i need to use lambda operator in first case unlike second one?
2. Why the compiler throws IndexOutOfBoundException, i suppose this is not the correct context for this Exception.
What happens is a few little conveniences in the library conspiring to bite you.
foreach signature is
def foreach(f: A => Unit): Unit
In your case, A is Int, so it needs a function which takes an Int and returns Unit. Fine with println. Note you have just written println, not println(something), which would not have been a function.
One would expect x += 1 to be just an instruction, so it would have type Unit, not a function, not a valid argument of foreach, and one would get a helpful compile-time error. But += in MutableList actually returns the list, which is convenient as it makes chaining operations easier:
def +=(elem: A): this.type
So the type of x+= 1 is MutableList[Int]. One will still expect a compilation error, not a function. Except that MutableLists (all Seqs actually) are functions, with Int parameters, returning the type of the Seq's elements. The function simply returns the i-th element. Again, that may be convenient, you may simply pass the seq where a function is expected, instead of having to write i => seq(i). Now you have a function, with an Int parameter, what foreach expects.
Still, it does not returns Unit, but Int. However, scala will accept that as an Int => Unit, just discarding the value. So it compiles.
Now to what it does: first, it evaluates the argument in foreach, so it calls x+=1, getting the list x, which now contains an element. It will then call this function, which is the access to the i-th element with arguments ranging from 1 to 10). Doing that, it would not add values to the list, but just access elements at the given indexes. It then fails immediately, as the list contains just one element, at index 0, so calling with 1 throws the IndexOutOfBoundException.
This code
(1 to 30).foreach { x =>
println(x)
println
}
does what I'd expect: it prints each of 1 to 30, interspersed with blanks. I'm pretty clear on what's going on here, I think: I'm passing an anonymous function that first prints its argument, and then prints a blank line.
What I don't understand is why this doesn't do the same:
(1 to 30).foreach {
println _
println
}
It looks equivalent to me. The underscore should represent the first and only argument to the function; and the function prints its argument, and then prints a blank line. But when I run this second version, I don't get the blank lines.
What causes this difference?
The first variant is straightforward:
In the first line, apply println on x.
In the second line, apply the no-argument println (this prints the extra newline).
With the second variant you effectively tell Scala to do this:
In the first line, define a function object from println().
Subsequently, do nothing with this newly created object.
In the second line, apply println to the argument (the element of the
sequence).
The confusion stems from the assumption that println(x) and println _ are equivalent. They are different. The funcId _ syntax defines a new function based on funcId, it is not the same as using the "underscore argument" notation when calling a function.
There is a number of things going on here.
First, of all the parameter placeholder syntax can only be used within outer parentheses of the lambda definition. It cannot be used within parentheses of the method calls that you perform within the lambda definition.
Here is an example to demonstrate this point.
val a = (1 to 10).map(_ + 1)
This will work.
val b = (1 to 10).map(math.sin(_ + 1))
This will not work.
Therefore your code does not use parameter placeholder syntax at all. It instead uses partially applied functions.
For example
(1 to 10).foreach(println _)
is functionally equal to
val a = println (_ : Int)
(1 to 10).foreach(a)
Also when a method name is used within lambda expression the underscore can be omitted. Scala will still generate the partially applied method.
Therefore
(1 to 10).foreach(println)
is equal to
(1 to 10).foreach(println _)
And therefore your code is equal to
val a = println (_ : Int)
(1 to 10).foreach{
a
a
}
And because {a a} returns a, it is equal to
val a = println (_ : Int)
(1 to 10).foreach(a)
To add to other answers, there actually exists a way to use println(_) and not to declare x parameter:
(1 to 30).foreach {
println(_: Int)
println
}
Here foreach parameter is function, which firstly invokes println(_) for range element, and then passes println(Int) result (which is (): Unit) to another function, _ => println, which ignores it's argument and prints new line.
I'm basically new to functional programming and scala, and the following question might possibly look stupid.
val f = (a:Int) => a+1
In the above snippet, should I consider f to be a function or a variable? Coming from a C/C++ background, the first thought that occurs is that f is a variable that stores the return value of the anonymous function, but I think that's not the correct way to interpret it Any explanation would be really helpful.
(Some of the terminologies I used above might be wrong with respect to scala/functional programming, kindly bear with it)
Here, f is a variable that stores a function. It's really no different from saying any of the following:
val a = 4 // `a` is a variable storing an Int
val b = "hi" // `b` is a variable storing a String
val f = (a:Int) => a+1 // `f` is a variable storing a function
You can also confirm this with the REPL:
scala> val f = (a:Int) => a+1
f: Int => Int = <function1>
So this is telling you that f has the type Int => Int. Or in other words, f is a function that takes one argument, an Int, and returns an Int.
Since f is a variable, you can call methods on it or pass it as an argument to functions that expect its type:
a + 3 // here I'm calling the `+` method on `a`, which is an Int
f(3) // here I'm calling the `apply` method on `f`, which is a function `Int => Int`
f(a) // the function `f` expects an `Int`, which `a` is
(1 to 3).map(f) // the `map` method expects a function from Int to Int, like `f`
Yes, like dhg said, f is a variable (that can't be changed) that stores a function.
However, there's a subtlety here:
... the first thought that occurs is that f is a variable that stores the
return value of the anonymous function
f actually stores the function, not the result. So you can give it different inputs, and get different outputs. So, you can use it like f(7) and then f(5). Functions in Scala are objects, so can be assigned to variables, passed as parameters, etc.
I recently posted about function literals, which may be helpful to you.
f is a value denoting a function literal.
In the statement, the right-hand-side is a function literal. The left-hand-side binds it to a name which is then called value (the val keyword is similar to let in LISP). Now the function is associated with the symbol f, so you can refer to that function by using this symbol f.
I disagree with the other answers which suggest that f should be called a variable. f is a value, because it is fixed to the right-hand-side term which is determined only once and cannot change. On the contrary a variable, introduced with var, allows you to re-assign values to a symbol:
var f = (i: Int) => i + 1
Where var begins a variable definition, f is the name or symbol of the variable, there could be an optional : ... defining type of the variable (if you leave that out, the type is automatically inferred from the assignment), and = ... defines the value initially assigned to the variable.
So when one says value, don't confuse this with a numeric constant, it is simply an entity that doesn't change. A function can be a value too, because f then always denotes this same identical function, even if you can feed that function with different arguments which yield different results.
Now with the var you can re-assign its right-hand-side:
f(2) // --> 3
f = (i: Int) => i * 2 // assign a new function to the variable f.
f(2) // --> 4
Functional programming is all about avoiding variables (re-assignments).
It is also possible to define a function without assigning it at all (to a value or a variable). The following defines such a function and immediately calls it with argument 4:
{ i: Int => i + 1 } apply 4 // --> 5
although that is seldom useful as a statement per se, but you will see 'plain' functions often when calling a method that expects a function argument. For instance
val s = List(1, 2, 3)
s.map { (i: Int) => i + 1 } // --> List(2, 3, 4)
s.map { _ + 1 } // equivalent
s.map( _ + 1 ) // equivalent
I am attempting to add an update method to the Symbol class.
class SymbolUpdate(s: Symbol) {
def update(i: Int) = s.name + i
}
implicit def toSymbolUpdate(s: Symbol) = new SymbolUpdate(s)
But when I run the code I get the following
scala> 's = 1
<console>:327: error: value update is not a member of object Symbol
's = 1
^
But it does work when I call the method directly.
scala> 's.update(1)
res41: java.lang.String = s1
Or if I explicitly put an empty argument array.
scala> 's() = 1
res42: java.lang.String = s1
Not sure what the problem is with my code?
According to the Scala Language Spec:
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.
It's especially clear if you read the corresponding section in Programming in Scala:
Similarly, when an assignment is made to a variable to which parenthesis and one or more arguments have been applied, the compiler will transform that into an invocation of an update methods that takes the arguments in parenthesis as well as the object to the right of the equals sign.
Together, I take it to mean that the parenthesis are required.