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.
Related
I have a method that with the implicit parameter. i get a error when i convert it to function in 2 case :
1:
def action(implicit i:Int) = i + " in action"
val f = action _
then i get a StackOverflowError.
2:
def action(implicit i:Int) = i + " in action"
val f = action(_)
then i get a error: missing parameter type
I must write like this :
val f = (i:Int) => action(i)
that's ok. And if the parameter of 'action' is not the implicit , all case are right. So how to explain , and what i miss ?
If you specify a parameter to a function to be implicit, you are inviting the compiler to supply the value of that parameter for you. So how does the compiler find those values? It looks for values of the same type (Int in your case) that have been declared as implicit values in a variety of scopes.
(For simplicity, I'll just use a local scope in this example, but you might want to read up on this topic. Programming in Scala, 3rd Ed is a good first step.)
Note that the names of the implicit values are ignored and have no bearing on proceedings, the compiler only looks at the types of implicit values. If multiple implicit values with the required type are found in the same scope, then the compiler will complain about ambiguous implicit values.
For example, the following provides a function with an implicit parameter and a default value for that parameter within the current scope:
def greetPerson(name: String)(implicit greeting: String) = s"$greeting $name!"
implicit val defaultGreeting = "Hello" // Implicit value to be used for greeting argument.
val y = greetPerson("Bob") // Equivalent to greetPerson("Bob")(defaultGreeting).
val z = greetPerson("Fred")("Hi")
Note that y is just a String value of "Hello Bob!", and z is a string with the value "Hi Fred!"; neither of them are functions.
Also note that greetPerson is a curried function. This is because implicit parameters cannot be mixed with regular, non-implicit parameters in the same parameter list.
In general, it's bad practice to use common types (Int, Boolean, String, etc.) as values for implicit parameters. In a big program, there might be a lot of different implicit values in your scope, and you might pick up an unexpected value. For that reason, it's standard practice to wrap such values in a case class instead.
If you're trying to create a value that supplies some of the arguments of another function (that is, a partially applied function), then that would look something like this:
def greetPerson(greeting: String, name: String) = s"$greeting $name!"
val sayHello = greetPerson("Hello", _: String)
val y = sayHello("Bob") // "Hello Bob!"
val sayHi = greetPerson("Hi", _: String)
val z = sayHi("Fred") // "Hi Fred!"
In both cases, we're creating partially applied functions (sayHi and sayHello) that call greetPerson with the greeting parameter specified, but which allow us to specify the name parameter. Both sayHello and sayHi are still only values, but their values are partially applied functions rather than constants.
Depending upon your circumstances, I think the latter case may suit you better...
I would also read up on how the underscore character (_) is used in Scala. In a partially applied function declaration, it corresponds to the arguments that will be provided later. But it has a lot of other uses too. I think there's no alternative to reading up on Scala and learning how and when to use them.
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)
This question already has answers here:
What does param: _* mean in Scala?
(3 answers)
Closed 8 years ago.
Hi I have following code
CookieMock(response, email).cookies: _*
.cookies is type def cookies: scala.Seq[Cookie].
What does :_* mean in Scala?
Thanks
If you are familiar with Java
here is the same explanation in Java:
varargs
Because * is not a type, you add the underscore.
def printInts(ints: Int*) = ints.mkString(",")
printInts(1,2,3)
//printInts(List(1,2,3)) //type mismatch; found : List[Int] required: Int
printInts(List(1,2,3): _*)
paste this to codebrew.io this will clarify.
The : is type ascription. _* is the type you ascribe when you need a Seq[A] to be treated as A*.
http://docs.scala-lang.org/style/types.html
The following are examples of ascription:
Nil: List[String]
Set(values: _*)
"Daniel": AnyRef
Ascription is basically just an up-cast performed at compile-time for the sake of the type checker. Its use is not common, but it does happen on occasion. The most often seen case of ascription is invoking a varargs method with a single Seq parameter. This is done by ascribing the _* type (as in the second example above).
Say I have a function
def f(a:Int = 0, b:String = "", c:Float=0.0, foos: Foo*) { ... }
Notice the use of default arguments for some parameters. Typically, to make use of default values, you invoke a function with named parameters like so:
val foo = Foo("Foo!")
f(foos = foo)
This syntax works because I'm only invoking the method with one foo. However, if I have two or more
val foo1 = Foo("Foo!")
val foo2 = Foo("Bar!")
f(foos = ...)
it's not so obvious what should be fed in here. Seq(foo1,foo2) and Seq(foo1,foo2):_* do not type check.
What's more, how can I call it with no foos?
// All out of foos!
f(foos = ...)
For this case, calling the function with empty parentheses (f()) does not work.
Thanks!
For the default parameters, see my comment to your question. For how to call the variadic part with a named argument, see below (scala 2.9.2):
scala> case class Foo(a:Int)
defined class Foo
scala> def f(a:Int, foos: Foo*) = foos.length
f: (a: Int, foos: Foo*)Int
scala> f(a=2, foos=Foo(2))
res0: Int = 1
// I'm not sure if this is cheating...
// am I just naming the first of the two variadic arguments?
scala> f(a=2, foos=Foo(2),Foo(3))
res1: Int = 2
//anyway you can do ....
scala> f(a=2, foos=Seq(Foo(1), Foo(2)):_*)
res2: Int = 2
// with no foos...
scala> f(a=2, foos=Nil:_*)
res3: Int = 0
Given the Scala 2.9 limitations that Paolo mentioned, you can still use currying to divide the parameters in different sections, one which uses named parameters with default arguments, and one for varargs (or multiple curried argument sections if you want more than one vararg parameter). Regarding readability the result is imho almost better than using named arguments only:
f(b="something")()
f(c=3.14)(foo1, foo2)
I'd like to initialize a scala BitSet to contain the integers from 1 to N. The following will work, but I'm looking for a better solution:
var s = BitSet.empty ++ (1 to n)
I was hoping that I could do something like this:
var s:BitSet = (1 to n).toSet
...but that results in an error:
error: polymorphic expression cannot be instantiated to expected type;
found : [B >: Int]scala.collection.immutable.Set[B]
required: scala.collection.immutable.BitSet
Am I missing something obvious?
Thats what breakOut is for:
val s: BitSet = (1 to n).map(identity)(breakOut)
See this question to understand the inner working of breakOut.
Another solution is to use the constructor of BitSet:
val s = BitSet((1 to n): _*)
the : _* tells the compiler that you want to use the Range as repeated parameters.
Because breakOut looks ugly you can use the pimp-my-library pattern to produce nicer looking code (as described here):
val s = (1 to n).to[BitSet]
Digging into the Scala source code, the definition of toBitSet is in TraversibleOnce.scala:
/** Converts this $coll to a set.
* $willNotTerminateInf
* #return a set containing all elements of this $coll.
*/
def toSet[B >: A]: immutable.Set[B] = immutable.Set() ++ self
So, interestingly enough, the Scala implementation of toSet is basically just doing your first solution behind the scenes in the case of a plain Set. If you really would strongly prefer the second syntax you suggested for the case of a BitSet, then you could roll your own with an implicit type conversion:
class BitSetConvertible(t: TraversableOnce[Int]) {
def toBitSet = BitSet.empty ++ t
}
implicit def asBitSetConvertible(t: TraversableOnce[Int]) = new BitSetConvertible(t)
With that in place, you can now make statements like:
val s = 1 to 10 toBitSet