Is there a difference between whether I use def or val while defining a partial function? I thought that probably def will be evaluated everytime (like a function call) while val will be evaluated only once but that doesn't seem to be the case.
scala> def add(x:Int)(y:Int) = {println("inadd");x+y}
add: (x: Int)(y: Int)Int
//def
scala> def add2ToDef= add(2) _
add2ToDef: Int => Int
//val
scala> val add2ToVal= add(2) _
add2ToVal: Int => Int = $$Lambda$1032/1413020227#512abf25
scala> add2ToDef(3)
inadd
res0: Int = 5
scala> add2ToVal(3)
inadd
res1: Int = 5
scala> add2ToDef(4)
inadd
res2: Int = 6
scala> add2ToVal(5)
inadd
res3: Int = 7
Essentially the same difference as between val and def in general:
def will produce a new lambda (new object) every time you reference it.
val will produce it once (at definition time) and every reference to it refers to the same instance.
In this case, val makes more sense so it's not creating a new lambda every time.
You are right that:
def will be evaluated every time you reference the function and val will be evaluated only once and the same value will be used every time.
It is true with partial functions as well. To see the behavior you can see this example:
scala> def add(x:Int)(y:Int) = {println("inadd");x+y}
add: (x: Int)(y: Int)Int
scala> def addWithDef = add(2)(3)
addWithDef: Int
scala> addWithDef // Evaluated
inadd
res0: Int = 5
scala> addWithDef // Evaluated again as "inadd" is printed again
inadd
res1: Int = 5
scala> val addWithVal = add(2)(3) // Evaluated once
inadd
addWithVal: Int = 5
scala> addWithVal //Same value referenced again(no "inadd" printed)
res2: Int = 5
scala> addWithVal //Same value referenced again(no "inadd" printed)
res3: Int = 5
Related
I am new to scala and was playing around with few concepts but got stuck with following one.
If i create a method like
def sample(value:Int) = {(x:Int)=>x+1}
This works in Scala and can be tested as sample(100), but I am not able to understand as how a method and literal here can be clubbed. Can someone explain what exactly is happening?
The parameter value here is never used and is therefore redundant. The method sample() returns a function which takes one integer parameter (which is discarded) and then adds 1 to it. So you get:
scala> def sample(value:Int) = { (x:Int) => x + 1 }
sample: (value: Int)Int => Int
scala> sample(100)
res2: Int => Int = <function1>
scala> sample(100)(10)
res3: Int = 11
scala> val f = sample(99)
f: Int => Int = <function1>
scala> f(1)
res4: Int = 2
You could use the value parameter in the following way:
scala> def plusX(value:Int) = { (x:Int) => x + value}
plusX: (value: Int)Int => Int
scala> val plus10 = plusX(10)
plus10: Int => Int = <function1>
scala> plus10(15)
res7: Int = 25
Now plusX creates a function which takes a integer and adds the value value to it
I do not understand why Set defined in this way produces these results.
My understanding is that Set is just a function which takes an int and return boolean.
Can someone explain me why I get this result using set?
I think this is a short way to express the function in Scala but I am new to this language and I do not understand how it works.
object sets {
type Set = Int => Boolean
var a=Set(3) //> a : scala.collection.immutable.Set[Int] = Set(3)
a(2) //> res0: Boolean = false
a(3) //> res1: Boolean = true
a(1) //> res2: Boolean = false
}
The type you defined in type Set = Int => Boolean and the object you created in var a=Set(3) are actually not connected to each other. Even this works:
scala> type Set = String
defined type alias Set
scala> val a = Set(3)
a: scala.collection.immutable.Set[Int] = Set(3)
When you call Set(3), you call apply method on the object Set. If you add new keyword, it will take your type alias into account:
scala> val b = new Set()
b: String = ""
a(2), a(3), a(1) work because Set[A], actually, does implement A => Boolean function trait and apply method is equivalent to contains: http://www.scala-lang.org/api/2.10.3/index.html#scala.collection.immutable.Set
I agree what izstas said they are different things. But "type Set = Int => Boolean" has effect. In the following steps in scala console, after "type Set = Int => Boolean" the error disappears.
scala> def func(s:Set) = 1
<console>:10: error: type Set takes type parameters
def func(s:Set) = 1
^
scala> def func(s:Set[Int]) = 1
func: (s: Set[Int])Int <---- specify the type in the set
scala> type Set = Int => Boolean
defined type alias Set
scala> def func(s:Set) = 1 <---- no error
func: (s: Set)Int
scala> def getSet(s:Set) = s
getSet: (s: Set)Set
scala> getSet(Set(1,2))
res0: Set = Set(1, 2)
scala> Set(1,2)
res1: scala.collection.immutable.Set[Int] = Set(1, 2)
scala> val t=Set(1,2)
t: scala.collection.immutable.Set[Int] = Set(1, 2)
(T,T)* resolves to Seq[(T,T)] after erasure, but how to represent (T,T)* itself as a type?
The reason I ask is there's an API I'm using that defines a:
def foo(bar: (String,String)*) = ...
but fails when I try to pass in a Seq[(String,String)].
My pull request to add in:
def foo(bar: Seq[(String,String)]) = ...
blows up due to the 2 methods having the same type after erasure.
Are star projections able to be represented as a concrete type?
You can pass the Seq if you follow it with :_* like this:
val s:Seq[(String, String)] = Seq( ("a", "b"), ("c", "d"), ... )
foo(s:_*)
So you shouldn't need both signatures.
To disambiguate the erased signatures:
scala> class X { def f(is: Int*) = is.sum }
defined class X
scala> class Y extends X { def f(is: Seq[Int])(implicit d: DummyImplicit): Int = f(is: _*) }
defined class Y
scala> new Y().f(1 to 10)
res3: Int = 55
or this is better, the signatures in collections always look like this to mean "two or more":
scala> class X {
| def f(i: Int): Int = i
| def f(is: Seq[Int]): Int = is.sum
| def f(i: Int, j: Int, rest: Int *): Int = i + j + rest.sum
| }
defined class X
scala> new X().f(3)
res9: Int = 3
scala> new X().f(3,4)
res10: Int = 7
scala> new X().f(3,4,5)
res11: Int = 12
scala> new X().f(1 to 10)
res12: Int = 55
You can't refer to a repeated parameter type, just as you can't refer to a by-name parameter type as such. So you can't convert to it. However, you can detect it reflectively, by name:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> typeOf[X].member(TermName("f")).asMethod.paramss.flatten.head.asTerm.typeSignature.typeSymbol.name
warning: there were 1 deprecation warning(s); re-run with -deprecation for details
res4: reflect.runtime.universe.Symbol#NameType = <repeated>
There is internal API, definitions.isRepeated(sym), if you want to cast for it.
After having discovered that currying multi parameter-groups method is possible, I am trying to get a partially applied function which requires implicit parameters.
It seams not possible to do so. If not could you explain me why ?
scala> def sum(a: Int)(implicit b: Int): Int = { a+b }
sum: (a: Int)(implicit b: Int)Int
scala> sum(3)(4)
res12: Int = 7
scala> val partFunc2 = sum _
<console>:8: error: could not find implicit value for parameter b: Int
val partFunc2 = sum _
^
I use a singleton object to create this partially applied function and I want to use it in a scope where the implicit int is defined.
That is because you don't have an implicit Int in scope. See:
scala> def foo(x: Int)(implicit y: Int) = x + y
foo: (x: Int)(implicit y: Int)Int
scala> foo _
<console>:9: error: could not find implicit value for parameter y: Int
foo _
^
scala> implicit val b = 2
b: Int = 2
scala> foo _
res1: Int => Int = <function1>
The implicit gets replaced with a real value by the compiler. If you curry the method the result is a function and functions can't have implicit parameters, so the compiler has to insert the value at the time you curry the method.
edit:
For your use case, why don't you try something like:
object Foo {
def partialSum(implicit x: Int) = sum(3)(x)
}
scala> object MySingleton {
| def sum(a: Int)(implicit b: Int): Int = { a+b }
|
|
| def caller(a: Int) = {
| implicit val b = 3; // This allows you to define the partial below
| def pf = sum _ // and call sum()() without repeating the arg list.
| pf.apply(a)
| }
| }
defined module MySingleton
scala> MySingleton.caller(10)
res10: Int = 13
Considering
object A {
def m(i: Int) = i
val m = (i: Int) => i * 2
}
one gets
scala> A.m(2)
<console>: error: ambiguous reference to overloaded definition,
both value m in object A of type => (Int) => Int
and method m in object A of type (i: Int)Int
match argument types (Int)
A.m(2)
^
Accessing the val can be done with
scala> val fun = A.m
fun: (Int) => Int = <function1>
scala> fun(2)
res: Int = 4
or
scala> A.m.apply(2)
res: Int = 4
but how would one access the def?
It is total rubbish (please, don't do this at home), but you can do it by assigning A to a variable of structural type, that has only the first m.
val x : { def m(i:Int):Int } = A
x.m(10)