This question already has answers here:
What does => and () => mean in Scala [duplicate]
(5 answers)
Closed 6 years ago.
While looking at an open source code I found out that sometimes some people use syntax like this:
Seq[Date => String]
Can you please explain what does this mean and how it is used? I am new to Scala.
Seq[Date => String]
Is a sequence of functions from Date (taking in a parameter of type Date) to String (returning a String). It is syntactic sugar for Function1[Date, String]:
Seq[Function1[Date, String]]
For example, one could use:
val x = List[Date => String](date => date.toString)
Which, when invoked, would print the toString method of the Date class.
It means this is a sequence of Functions from Date to String. In Scala, functions are first-class citizens, which means (among other things) that functions have types. A => B is the notation describing the type of a function that takes an argument of type A and returns a value of type B.
For example, you can write:
val f1: Date => String = d => d.toString
def f2(d: Date): String = d.toString
val s: Seq[Date => String] = Seq(f1, f2)
Related
This question already has answers here:
How do I get around type erasure on Scala? Or, why can't I get the type parameter of my collections?
(11 answers)
sbt compile time warning: non-variable type argument String in type pattern List[String]
(2 answers)
Closed 3 years ago.
I have a function which takes the parameter. Its data type is Any. I want to differentiate List from other data types like String, Int, Double. I want to check if the parameter value is list or not here is my code
val userList: List[String] = List("1","2")
val user = "UserList"
val name = "Name"
myFunction(user, userList)
def myFunction(fieldName: String, value: Any): Unit = {
if (fieldName.equals(user)) {
value match {
case list: List[String] => print("its a list perform operation accordingly")
}
}
else {
log.info("its a string")
}
}
But the compiler generates the warning:
non-variable type argument String in type pattern List[String] (the
underlying of List[String]) is unchecked since it is eliminated by
erasure
I want to fix this warning message.
I do not want to use asInstanceOf like
val list = value.asInstanceOf[List[String]]
to avoid this warning message.
Since you don't care about the element type of the List you can just leave the type blank:
case _: List[_] => print("its a list perform operation accordingly")
You cannot test specifically for List[String] because this information is not available when the test is executed. It you want to do this you will need to use a type class or polymorphism.
I'm learning specs2 testing framework by following some of its examples.
I've noticed the following anonymous function syntax is recurring:
val upper = (_: String).toUpperCase
which is equivalent to more conventional / usual
val upper = (s: String) => s.toUpperCase
Although the syntax is simple and elegant, yet it's not very familiar (easy).
Can someone step me through how the first syntax works / derives? I'm pretty sure that it has to do with some sort of partial application but cannot reason fully.
Also is the syntax used frequently in Scala? (I'm still learning the ropes here :] )
Edit::
I've found the recurring pattern to use such syntax is with ad-hoc polymorphism (simply, overloaded methods / functions) where argument type of the passed function determines what function is dispatched.
For example,
def f(g: Int => String): String = g(10)
def f(g: String => String): String = g("hello")
f((_: Int).toString + " beers") // 10 beers
f((_: String) + " world") // hello world
This kind of pattern is recurring in libraries like ScalaCheck.
The syntax indicates the compiler you're creating a function with a parameter of type String, which is inserted where the _ is used, according to parameter order. If you had:
val f = (_:String).length + (_:Int)
it would create a function (String, Int) => Int, where each _ marks where the parameter is being used. The order is important! They must be used in the same order you want the function's parameters to be
If the types are already defined when declaring the val, you can omit them in the function body:
val f: (String, Int) => Int = _.length + _
This question already has answers here:
Scala foreach strange behaviour
(5 answers)
Closed 7 years ago.
Given these case classes:
case class FeatureDistance(id: Long, distance: Double)
case class SearchResult(score: Float, id: Long)
Why does this not compile?
val distances = List[FeatureDistance](FeatureDistance(1L, 10f))
val results = distances.map(SearchResult(0f, _.id))
But this does:
val results = distances.map(fd => SearchResult(0f, fd.id))
The compilation error says: missing parameter type for expanded function ((x$3) => x$3.id)
Is it because _ is only scoped to the map function so it's not visible in the SearchResult.apply call?
After doing a bit of research, I found a post on the old scala forums that contains this quote:
When you use "_" as a place holder for an anonymous parameter of a function, the scope of that function is the innermost parenthesis containing it.
So, it's just a question of scope. I suspect this has to do with problems that could otherwise result from having nested function calls that use more than one underscore. For instance:
//suppose we have some x:List[List[Int]]
x.map(_.map(_ + 1))
Somewhat similar to Stack Overflow question Compose and andThen methods, I've been working through Twitter's Scala School tutorial and quickly ran into the same problem that a commenter had (which was great, because I went to bed thinking my problem was solved).
In the tutorial, it defines two methods as such:
def addUmm(x: String) = x + " umm"
def addAhem(x: String) = x + " ahem"
and while in newer versions of Scala, you can't call compose on them as such: addUmm(_).compose(addAhem(_)), the accepted answer (and some of the other answers seem to hinge upon the fact that addUmm and addAhem are methods, not functions, which creates an issue when trying to call compose. I went to bed satisfied, having successfully run:
scala> ((s: String) => s + " umm").compose((s: String) => s + " ahem")
res0: String => java.lang.String = <function1>
Cool. The issue is that while not being able to compose methods makes some sense, when I the same thing with values I know evaluate to Function1:
val a = (s: String) => s + " umm"
val b = (s: String) => s + " ahem"
val c = a(_).compose(b(_))
Well, that last line coughs up the same error that the original question did, even though they're partial applications of functions this time, not methods. One of the answers in the original question (highly-ranked, but not the accepted answer) seems to hint that it has to do with how the partial application is expanded, what is the explanation?
For a Scala newbie, the fact that the inferencer gets a(_).compose(b(_)) wrong no matter if you explicitly specify _: String both places, but a.compose(b) does is somewhat confusing.
a(_).compose(b(_)) expands to x => { a(x).compose(y => b(y) }. Hence the error. What you want is (x => a(x)).compose(y => b(y)). Adding a pair of parentheses fixes this.
scala> (a(_)).compose(b(_: String))
res56: String => java.lang.String = <function1>
scala> res56("hello")
res57: java.lang.String = helloahemumm
But since a and b are functions, you can avoid all this cruft and simply do a compose b.
You can use simply 'a compose b'.
scala> val c = a compose b
c: String => java.lang.String = <function1>
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Syntax sugar: _*
I wrote a function that gets passed a format string (for String.format(...)) and a varargs array of parameters (among other things). The method looks like this:
def myMethod(foo: Number, formatStr: String, params: Any*): Unit = {
// .. some stuff with foo
println(formatStr, params.map(_.asInstanceOf[AnyRef]) : _*)
}
I got the syntax for the params argument here. It works! But how? I do not understand the syntax of the second argument to println, particularly the ending part (: _*). It is obviously calling map and expanding the array to a sequence of AnyRefs.
Generally, the : notation is used for type ascription, forcing the compiler to see a value as some particular type. This is not quite the same as casting.
val b = 1 : Byte
val f = 1 : Float
val d = 1 : Double
In this case, you're ascribing the special varargs type _*. This mirrors the asterisk notation used for declaring a varargs parameter and can be used on a variable of any type that subclasses Seq[T]:
def myMethod(params: Any*) = ... //varargs parameter, use as an Array[Any]
val list = Seq("a", 42, 3.14) //a Seq[Any]
myMethod(list : _*)
The ending part : _* converts a collection into vararg parameters.
It looks weird, I know.