I'm new to scala so sorry if this is easy but I've had a hard time finding the answer.
I'm having a hard time understanding what <- does, and what ()=> Unit does. My understanding of these is that -> is sometimes used in foreach, and that => is used in maps. Trying to google "scala "<-" doesn't prove very fruitful. I found http://jim-mcbeath.blogspot.com/2008/12/scala-operator-cheat-sheet.html but it wasn't as helpful as it looks at first glance.
val numbers = List("one", "two", "three","four","five")
def operateOnList() {
for(number <- numbers) {
println(number + ": came out of this crazy thing!")
}
}
def tweener(method: () => Unit) {
method()
}
tweener(operateOnList)
() => Unit means that method is a function that takes no parameter and returns nothing (Unit).
<- is used in the for comprehension as an kind of assignation operator. for comprehension are a little bit specific because they are internally transformed. In your case, that would be transforms as numbers.foreach(i => println(i + ": came out of this crazy thing!"))
<- in the for comprehension means that we will iterate over each element of the numbers list and passed to number.
'<-' could be threated as 'in' so
for(number <- numbers){
...
}
could be translated into english as for each number in numbers do
'<-' has a twin with a different semantics: '->'. Simply it is just a replacement of comma in tuples: (a,b) is an equivalent to (a->b) or just a->b. The meaning after this symbols is that 'a' maps to 'b'. So this is often used in definition of Maps:
Map("a" -> 1,"aba" -> 3)
Map("London" -> "Britain", "Paris" -> "France")
Here you can think about mapping as a projection (or not) via some function (e.g. 'length of string', 'capital of').
Better explanation is here.
Last, but not least is '=>' which is map too, but with a general semantics. '=>' is in use all over the place in anonymous expressions:
scala> List(1,2,3,4).map(current => current+1)
res5: List[Int] = List(2, 3, 4, 5)
Which is for each element map current element of list with function 'plus one'
List(1,2,3,4).map(c => c%2 match {
| case 0 => "even"
| case 1 => "odd"
| }
| )
res6: List[java.lang.String] = List(odd, even, odd, even)
Map current element with provided pattern mathing
In the method
def tweener(method: () => Unit) {
method()
}
the method is called tweener, the parameter is arbitrarily named method, and the type of method is () => Unit, which is a function type, as you can tell from the =>.
Unit is a return type similar to void in Java, and represents no interesting value being returned. For instance, the return type of print is Unit. () represents an empty parameter list.
Confusingly, () is also used to represent an instance of Unit, called the unit value, the only value a Unit can take. But this is not what it means in the function type () => Unit, just as you can't have a function type 42 => Unit.
Back to your example, tweener takes a function of type () => Unit. operateOnList is a method, but it gets partially applied by the compiler to turn it into a function value. You can turn methods into functions yourself like this:
scala> def m = println("hi")
m: Unit
scala> m _
res17: () => Unit = <function0>
operateOnList can be turned into the right type of function because its parameter list is empty (), and its return type is implicity Unit.
As a side-note, if operateOnList were defined without the empty parameter list (as is legal, but more common when the return type is not Unit), you would need to manually partially apply it, else its value will be passed instead:
def f1() {}
def f2 {}
def g(f: () => Unit) {}
g(f1) // OK
g(f2) // error, since we're passing f2's result (),
// rather than partial function () => Unit
g(f2 _) // OK
Related
Background
I tried to answer a question "what is function?" and wonder if I actually know what it is. Please help to understand what a "function" is in Scala. It may sound non-sense debate but please be patient to help.
Questions
1. What is function
A "function" is a "computation/operation" to be "applied" to a single "argument" to generate an "value". If there are multiple argument, then it can be converted into ()()()... which is called currying.
w is a name
b is a binding of a function object to a name
c is computation
a is application
g is argument on which apply an compuation
val w = ( ) => { }
^ ^ ^ ^ ^
| | | | |
(n) (b) (g) (a) (c)
Is it OK to say these?
Also if this is to apply a computation to an argument:
() => { }
Then it actually should be in the opposite direction?
() <= { }
or
{ } => ()
2. Decomposition of definition
Is this correct understanding of what "def f (x:Unit):Unit = {}" is?
//--------------------------------------------------------------------------------
// The function literal says:
// 1. Define a "function" (ignore "method" here).
// 2. Bind the function to a name f.
// 3. It is to be applied to an "argument" of type Unit.
// 4. Bind the argument to a name x.
// 5. E-valuation, or appliation of the function to an argument generates an "value" of type Unit.
// 6. After evaluation, substitute it with the "value".
//--------------------------------------------------------------------------------
def f (x:Unit):Unit = {}
3. Evaluation / Application
Is "evaluation" the same with "application of a function to an argument and yield an value"? When I read lambda calculas, word "application" is used, but I think "evaluation" is also used.
Unit
//--------------------------------------------------------------------------------
// The literal says:
// 1. Apply the function f
// 2. on the "argument" enclosed between '(' and ')', which is Unit.
// 3. and yield Unit as the "value" evaluated.
//--------------------------------------------------------------------------------
def f (x:Unit):Unit = {}
f()
Is it the same with this? If so is "Unit" an object?
f(Unit) // No error in Scala worksheet
What is causing the error "Too many arguments" for Unit as argument below?
// Define a function that applies on an argument x of type Unit to generate Unit
() => {} // res0: () => Unit = <function0>
(() => {}) // res1: () => Unit = <function0>
// Application
(() => {})()
/* Error: Too many arguments */
(() => {})(Unit)
4. Referential transparency
Please advise if this is correct.
Using "def g (x:String): Unit = println(x)" as an example, "referential transparency" means that g(x) can be always substituted with its result and it will not break any.
If
g("foo")
can be always replaced with
Unit
then it is referentially transparent. However, it is not the case here for g. Hence g is not a referentially transparent function, hence it is not "pure" function. Random is also not pure.
{ scala.util.Random.nextInt } // res0: Int = -487407277
In Scala, function can be pure or side-effective. There is no way to tell by just having look at a function. Or is there a way to mark as such, or validate if it is pure or not?
5. Method is not a function
A method cannot be a first class object to be passed around but it can be by converting it to a function.
def g (x:String): Unit = println(x)
g("foo")
val _g = g _
_g("foo")
Why method cannot be a first class object? If a method is an object, what will happen or what will break?
Scala compiler does clever inferences or complehentions, then if it can be converted into an object with _, why Scala does not make it a firt class object?
6. What is { ... }?
Update:
"=> T" is call by name passing expression to be evaluated inside the function, hence has nothing to do with "{...}" specifically. {...} is a block expression. Hence all below is invalid.
It looks "{...}" is the same with "=> T".
def fill[T](n: Int)(elem: => T)
Array.fill[Int](3)({ scala.util.Random.nextInt })
{...} in itself yield an value without taking any argument.
{ scala.util.Random.nextInt } // res0: Int = 951666328
{ 1 } // res1: Int = 1
Does it mean "application" is an independent first class object, or the Scala compiler is clever enough to understand it is an abbreviation of:
() => { scala.util.Random.nextInt }
or
val next = (x:Int) => { scala.util.Random.nextInt(x) }
If so, "=> T" is actually "() => T"?
In Scala function is an implementation of one of traits from Function1 to Function22 depending on input parameters amount. For your particular example w is a shorthand for anonfunW:
val w = () => {}
val anonfunW = new Function1[Unit, Unit] {
def apply(x: Unit): Unit = ()
}
When using these in a function parameters description, they have different effects.
Only the latter form can accept multi-line operations like
{
println(“hello”)
println(“world”)
1
}
However, the former can’t.
I know ‘()’ means “no parameters”, right? But what ‘’ means in ‘=>Int’?
Here's the whole story.
Define a function
def func(x: =>Int)= {
println(x)
}
Invoke it
func {
println("hello")
println("world")
1
}
We will get
hello
world
1
However, if we define the function as
def func(x: ()=>Int)= {
println(x)
}
Invoke it using the former code, we will get
error: type mismatch;
found : Int(1)
required: () => Int
1
^
So, what's the difference between ‘x: () => Int’ and ‘x: => Int’?
Behaviors Of Call By Name Evaluation VS Higher-Order Functions
Call By Name Evaluation:
In case of call by name, the expression is evaluated before the function is invoked.
Example:
def func(x: =>Int): Int= {
x
}
func(10 + 2)
Higher-Order Functions:
In case of HOF, the function is passed and its result are computed when the function is invoked.
Example:
def func(x: () =>Int): () => Int = {
x
}
func(() => 10 + 2)
Note: Check the return types for more clarity.
Essentially, there is no difference. Both represent 0-arity functions which result in an Int value.
However, there is a big difference in how they are used. One, x: => Int, is used for a call-by-name parameter in a method and is invoked simply by referencing an Int. The compiler does the rest.
The other form, x: () => Int, is used for a method parameter where you really want to pass in a 0-arity function. But when you use x within your method, you must actually give it parentheses. And, of course, when you invoke the method, you need to pass in a function (or partially-applied method), not an Int.
Here's an example:
def and(a: Boolean, b: () => Boolean): Boolean = if (a) b() else false
def not(): Boolean = false
println(and(true, not))
I am composing function literals, though unlike most examples I've seen I'm starting with a multi-argument function that is then curried.
I have:
//types
case class Thing1(v: Double)
case class Thing2(v: Double)
case class Thing3(v: Double)
type Multiplier = Double
//functions
val f1 = (t: Thing1, m: Multiplier) => Thing2(m * t.v)
val f2 = (t: Thing2) => Thing3(t.v)
I want to compose f1 and f2 to get a combined function
Thing1 => (Multiplier => Thing3)
As expected, the following doesn't compile:
val fcomposed1 = f1.curried.andThen(f2) // does not compile
By experimentation, I was able to work out that the following does compile and has the right signature for fcomposed:
val fcomposed2 = f1.curried(_:Thing1).andThen(f2)
I've read various sources like What are all the uses of an underscore in Scala? and possibly relevant Why does Scala apply thunks automatically, sometimes? but unfortunately I still cannot work out exactly step-by-step what is happening here and why it works.
Furthermore, I would expect the above separated into two expressions to work identically to fcomposed2, however instead the second does not compile:
val f1partial = f1.curried(_:Thing1)
val fcomposed3 = f1partial.andThen(f2) // does not compile - same error as fcomposed1
Looks like f1partial returns the same signature as f1.curried, which makes me wonder further how the earlier fcomposed2 works.
Could someone please explain both behaviours step by step?
Here, the _ is acting as syntactical sugar for a lambda expression, but at a level you might not expect.
f1.curried has type Thing1 => Multiplier => Thing2
f1.curried(_:Thing1) is the same as { x: Thing1 => f1.curried(x) }. Since the result of f1.curried(x) has type Multiplier => Thing2, the final type of the whole expression is still Thing1 => Multiplier => Thing2. So it is not valid to call andThen(f2) on the result (f1partial) because the input type of function f2 (Thing2) is not the same as the output of the previous function (Multiplier => Thing2).
By contrast, f1.curried(_:Thing1).andThen(f2) expands to { x: Thing1 => f1.curried(x).andThen(f2) }. f1.curried(x) evaluates to type Multiplier => Thing2, like stated earlier, so you can call andThen(f2) on that, resulting in a Multiplier => Thing3. So then the entire expression evaluates to a Thing1 => Multiplier => Thing3
Perhaps it's more clear if you think about the differences between these two expressions:
val fcomposed1 = { x: Thing1 => f1.curried(x).andThen(f2) } // valid
val fcomposed2 = { x: Thing1 => f1.curried(x) }.andThen(f2) // error
I have a map m
val m = Map(1->2, 3->4, 5->6, 7->8, 4->4, 9->9, 10->12, 11->11)
Now i want a map whose keys are equal to the values. So i do this
def eq(k: Int, v: Int) = if (k == v) Some(k->v) else None
m.flatMap((k,v) => eq(k,v))
This gives me the error
error: wrong number of parameters; expected = 1
m.flatMap((k,v) => eq(k,v))
Whats wrong with the above code? flatMap expects a one argument function and here i am passing one argument which is a Pair of integers.
Also this works
m.flatMap {
case (k,v) => eq(k,v)
}
but this does not
m.flatMap {
(k,v) => eq(k,v)
}
Looks like i am missing something. Help?
There is no such syntax:
m.flatMap((k,v) => eq(k,v))
Well, in fact there is such syntax, but actually it is used in functions that accept two arguments (like reduce):
List(1,2,3,4).reduce((acc, x) => acc + x)
The
m.flatMap {
case (k,v) => eq(k,v)
}
syntax works because in fact it is something like this:
val temp: PartialFunction[Tuple2[X,Y], Tuple2[Y,X]] = {
case (k,v) => eq(k,v) // using literal expression to construct function
}
m.flatMap(temp) // with braces ommited
They key thing here is the usage of case word (actually, there is a discussion to enable your very syntax) which turns usual braces expression, like { ... } into full blown anonymous partial function
(If you want to simply fix the error you're getting, see the 2nd solution (with flatMap); if you want a generally nicer solution, read from the beginning.)
What you need instead is filter not flatMap:
def eq(k: Int, v: Int) = k == v
val m = Map(1->2, 3->4, 5->6, 7->8, 4->4, 9->9, 10->12, 11->11)
m.filter((eq _).tupled)
...which of course reduces to just the following, without the need for eq:
m.filter { case (k, v) => k == v }
result:
Map(9 -> 9, 11 -> 11, 4 -> 4)
OR... If you want to stick with flatMap
First you must know that flatMap will pass to your function TUPLES not keys and values as separate arguments.
Additionally, you must change the Option returned by eq to something that can be fed back to flatMap on sequences such as List or Map (actually any GenTraversableOnce to be precise):
def eq(k: Int, v: Int) = if (k == v) List(k -> v) else Nil
m.flatMap { case (k,v) => eq(k,v) } // use pattern matching to unpack the tuple
or the uglier but equivalent:
m.flatMap { x => eq(x._1, x._2) }
alternatively, you can convert eq to take a tuple instead:
m.flatMap((eq _).tupled)
I think that what you want is a single argument that will be a couple, not two arguments. Something like this may work
m.flatMap(k => eq(k._1, k._2))
The code snippet that works uses pattern matching. You give names to both elements of your couple. It's a partial function and can be use here in your flatMap.
You have to do:
m.flatMap { case (k,v) => eq(k,v) }
Note that here I switch to curly braces, which indicates a function block rather than parameters, and the function here is a case statement. This means that the function block I'm passing to flatMap is a partialFunction that is only invoked for items that match the case statement.
Your eq function takes two parameters, that is why you are getting the type error. Try:
def f(p: (Int, Int)) = if (p._1 == p._2) Some(p) else None
m flatMap f
I have a recursive function that takes a Map as single parameter. It then adds new entries to that Map and calls itself with this larger Map. Please ignore the return values for now. The function isn't finished yet. Here's the code:
def breadthFirstHelper( found: Map[AIS_State,(Option[AIS_State], Int)] ): List[AIS_State] = {
val extension =
for(
(s, v) <- found;
next <- this.expand(s) if (! (found contains next) )
) yield (next -> (Some(s), 0))
if ( extension.exists( (s -> (p,c)) => this.isGoal( s ) ) )
List(this.getStart)
else
breadthFirstHelper( found ++ extension )
}
In extension are the new entries that shall get added to the map. Note that the for-statement generates an iterable, not a map. But those entries shall later get added to the original map for the recursive call. In the break condition, I need to test whether a certain value has been generated inside extension. I try to do this by using the exists method on extension. But the syntax for extracting values from the map entries (the stuff following the yield) doesn't work.
Questions:
How do I get my break condition (the boolean statement to the if) to work?
Is it a good idea to do recursive work on a immutable Map like this? Is this good functional style?
When using a pattern-match (e.g. against a Tuple2) in a function, you need to use braces {} and the case statement.
if (extension.exists { case (s,_) => isGoal(s) } )
The above also uses the fact that it is more clear when matching to use the wildcard _ for any allowable value (which you subsequently do not care about). The case xyz gets compiled into a PartialFunction which in turn extends from Function1 and hence can be used as an argument to the exists method.
As for the style, I am not functional programming expert but this seems like it will be compiled into a iterative form (i.e. it's tail-recursive) by scalac. There's nothing which says "recursion with Maps is bad" so why not?
Note that -> is a method on Any (via implicit conversion) which creates a Tuple2 - it is not a case class like :: or ! and hence cannot be used in a case pattern match statement. This is because:
val l: List[String] = Nil
l match {
case x :: xs =>
}
Is really shorthand/sugar for
case ::(x, xs) =>
Similarly a ! b is equivalent to !(a, b). Of course, you may have written your own case class ->...
Note2: as Daniel says below, you cannot in any case use a pattern-match in a function definition; so while the above partial function is valid, the following function is not:
(x :: xs) =>
This is a bit convoluted for me to follow, whatever Oxbow Lakes might think.
I'd like first to clarify one point: there is no break condition in for-comprehensions. They are not loops like C's (or Java's) for.
What an if in a for-comprehension means is a guard. For instance, let's say I do this:
for {i <- 1 to 10
j <- 1 to 10
if i != j
} yield (i, j)
The loop isn't "stopped" when the condition is false. It simply skips the iterations for which that condition is false, and proceed with the true ones. Here is another example:
for {i <- 1 to 10
j <- 1 to 10
if i % 2 != 0
} yield (i, j)
You said you don't have side-effects, so I can skip a whole chapter about side effects and guards on for-comprehensions. On the other hand, reading a blog post I made recently on Strict Ranges is not a bad idea.
So... give up on break conditions. They can be made to work, but they are not functional. Try to rephrase the problem in a more functional way, and the need for a break condition will be replaced by something else.
Next, Oxbow is correct in that (s -> (p,c) => isn't allowed because there is no extractor defined on an object called ->, but, alas, even (a :: b) => would not be allowed, because there is no pattern matching going on in functional literal parameter declaration. You must simply state the parameters on the left side of =>, without doing any kind of decomposition. You may, however, do this:
if ( extension.exists( t => val (s, (p,c)) = t; this.isGoal( s ) ) )
Note that I replaced -> with ,. This works because a -> b is a syntactic sugar for (a, b), which is, itself, a syntactic sugar for Tuple2(a, b). As you don't use neither p nor c, this works too:
if ( extension.exists( t => val (s, _) = t; this.isGoal( s ) ) )
Finally, your recursive code is perfectly fine, though probably not optimized for tail-recursion. For that, you either make your method final, or you make the recursive function private to the method. Like this:
final def breadthFirstHelper
or
def breadthFirstHelper(...) {
def myRecursiveBreadthFirstHelper(...) { ... }
myRecursiveBreadthFirstHelper(...)
}
On Scala 2.8 there is an annotation called #TailRec which will tell you if the function can be made tail recursive or not. And, in fact, it seems there will be a flag to display warnings about functions that could be made tail-recursive if slightly changed, such as above.
EDIT
Regarding Oxbow's solution using case, that's a function or partial function literal. It's type will depend on what the inference requires. In that case, because that's that exists takes, a function. However, one must be careful to ensure that there will always be a match, otherwise you get an exception. For example:
scala> List(1, 'c') exists { case _: Int => true }
res0: Boolean = true
scala> List(1, 'c') exists { case _: String => true }
scala.MatchError: 1
at $anonfun$1.apply(<console>:5)
... (stack trace elided)
scala> List(1, 'c') exists { case _: String => true; case _ => false }
res3: Boolean = false
scala> ({ case _: Int => true } : PartialFunction[AnyRef,Boolean])
res5: PartialFunction[AnyRef,Boolean] = <function1>
scala> ({ case _: Int => true } : Function1[Int, Boolean])
res6: (Int) => Boolean = <function1>
EDIT 2
The solution Oxbow proposes does use pattern matching, because it is based on function literals using case statements, which do use pattern matching. When I said it was not possible, I was speaking of the syntax x => s.