Reputation: 45
I'm working on the assignments on Coursera's Scala course and have a question. Out of curiosity, I've switched from an anonymous function to a defined one:
object sets {
def main(args:Array[String]) {
type Set = Int => Boolean
def contains(s: Set, elem: Int): Boolean = {println("in contains elem ="+elem);s(elem)}
def singletonSet(elem: Int): Set = { //println("in singleton elem ="+elem); (x: Int) => x == elem}
def singletonSetF(x: Int): Boolean = {
println ("in singleton elem ="+elem+", x="+x)
elem == x
}
singletonSetF
}
println(contains(singletonSet(69), 6))
}
}
And here is the output:
in contains elem =6
in singleton elem =69, x=6
false
I believe the code is correct and working properly. My question is how and why does the "elem = 6" argument passed from the contains method, get assigned to "x = 6" in the singletonSetF method? Is the contains function call "s(elem)" a call to singletonSetF rather than singletonSet?
Upvotes: 0
Views: 89
Reputation: 42617
The contains
function takes two arguments: a Set
and an Int
. We are trying to test whether the Set
contains the Int
.
The Set is actually a function of type Int => Boolean
, as defined by the type alias for Set
.
We create this first argument by calling singletonSet
, which returns a function (singletonSetF
). However, singletonSetF
is a closure - it captures the value of elem
passed into singletonSet
, which in this case is 69.
Finally we call s(elem)
. s
is the closure containing the value 69. elem
is the value 6, which is then bound to the parameter 'x' in singletonSetF
.
Important: The code is a little confusing because you use elem
to mean two different things in two different places - in contains
, it is the value we are testing for membership of the Set; in singletonSet
, it is the sole member of the Set. Renaming one of these may help a lot!
Upvotes: 1
Reputation: 15074
Your singletonSetF
call, made in the singletonSet
method when called with the value 69
, results in a Set
instance, which in this case is an instance of a function from Int
to Boolean
(Int => Boolean
). The function is created at this point (although it does "close" over the value 69
for elem
), not evaluated, so x
hasn't been set here.
Then, when contains
is called, it runs the line s(elem)
where elem
here (not the same elem
closed over by singletonSetF
!) is the paramter value 6
.
The line s(elem)
is a call to that earlier-created function (s
here is the same Set
- hence the same Int => Boolean
instance - created by the call to singletonSet
), passing the value of the parameter elem
(passed in to contains
as the value 6
) into that function.
At this point the function is executed, with x
= 6
, producing the printed statements you observed.
Upvotes: 1
Reputation: 11317
I think the main problem is that you assume that a Set
is kind of a fixed data structure once you obtain it from singletonSet
. However, it is just a function that can be called. s(elem)
calls it and ends up in executing the code in singletonSetF
.
Here is what happens: singletonSet(69)
calls the singletonSet
function. This function returns a function value of the singletonSetF
function. The function value acts as kind of a wrapper around a local function or method. You don't see the wrapper but its added implicitly because singletonSetF
cannot be returned directly (it's a local function that cannot be passed around).
contains
receives this function value which is properly typed as Int => Boolean
and calls the function with the value 6
. The function value/wrapper then calls the real singletonF
with value 6
.
Upvotes: 1