I'm just trying to understand the below code :
Here a new type alias Set is declared which is a function that takes an Int
parameter and returns a boolean
type Set = Int => Boolean
Here a new method 'contains' is declared, which takes two parameters of type Set and Int
which returns a boolean. The boolean is set to the function declared in earlier
('type Set = Int => Boolean')
But what logic is performed to determine if the Int 'elem' is a member of Set 's'
def contains(set: Set, elem: Int): Boolean = set(elem)
Here a method is defined which returns a set which returns a function ?
def singletonSet(elem: Int): Set = set => set == elem
Complete code with comments :
/**
* We represent a set by its characteristic function, i.e.
* its `contains` predicate.
*/
type Set = Int => Boolean
/**
* Indicates whether a set contains a given element.
*/
def contains(set: Set, elem: Int): Boolean = set(elem)
/**
* Returns the set of the one given element.
*/
def singletonSet(elem: Int): Set = set => set == elem
Let's read sort of backwards, in logical order.
Say you have a finite set of integers: 0, 1, 2, 3, 5, 8 for instance
One way to describe this set of integers is through a function (its characteristic or indicator function) that, for each integer, returns true if the integer is in the set, false if it is not.
The signature for this function, as we described it, must always be Int => Boolean ("give me an integer, I will tell you if it's in the set"), while its implementation will vary depending on the specific set.
For the set in my example above you could write this function simply as:
val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x
or recognize that the ints in the set are the first ones of the Fibonacci sequence and define f in a slightly more sophisticated way (which I won't do here...).
Note that the "contains" I've used is defined for all scala collections.
In any case, now you have a function that tells you what is in the set and what is not.
Let's try it in the REPL.
scala> val mySet: Int => Boolean = x => Array(0,1,2,3,5,8) contains x
mySet: Int => Boolean = <function1>
scala> mySet(3)
res0: Boolean = true
scala> mySet(9)
res1: Boolean = false
Now, mySet has type Int => Boolean, which we can make more readable if we define it as a type alias.
scala> type Set = Int => Boolean
defined type alias Set
Besides readability, defining Set as an alias of Int => Boolean is making it explicit that in a way a Set is its characteristic function. We can redefine mySet in a more concise (but otherwise equivalent) way with the Set type alias:
scala> val mySet: Set = x => Array(0,1,2,3,5,8) contains x
mySet: Int => Boolean = <function1>
Now for the last piece of this long answer. Let's define a characteristic function to describe this Singleton set: 3.
Easy:
val Singleton3 : Set = set => set == 3
for a Singleton set containing only 4, it would be:
val Singleton4 : Set = set => set == 4
So, let's generalize the creation of these functions and write a method that returns a Singleton function that, for any integer, describes the set containing only that integer:
def singletonSet(elem: Int): Set = set => set == elem
APPENDIX:
I skipped this part, because it wasn't really needed: def contains(set: Set, elem: Int): Boolean = set(elem)
I think it's sort of pointless and (without more context) it looks just like a contrived example to demonstrate how you can pass a function around as an argument, just like any other type in scala. It takes the Int => Bool function and the Int and just applies the function to the Int so you can do
scala> contains(mySet, 3)
res2: Boolean = true
which is like calling mySet(3) directly.
After watching the lecture video on "Currying", I believe that Paolo's solution expressed in a more verbose manner is :
def singletonSet(elem: Int): Set = {
def innerFunction (givenElement: Int) =
if (elem == givenElement) true
else false
innerFunction
}
Plesae correct me if I am wrong!
To answer your question - But what logic is performed to determine if the Int 'elem' is a member of Set 's'
This is performed when you make the actual function call. Consider the following function call.
contains(singletonSet(1), 1)
Now singletonSet is defined as def singletonSet(elem: Int): Set = x => x == elem (I choose to use the identifier x for clarity sake). The return type of the singletonSet is the function of type Set which takes an Int argument and returns Boolean. So the above calling function's first argument singletonSet(1) equates to the function x => x == 1 as elem here is 1. So we get
contains((x => x == 1),1)
Now considering the definition of contains function def contains(f: Set, elem: Int): Boolean = f(elem). The first argument in the call above is the function x => x == 1 which substitutes formal parameter f and second argument 1 substitutes formal parameter elem. The return value of contains is the function f(elem) which equates to f(1). Since f(x) is defined as (x == 1), f(1) equates to (1 == 1) which returns true.
Going by the same logic, a function call like contains(singletonSet(1), 2) would finally equate to (1 == 2) which will return false.
I'm taking the course now, was also confused, but I think I get the point now.
def singletonSet(elem: Int): Set = (x : Int) => x == elem
here singletonSet is a function that returns a function with the type Set, which is defined as type Set = Int => Boolean
so when you call def contains(s:Set, elem:Int): Boolean = s(elem), for example: contains(singletonSet(1), 2), singletonSet(1) is returning a function with elem(in the definition of singletonSet) set to 1, and the 2(also defined as elem, but is defined in the parameter of contains) is passed in as the x in singletonSet definition, we need to get rid of java set idea, we don't need the singletonSet to persist the value we set.
For better understanding, we can change the parameter name as following:
def singletonSet(elemToStore: Int): Set = (x : Int) => x == elemToStore
def contains(s: Set, elemToCheck: Int): Boolean = s(elemToCheck)
Related
It's a question regarding syntactic sugars in Scala functions, similar discussion could be found here and here. Both answers give great insights, but I still cannot get my head aroud.
That is, I could not understand how characteristic function works?
Characteristic function (see the code below):
s(elem)
Set(elem)
Let's see an example,
object devScript extends App {
type Set = Int => Boolean
def contains(s: Set, elem: Int): Boolean = s(elem)
def singletonSet1(elem: Int): Set = (x: Int) => x == elem
def singletonSet2(elem: Int): Set = Set(elem)
println(contains(singletonSet1(5), 5))
println(contains(singletonSet2(5), 5))
}
Returns:
true
true
singletonSet1 and singletonSet2 have given the same result, so are they just two functions that expressing the same thing but in different forms? Moreover, without explicitly define a Boolean clause, how could a function return true/false?
I think this example is a bit confusing because there are two definitions of Set in scope. You define your own type alias Set which has a type of a function that takes Int and returns Boolean: Int => Boolean. On the other hand you also have Set from Scala collections in scope which has apply function which is also of the same type: Int => Boolean. Let's look at these types in REPL:
scala> singletonSet1 _
res1: Int => Set = $$Lambda$1261/1618596377#4ed90b04
scala> singletonSet2 _
res2: Int => Set = $$Lambda$1262/224661478#14f08a97
scala> Set(1).apply _
res3: Int => Boolean = $$Lambda$1352/273821181#17d6b6e
// same as apply above
scala> Set(1)(_)
res4: Int => Boolean = $$Lambda$1377/1981148063#4ebe0e3f
scala> singletonSet1(1)
res5: Set = $$Lambda$1230/593573468#7574d30b
scala> singletonSet1(1)(1)
res6: Boolean = true
// or similarly:
scala> singletonSet2(1)(1)
res7: Boolean = true
As you can see apply, also written as () conforms to the type that you need to return from your singletonSet[1|2] function.
You are right that both of them can be used as functions which are implemented in different forms: using closures for singletonSet1 and using regular Scala Set in singletonSet2 case.
Note that singletonSet[1|2] doesn't return boolean, it returns a function that will return a Boolean provided you've given it an Int. There is one more level of indirection involved. If you write out the type of these functions entirely it will look like this: Int => Int => Boolean, or equivalently: Int => Set.
Coincidentally I wrote a blog post trying to explain how this works. You can check it out here:http://izmailoff.github.io/programming%20languages/functional%20programming/functional_sets. Hopefully it's clear enough.
The Set(elem) refers to the companion object of scala.collection.Set, which is a value, and therefore is not shadowed by your type-definition Set.
Just run this to see it:
object devScript extends App {
type Set = Int => Boolean
def contains(s: Set, elem: Int): Boolean = s(elem)
def singletonSet1(elem: Int): Set = (x: Int) => x == elem
def singletonSet2(elem: Int): Set = Set(elem)
println(contains(singletonSet1(5), 5))
println(contains(singletonSet2(5), 5))
println(singletonSet2(42).getClass)
}
It will print true, true, class scala.collection.immutable.Set$Set1,
instead of something like Int => Boolean, as you might have expected.
Even more confusingly, the contains(singletoSet2(5), 5) also works, because, scala's standard collection Set[A] also implements A => Boolean, as can be seen in the documentation.
What is the difference between:
def even: Int => Boolean = _ % 2 == 0
and
val even: Int => Boolean = _ % 2 == 0
Both can be called like even(10).
Method def even evaluates on call and creates new function every time (new instance of Function1).
def even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = false
val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
With def you can get new function on every call:
val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1049057402
test()
// Int = -1049057402 - same result
def test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -240885810
test()
// Int = -1002157461 - new result
val evaluates when defined, def - when called:
scala> val even: Int => Boolean = ???
scala.NotImplementedError: an implementation is missing
scala> def even: Int => Boolean = ???
even: Int => Boolean
scala> even
scala.NotImplementedError: an implementation is missing
Note that there is a third option: lazy val.
It evaluates when called the first time:
scala> lazy val even: Int => Boolean = ???
even: Int => Boolean = <lazy>
scala> even
scala.NotImplementedError: an implementation is missing
But returns the same result (in this case same instance of FunctionN) every time:
lazy val even: Int => Boolean = _ % 2 == 0
even eq even
//Boolean = true
lazy val test: () => Int = {
val r = util.Random.nextInt
() => r
}
test()
// Int = -1068569869
test()
// Int = -1068569869 - same result
Performance
val evaluates when defined.
def evaluates on every call, so performance could be worse than val for multiple calls. You'll get the same performance with a single call. And with no calls you'll get no overhead from def, so you can define it even if you will not use it in some branches.
With a lazy val you'll get a lazy evaluation: you can define it even if you will not use it in some branches, and it evaluates once or never, but you'll get a little overhead from double check locking on every access to your lazy val.
As #SargeBorsch noted you could define method, and this is the fastest option:
def even(i: Int): Boolean = i % 2 == 0
But if you need a function (not method) for function composition or for higher order functions (like filter(even)) compiler will generate a function from your method every time you are using it as function, so performance could be slightly worse than with val.
Consider this:
scala> def even: (Int => Boolean) = {
println("def");
(x => x % 2 == 0)
}
even: Int => Boolean
scala> val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
val //gets printed while declaration. line-4
even2: Int => Boolean = <function1>
scala> even(1)
def
res9: Boolean = false
scala> even2(1)
res10: Boolean = false
Do you see the difference? In short:
def: For every call to even, it calls the body of the even method again. But with even2 i.e. val, the function is initialized only once while declaration (and hence it prints val at line 4 and never again) and the same output is used each time it accessed. For example try doing this:
scala> import scala.util.Random
import scala.util.Random
scala> val x = { Random.nextInt }
x: Int = -1307706866
scala> x
res0: Int = -1307706866
scala> x
res1: Int = -1307706866
When x is initialized, the value returned by Random.nextInt is set as the final value of x. Next time x is used again, it will always return the same value.
You can also lazily initialize x. i.e. first time it is used it is initialized and not while declaration. For example:
scala> lazy val y = { Random.nextInt }
y: Int = <lazy>
scala> y
res4: Int = 323930673
scala> y
res5: Int = 323930673
See this:
var x = 2 // using var as I need to change it to 3 later
val sq = x*x // evaluates right now
x = 3 // no effect! sq is already evaluated
println(sq)
Surprisingly, this will print 4 and not 9! val (even var) is evaluated immediately and assigned.
Now change val to def.. it will print 9! Def is a function call.. it will evaluate each time it is called.
val i.e. "sq" is by Scala definition is fixed. It is evaluated right at the time of declaration, you can't change later. In other examples, where even2 also val, but it declared with function signature i.e. "(Int => Boolean)", so it is not Int type. It is a function and it's value is set by following expression
{
println("val");
(x => x % 2 == 0)
}
As per Scala val property, you can't assign another function to even2, same rule as sq.
About why calling eval2 val function not printing "val" again and again ?
Orig code:
val even2: (Int => Boolean) = {
println("val");
(x => x % 2 == 0)
}
We know, in Scala last statement of above kind of expression (inside { .. }) is actually return to the left hand side. So you end up setting even2 to "x => x % 2 == 0" function, which matches with the type you declared for even2 val type i.e. (Int => Boolean), so compiler is happy. Now even2 only points to "(x => x % 2 == 0)" function (not any other statement before i.e. println("val") etc. Invoking event2 with different parameters will actually invoke "(x => x % 2 == 0)" code, as only that is saved with event2.
scala> even2(2)
res7: Boolean = true
scala> even2(3)
res8: Boolean = false
Just to clarify this more, following is different version of the code.
scala> val even2: (Int => Boolean) = {
| println("val");
| (x => {
| println("inside final fn")
| x % 2 == 0
| })
| }
What will happen ? here we see "inside final fn" printed again and again, when you call even2().
scala> even2(3)
inside final fn
res9: Boolean = false
scala> even2(2)
inside final fn
res10: Boolean = true
scala>
Executing a definition such as def x = e will not evaluate the expression e. In- stead e is evaluated whenever x is invoked.
Alternatively, Scala offers a value definition
val x = e,which does evaluate the right-hand-side as part of the evaluation of the definition.
If x is then used subsequently, it is immediately replaced by the pre-computed value of e, so that the expression need not be evaluated again.
also, Val is a by value evaluation. Which means the right-hand side expression is evaluated during definition. Where Def is by name evaluation. It will not evaluate until it's used.
In addition to the above helpful replies, my findings are:
def test1: Int => Int = {
x => x
}
--test1: test1[] => Int => Int
def test2(): Int => Int = {
x => x+1
}
--test2: test2[]() => Int => Int
def test3(): Int = 4
--test3: test3[]() => Int
The above shows that “def” is a method (with zero argument parameters) that returns another function "Int => Int” when invoked.
The conversion of methods to functions is well explained here: https://tpolecat.github.io/2014/06/09/methods-functions.html
In REPL,
scala> def even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean
scala> val even: Int => Boolean = { _% 2 == 0 }
even: Int => Boolean = $$Lambda$1157/1017502292#57a0aeb8
def means call-by-name, evaluated on demand
val means call-by-value, evaluated while initialization
Note: There are different types of functions in Scala: abstract, concrete, anonymous, high order, pure, impure etc...
Explaining val function:
A val function in Scala is a complete object. There are traits in Scala to represent functions with various numbers of arguments: Function0, Function1, Function2, etc. As an instance of a class that implements one of these traits, a function object has methods. One of these methods is the apply method, which contains the code that implements the body of the function.
When we create a variable whose value is a function object and we then reference that variable followed by parentheses, that gets converted into a call to the apply method of the function object.
Explaining Method i.e def:
Methods in Scala are not values, but functions are.
A Scala method, as in Java, is a part of a class. It has a name, a signature, optionally some annotations, and some bytecode.
The implementation of a method is an ordered sequence of statements that produces a value that must be compatible with its return type.
This is slightly different from this question.
I want to define a function type that have default value defined.
Like this:
trait Foo {
type MyFunction = (Int, Option[Int] = 0) => Boolean
def checkInts(f: MyFunction)
}
Is it possible? If yes, how can I achieve this? If not, why?
Read here why you can't have default arguments in anonymous functions and how to make something similar - In Scala, can you make an anonymous function have a default argument?
But if you just need a way to pass a function taking 2 or 1 argument, you can always use simpler approach:
trait Foo {
type MyFunc1 = (Int) => Boolean
type MyFunc2 = (Int, Int) => Boolean
def checkInts(f: MyFunc1)
def checkInts(f: MyFunc2)
// common code of checkInts could be in some private method
}
Based on my knowledge so far you cannot define a type with default parameters. A type is a type.
What you can do is define a partially applied function.
Taking as an example the following function:
scala> def factorOf(x: Int, y: Int) = y % x == 0
factorOf: (x: Int, y: Int)Boolean
If you want a shortcut to the function without retaining any parameters, you can use the wildcard operator (_) assignment
scala> val f = factorOf _
f: (Int, Int) => Boolean = <function2>
scala> val x = f(7, 20)
x: Boolean = false
If you want to retain some of the parameters, you can partially apply the function by using the wildcard operator to take the place of one of the parameters. The wildcard operator here requires an explicit type, because it is used to generate a function value with a declared input type:
scala> val multipleOf3 = factorOf(3, _: Int)
multipleOf3: Int => Boolean = <function1>
scala> val y = multipleOf3(78)
y: Boolean = true
The new function value, multipleOf3, is a partially applied function, because it contains some but not all of the parameters for the factorOf() function.
A cleaner way to partially apply functions is to use functions with multiple parameter lists. This is a technique
known as currying the function:
scala> def factorOf(x: Int)(y: Int) = y % x == 0
factorOf: (x: Int)(y: Int)Boolean
scala> val isEven = factorOf(2) _
isEven: Int => Boolean = <function1>
scala> val z = isEven(32)
z: Boolean = true
What's the verbose way for val Singleton4 : Set = set => set == 4? I am unable to understand where the set parameter is coming from.
What maybe confuses you is the fact that Set is not what one would expect from the Scala library. You should read the line as:
val Singleton4: Int => Boolean = someArbitraryName => someArbitraryName == 4
// <identifier> <type> = <argument> => <returnValue>
It's not "coming" from anywhere, Set is defined as a function from an integer to a boolean and the type of Singleton4 is exactly that, it takes an integer and returns a function which needs another integer and returns a boolean:
scala> type Set = Int => Boolean
defined type alias Set
scala> def singletonSet(elem: Int): Set = set => set == elem
singletonSet: (elem: Int)Int => Boolean
scala> val p: Set = singletonSet(3)
p: Int => Boolean = <function1>
So now p is a function which takes an integer:
scala> p(3)
res0: Boolean = true
scala> p(2)
res1: Boolean = false
An alternative way of writing that is this:
def singletonSet(elem: Int) = (i: Int) => i == elem
val p: (Int) => Boolean = singletonSet(3)
Or using a different way but achieving the same result:
def singletonSet(elem: Int)(i: Int): Boolean = i == elem
val p: (Int) => Boolean = singletonSet2(3)
By currying the function and applying only one argument you get back a function which still needs another integer to be fully evaluated.
The other answers are very good, but I thought I'd throw some additional details to help newcomers to Scala understand the notation better (as there are some hidden gems in the notation that were not uncovered/described).
Let's play the Scala compiler game!
The following val says enough about what Set the type represents.
val Singleton4: Set = set => set == 4
The type of val is given explicitly - it's Set. We don't however know much about it...yet. It has however to be given to the compiler before it can be used and given the left-hand side it's a function (mind the => two-letter string) from a type (we'll get to it in a moment) to Boolean since set == 4 will inevitably end as Boolean.
From set == 4 we can deduce that set can only be Int (so you can compare apples to apples) and hence we've got the type of set as Int.
The right-hand side of = of the val could also have been written as:
val Singleton4: Set = (set: Int) => set == 4
So, the Singleton4 val is an instance of a function Int => Boolean that's called Set. Set's declared as such somewhere above (lexicographically):
type Set = Int => Boolean
You could substitute Set to the type alias and end up with:
val Singleton4: Int => Boolean = (set: Int) => set == 4
From the question linked here, I found this implementation of Union in Scala:
def union(a: Set, b: Set): Set = i => a(i) || b(i)
And Set is a function of type:
type Set = Int => Boolean
Now I understand that in Scala, a function is mapped from Int to Boolean here, and I further understand how this statement is executed:
a(i) || b(i)
But what I don't understand is what is 'i' here. Where does it come from? And when it finds a match between to sets, it returns true, if it indeed does, where do I filter it?
The Set (which is just a function) that gets returned from union takes some integer as a parameter; you must give it an arbitrary name so that you can refer to it in the function body. It may make more sense if you write the function like this:
def union(a: Set, b: Set): Set = {
(i) => a(i) || b(i)
}
It may make even more sense if you write it like this:
def union(a: Set, b: Set): Set = {
// The union of two sets is a new function that takes an Int...
def theUnion(i: Int): Boolean = {
// and returns true if EITEHR of the other functions are true
a(i) || b(i)
}
// Now we want to return the NEW function
theUnion
}
Again, i is arbitrary and could be replaced with any variable:
def union(a: Set, b: Set): Set = item => a(item) || b(item)
[Update]
Because we're representing sets as functions, there's no need to iterate to see if they contain a number. For example, here's a set that contains any number below -5:
val belowNegFive: Set = (i) => i < -5
When we call that function with a number, it will tell us if that number is in the set. Note that at no time did we actually tell it the specific numbers that were in the set:
scala> belowNegFive(10)
res0: Boolean = false
scala> belowNegFive(-100)
res1: Boolean = true
scala> belowNegFive(-1)
res2: Boolean = false
Here's another set that includes any number between 50 and 100:
val fiftyToHundred: Set = (i) => i >= 50 && i <= 100
scala> fiftyToHundred(50)
res3: Boolean = true
scala> fiftyToHundred(100)
res4: Boolean = true
scala> fiftyToHundred(75)
res5: Boolean = true
scala> fiftyToHundred(49)
res6: Boolean = false
Now, a union of the sets belowNegFive and fiftyToHundred would contain any number that is either below -5 or between 50 and 100. We can easily represent this in code by returning a new function which itself returns true if either of the other two functions returns true.
scala> val unionOfBoth: Set = (i) => belowNegFive(i) || fiftyToHundred(i)
unionOfBoth: Int => Boolean = <function1>
scala> unionOfBoth(-10)
res7: Boolean = true
scala> unionOfBoth(50)
res8: Boolean = true
scala> unionOfBoth(0)
res9: Boolean = false
The union function from your question is just a way of applying this pattern generically over any two sets.
Let say we have object called SoSet given by
object SoSet {
type Set = Int => Boolean
val a : Set = ???
val b : Set = ???
def isItem(item : Int) = a(item) || b(item)
}
The signature of isItem is given by Int => Boolean which is a Set. So far so good.
But now we just want to return the function isItem (i.e. a Set).
So lets define union function for this (There are no parameters right now. We will add it later).
object SoSet {
//..
def union : Set = isItem // returns the function isItem
}
Now lets refactor the isItem into a anonymous function.
object SoSet {
//..
def union : Set = {
(item : Int) => a(item) || b(item)
}
}
Lets move Set a and b from object SoSet to parameters of def union. Refactor item to i.
object SoSet {
type Set = Int => Boolean
def union(a : Set, b : Set) : Set = (i : Int) => a(i) || b(i)
}
UPDATE
val s1 = Set(1, 2, 3)
val s2 = Set(2, 3, 4)
val s3 = union(s1, s2) // returns the function.. Int => Boolean = <function1>
s3(2) // invokes the function & checks if 2 is present in the union
And when it finds a match between to sets, it returns true, if it indeed does, where do I filter it?
union does not find a match between two sets, it creates a new set which contains the values of
both sets. Example:
val a = (i) => i == 2 // a contains 2 as a(2) == True
val b = (i) => i == 5 // b contains 5 as b(5) == True
val u = union(a, b) // u contains 2 and 5 as u(2) == True and u(5) == True
So the 'filtering' just happens on the way. This function is not iterating over each set, filtering specific things out, it just returns a combination of two functions which then can executed later to query for the actual values.
Example of querying the values of a union:
val a = (i) => i == 2
val b = (i) => i == 5
val u = union(a, b)
for(i <- 1 to 10 if u(i)) yield i // returns Vector(2, 5)
And yes, this is not an optimal way of storing values in sets as you have to check values by
guessing but it is a good way to demonstrate how combining functions adds complex functionality without
writing very complex code.
You can implement a union function like this:
def union[A](set1: Set[A], set2:Set[A]):Set[A] = {
set1.foldLeft(set2)((set, elem) => set + elem)
}
or
def union[A](set1: Set[A], set2:Set[A]):Set[A] = {
set1.flatMap(elem => set2 + elem)
}
These will be generic so you can use it for sets of any type