Array("hi","there").map(println)
Array("hi","there").map(s => println(s))
Array("hi","there").map(println(_))
Each of the above statements yields the same output though in the first 2 argument to map is a function object whereas in the last one it is function invocations.
How is map able to handle both?
Signature of map in TraversableLike class is like this:
def map[B, That](f: scala.Function1[A, B])(implicit bf: scala.collection.generic.CanBuildFrom[Repr, B, That]) : That = { /* compiled code */ }
How is map able to handle both?
It is able to handle both because the compiler created a method value for map by performing eta-expansion on the println. There is a distinction in Scala between methods and functions, where the former doesn't hold any value, which makes the compiler need to go the extra mile to make it work.
The compiler after eta-expansion actually emits:
Array("hi","there").map(s => println(s))
Matching your second example. The actual code is more verbose, but means the same:
scala.this.Predef.refArrayOps[String](
scala.Array.apply[String]("hi", "there")(
(ClassTag.apply[String](classOf[java.lang.String]): scala.reflect.ClassTag[String])))
.map[Unit, Any]({((x: Any) => scala.this.Predef.println(x))
})(scala.this.Array.canBuildFrom[Unit]((ClassTag.Unit: scala.reflect.ClassTag[Unit])));
As #slouc said in the comments, the third example using the placeholder syntax is desugered into s => println(s), which makes it an equivalent to your second example.
As a complete not so important side note, since println returns Unit, Array.foreach would be more suitable here:
Array("hi","there").foreach(println)
Related
Where UserData.retrieve is of type (m: Map[String, String]) => User
and UserData.update is of type (r: spark.sql.Row) => Unit
why does
receipts map UserData.retrieve
work fine, but when I run
events foreach UserData.update
it results in the following error:
missing argument list for method update in object UserData
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `update _` or `update(_)` instead of `update`.
I see in the documentation that map expects func: (T) ⇒ U and foreach expects f: (T) ⇒ Unit so it seems to me that the compiler should convert my methods to functions for both map and foreach, but instead it only does so for map. Why?
n.b. I know that I can make this foreach call work by explicitly converting it,
receipts.foreach.(UserData.update(_))
but here I am asking for help understanding why I have to.
Unapplied methods are only converted to functions when a function type is expected.
foreach on Dataset is overloaded and may be called with ForeachFunction[T] or T => Unit.
The compiler does not have enough information to resolve which overloaded method is being called and therefore will not apply the function.
In Scala (Play Framework), I can't understand the type signatures even though I read through all the symbols in here.
For example:
/* matches if a == b */
def equalTo[T](t: => T): BeEqualTo
class BeEqualTo(t: => Any)
extends BeTypedEqualTo[Any]
What on earth do these type signatures even mean?
For example, what exactly is "a" and "b" in the documentation? All I see is "t". Is equalTo a function that takes in a function which returns a value of generic type T?
Another example...
Say I have this line...
status(home).must(equalTo(OK))
According to the IDE, OK is a pattern or symbol of type Int. So OK is an Int? You can monkey-patch an int to give it a function like "must", but how can an Int go inside of "equalTo", a function that takes in a function?
Now some of the type signatures make sense. For example...
def status(of: Future[Result])(implicit timeout: Timeout): Int
^ This is a curried function that takes in a future that returns something of type Result and that sucks in an implicit parameter of type Timeout from somewhere (Scala magic) and returns an Int. "home" is of type "Future[Result]", so it fits inside "status".
But other stuff...
contentType(home).must(beSome.which(_ == "text/html"))
^ My IDE says that beSome is of type
def beSome[T](check: ValueCheck[T]): SomeCheckedMatcher[T]
^ So "beSome" is a function. If that is the case, then how on earth can I appeand ".which()", another function, to it as if it were an object?
Another example...
def which[R : AsResult](f: (U) => R): OptionLikeCheckedMatcher[F, Nothing, U]
^ How on earth do you read these type signatures? "which" takes in "f: (U)", or a variable which we call "f" of type "(U)"? Why the unnecessary parenthesis around the "(U)"? Can't you just say "f: U" and make U be a String if R is a String?
"must" is like this...
def must(m: => Matcher[T]): MatchResult[T]
^ So "must" takes in a function that returns a Matcher. But "which" is passing in an OptionLikeCheckedMatcher. "m: => Matcher[T]" is a function that takes in an "m" and returns a "Matcher[T]". How is that the same as an object of type OptionLikeCheckedMatcher?
Can someone provide a definitive guide as to how to read Scala type signatures?
I think you're getting a little confused with the distinction between a function-valued parameter and a call-by-name parameter. They are similar but not quite the same. In the first example you posted, def equalTo[T](t: => T): BeEqualTo, the : => notation means that the parameter is not evaluated immediately (as it would be if it were declared with just a colon), but every time it is used in an expression. This link might clarify things a bit for you: https://tpolecat.github.io/2014/06/26/call-by-name.html
In another example you posted, def which[R: AsResult](f: (U) => R): OptionCheckedLikeMatcher[F, Nothing, U] takes in a function parameter called f, which accepts a U as its argument and returns a T. The brackets around the U are indeed unnecessary, but they would have been necessary if (for example) f were a function taking 2 parameters of type U - we would then have written it as f: (U, U) => R. The return value of which will be an OptionCheckedMatcher. Assuming that this is a subtype of Matcher (which seems sensible), this is the value which is passed to must.
I'm entirely new to Scala and while reading some tutorials and documentation, I experimented with defining custom control structures.
So I tried to implement an implicit class MyBoolean that provides a ? method with two parameter lists. The first parameter is a block that gets executed if MyBoolean is true, the second gets executed if MyBoolean is false.
Here is an example of how the syntax of the resulting control structure should look like:
true ? {println("true")} {println("false")};
so essentially just a simple if-else statement implemented as a method on Boolean.
Here is my implementation:
object Test extends App {
implicit class MyBoolean(val value: Boolean) {
def ? (body1: => Unit)(body2: => Unit){
if (value) body1;
else body2
}
}
override def main(args: Array[String]): Unit = {
// true ? {println("true")} {println("false")}; //--> compiler error
true.? {println("true")} {println("false")}; // works fine...
}
}
The problem I'm facing is that I get the following compiler error with the intended syntax (in Eclipse):
missing arguments for method ? in class MyBoolean; follow this method
with `_' if you want to treat it as a partially applied function
It only works if I explicitly add the dot . before the method ?.
Shouldn't the dot be optional in Scala when calling methods? Is there anything I'm missing?
Shouldn't the dot be optional in Scala when calling methods?
Sort of, but that's not exactly accurate.
In these cases, that's true:
a.b(c) can be written as a b c
a.b(c, d) can be rewritten as a b (c, d).
From the language spec section 6.12.3, Infix Operations:
The right-hand operand of a left-associative operator may consist of several arguments enclosed in parentheses, e.g. e op e1, …, en. This expression is the interpreted as e.op(e1, …, en).
A left-associative binary operation e1 op e2 is interpreted as e1.op(e2).
But there is no corresponding rule for expressions of the form a.b(c)(d). I'm not really sure why, though. It seems to me that a b {c} {d} would be a perfectly reasonable way to write that.
This is one of the weirdest wrinkles in Scala syntax. You can still use point-free style with multiple argument lists but you have to group the object, method, and first argument list using parentheses (?!)
(true ? {println("true")}) {println("false")}
works just fine.
Why does it work this way? It is rather convenient with the /: and :\ fold symbols; then you can group your first element together with the collection it's supposed to run through.
For everything else it is questionable at best.
Regardless, you're stuck with either parentheses or a dot.
The dot's optional when calling 1-parameter methods, but that syntax doesn't work for a 2-parameter method, even when curried (except as #RexKerr suggests if you bracket it).
You might be able to get it working by doing "manual" currying: write a one-parameter method that returns an object with an apply:
class PartiallyApplied(value: Boolean, body1: => Unit) {
def apply(body2: => Unit) = if (value) body1; else body2
}
class MyBoolean...
def ? (body1: => Unit) = new PartiallyApplied(value, body1)
Is there a reason to use a PartialFunction on a function that's not partial?
scala> val foo: PartialFunction[Int, Int] = {
| case x => x * 2
| }
foo: PartialFunction[Int,Int] = <function1>
foo is defined as a PartialFunction, but of course the case x will catch all input.
Is this simply bad code as the PartialFunction type indicates to the programmer that the function is undefined for certain inputs?
There is no advantage in using a PartialFunction instead of a Function, but if you have to pass a PartialFunction, then you have to pass a PartialFunction.
Note that, because of the inheritance between these two, overloading a method to accept both results in something difficult to use, as the type inference won't work.
The thing is, there are many examples of times when what you need to define on a trait/object/function definition is a PartialFunction but in reality the real implementation may not be one. Case in point, take a look at def collect[B](f: PartialFunction[A,B]):
val myList = thatList collect {
case Right(value) => value
case Left(other) => other.toInt
}
It's clearly not a "real" partial as it is defined for all input. That said, if I wanted to, I could just have the Right match.
However, if I were to have written collect as a full on plain function, then I'd miss out on the desired behavior (that is to be both a filter and a map rolled into one base on when a function is defined.) That's nice behavior and allows for a lot of flexibility when writing my own code.
So I guess the better question is, will you ever want behavior to reflect that a function might not be defined everywhere? If the answer is no, then don't do it.
PartialFunction literals allow pattern matching directly on arguments (e.g. { case (a, b) => ... } instead of _ match { case (a, b) => ... }), which makes code more readable (see #wheaties' answer for another example).
EDIT: apparently this is wrong, see Daniel C. Sobral's comment on his answer. Not deleting, so that the comments still make sense.
I'm working on a DSL for a experimental library I'm building in Scala, and I've run into some vexing peculiarities of Scala's type inference as it pertains to lambda expression arguments that don't seem to be covered in the book Programming In Scala.
In my library, I have a trait, Effect[-T], that is used to represent temporary modifiers that can be applied to an object of type T. I have a object, myEffects, that has a method named += that accepts an argument of type Effect[PlayerCharacter]. Lastly, I have a generic method, when[T], that is used for constructing conditional effects by accepting a conditional expression and another effect as an argument. The signature is as follows:
def when[T](condition : T => Boolean) (effect : Effect[T]) : Effect[T]
When I call the "when" method with the above signature, passing it's result to the += method, it is unable to infer the type of the argument to the lambda expression.
myEffects += when(_.hpLow()) (applyModifierEffect) //<-- Compiler error
If I combine the arguments of "when" into a single parameter list, Scala is able to infer the type of the lambda expression just fine.
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T]
/* Snip */
myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
It also works if I remove the second parameter entirely.
def when[T](condition : T => Boolean) : Effect[T]
/* Snip */
myEffects += when(_.hpLow()) //This works too!
However, for aesthetic reasons, I really want the the arguments to be passed to the "when" method as separate parameter lists.
My understanding from section 16.10 of Programming in Scala is that the compiler first looks at whether the method type is known, and if so it uses that to infer the expected type of it's arguments. In this case, the outermost method call is +=, which accepts an argument of type Effect[PlayerCharacter]. Since the return type of when[T] is Effect[T], and the method to which the result is being passed expects an argument of type Effect[PlayerCharacter], it can infer that T is PlayerCharacter, and therefore the type of the lambda expression passed as the first argument to "when" is PlayerCharacter => Boolean. This seems to be how it works when the arguments are provided in one parameter list, so why does breaking the arguments into two parameter lists break it?
I'm relatively new to Scala myself, and I don't have a lot of detailed technical knowledge of how the type inference works. So best take this with a grain of salt.
I think the difference is that the compiler is having trouble proving to itself that the two Ts are the same in condition : T => Boolean and effect : Effect[T], in the two-parameter-list version.
I believe when you have multiple parameter lists (because Scala views this as defining a method which returns a function that consumes the next parameter list) the compiler treats the parameter lists one at a time, not all together as in the single parameter list version.
So in this case:
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T]
/* Snip */
myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
The type of applyModifierEffect and the required parameter type of myEffects += can help constrain the parameter type of _.hpLow(); all the Ts must be PlayerCharacter. But in the following:
myEffects += when(_.hpLow()) (applyModifierEffect)
The compiler has to figure out the type of when(_.hpLow()) independently, so that it can check if it's valid to apply it to applyModifierEffect. And on its own, _.hpLow() doesn't provide enough information for the compiler to deduce that this is when[PlayerCharacter](_.hpLow()), so it doesn't know that the return type is a function of type Effect[PlayerCharacter] => Effect[PlayerCharacter], so it doesn't know that it's valid to apply that function in that context. My guess would be that the type inference just doesn't connect the dots and figure out that there is exactly one type that avoids a type error.
And as for the other case that works:
def when[T](condition : T => Boolean) : Effect[T]
/* Snip */
myEffects += when(_.hpLow()) //This works too!
Here the return type of when and its parameter type are more directly connected, without going through the parameter type and the return type of the extra function created by currying. Since myEffects += requires an Effect[PlayerCharacter], the T must be PlayerCharacter, which has a hpLow method, and the compiler is done.
Hopefully someone more knowledgeable can correct me on the details, or point out if I'm barking up the wrong tree altogether!
I am a little confused because in my view, none of the versions you say work should, and indeed I cannot make any of them work.
Type inferences works left to right from one parameter list (not parameter) to the next. Typical example is method foldLeft in collections (say Seq[A])
def foldLeft[B] (z: B)(op: (B, A) => B): B
The type of z will makes B known, so op can be written without specifying B (nor A which is known from the start, type parameter of this).
If the routine was written as
def foldLeft[B](z: B, op: (B,A) => B): B
or as
def foldLeft[B](op: (B,A) => B)(z: B): B
it would not work, and one would have to make sure op type is clear, or to pass the B explicity when calling foldLeft.
In your case, I think the most pleasant to read equivalent would be to make when a method of Effect, (or make it look like one with an implicit conversion) you would then write
Effects += applyModifierEffect when (_.hpLow())
As you mentionned that Effect is contravariant, when signature is not allowed for a method of Effect (because of the T => Boolean, Function is contravariant in its first type parameter, and the condition appears as a parameter, so in contravariant position, two contravariants makes a covariant), but it can still be done with an implicit
object Effect {
implicit def withWhen[T](e: Effect[T])
= new {def when(condition: T => Boolean) = ...}
}