Scala String* type (in function args) - scala

I have the following method:
def m(a: String*) = { // ... }
I'm wondering what the use is of the asterisk (*) symbol in this syntax? I'm obviously new to Scala. I googled but am probably googling the wrong thing. Any help is appreciated.
Cheers!

Its called as "var args" (variable arguments).
def concat(strs: String*): String = strs.foldLeft("")(_ ++ _)
Scala REPL
scala> def concat(strs: String*): String = strs.foldLeft("")(_ ++ _)
concat: (strs: String*)String
scala> concat()
res6: String = ""
scala> concat("foo")
res7: String = foo
scala> concat("foo", " ", "bar")
res8: String = foo bar

This is called a repeated parameter (see Section 4.6.3 of the Scala Language Specification).
Repeated Parameters allow a method to take an unspecified number of arguments of the same type T, which are accessible inside the method body bound to a parameter of type Seq[T].
In your case, inside the method m, the parameter a will be bound to a Seq[String].

That's the syntax to define a method that take a variable number of arguments.
Your m method can take 0, 1 or more arguments and these are all valid invocations:
m()
m("hello")
m("hello", "world")
You can also pass a collection to that method if you use the appropriate type hint:
val words = Seq("hello", "world")
m(words: _*)
You can play around with this code here on Scastie (where I implemented m as the concatenation of the input strings).

Related

meaning of String* in scala [duplicate]

I have the following method:
def m(a: String*) = { // ... }
I'm wondering what the use is of the asterisk (*) symbol in this syntax? I'm obviously new to Scala. I googled but am probably googling the wrong thing. Any help is appreciated.
Cheers!
Its called as "var args" (variable arguments).
def concat(strs: String*): String = strs.foldLeft("")(_ ++ _)
Scala REPL
scala> def concat(strs: String*): String = strs.foldLeft("")(_ ++ _)
concat: (strs: String*)String
scala> concat()
res6: String = ""
scala> concat("foo")
res7: String = foo
scala> concat("foo", " ", "bar")
res8: String = foo bar
This is called a repeated parameter (see Section 4.6.3 of the Scala Language Specification).
Repeated Parameters allow a method to take an unspecified number of arguments of the same type T, which are accessible inside the method body bound to a parameter of type Seq[T].
In your case, inside the method m, the parameter a will be bound to a Seq[String].
That's the syntax to define a method that take a variable number of arguments.
Your m method can take 0, 1 or more arguments and these are all valid invocations:
m()
m("hello")
m("hello", "world")
You can also pass a collection to that method if you use the appropriate type hint:
val words = Seq("hello", "world")
m(words: _*)
You can play around with this code here on Scastie (where I implemented m as the concatenation of the input strings).

Get value from map returned from function with implicit in Scala

Having an implicit value and function defined as follows
implicit val v = 0
def function(implicit v: Int): Map[String, String] = Map("key" -> "value")
I can do
function.get("key") // res0: Option[String] = Some(value)
function(v)("key") // res0: String = value
but the following doesn't compile
function("key")
So how can I in one go access a map using parentheses and pass implicit parameter?
Here are your options:
scala> function.apply("key")
res6: String = value
scala> function(implicitly)("key")
res7: String = value
As compiler can't know if you want to pass an implicit parameter explicitly or call apply method, designers decided it will mean passing the implicit parameter.
You can either give up on using the syntactic sugar and just use apply that will resolve ambiguity or you can pass the parameter explicitly, but let the compiler find the value.

In Scala, how to use 'toArray()' to turn a stack to a array?

I use the 'toArray' api of immutable.Stack like the codes below in Scala, but it reports error.
var stack1 = mutable.Stack[Long]()
val array = stack1.toArray();
It reports 'Cannot resolve reference toArray with such signature' about toArray
and "unspecified value parameters" about the '()' of toArray() !
An image
TLDR
the correct way is to call toArray without parentheses
Explanation
toArray function has the following signature (you can use tab to expand signatures in Scala repl):
scala> stack1.toArray
def toArray[B >: Long](implicit evidence$1: scala.reflect.ClassTag[B]): Array[B]
It expects ClassTag implicit parameter:
scala> stack1.toArray
res2: Array[Long] = Array()
scala> stack1.toArray(scala.reflect.classTag[Long])
res3: Array[Long] = Array()
In the first case, parameter is substituted by compiler. In the second case parameter passed explicitly.

What method conversion has been applied to this example?

In the spec of scala 6.26.2, there are 4 kind of conversions for methods:
MethodConversions
The following four implicit conversions can be applied to methods which are not applied to some argument list.
Evaluation. A parameterless method m of type => T is always converted to type T by evaluating the expression to which m is bound.
Implicit Application. If the method takes only implicit parameters, implicit argu- ments are passed following the rules of §7.2.
Eta Expansion. Otherwise, if the method is not a constructor, and the expected type pt is a function type (Ts′) ⇒ T′, eta-expansion (§6.26.5) is performed on the expression e.
Empty Application. Otherwise, if e has method type ()T , it is implicitly applied to the empty argument list, yielding e().
Some scala code:
def hello(): String = "abc"
def world1(s: String) = s
def world2(s: => String) = s
def world3(s: () => String) = s
world1(hello)
world2(hello)
world3(hello)
My question is, for world1, world2 and world3, which conversion rule is applied to each of them?
def world1(s: String) = s
world1(hello)
Empty application: hello is evaluated as hello() and then passed as the argument of world1
def world2(s: => String) = s
world2(hello)
Eta-expansion + Evaluation: hello is expanded into a function and evaluated lazily.
def world3(s: () => String) = s
world3(hello)
Eta-expansion: hello is expanded to a Function0[String]
Eta-expansion is necessary because methods and functions are two different things, even though the scala compiler is very good at hiding this difference.
The difference comes from the fact that methods are a JVM concept, whereas first-class functions are a scala-specific concept.
You can try this out in a REPL. First, let's define a method hello
scala> def hello(s: String) = s"hello $s"
hello: (s: String)String
scala> hello.hashCode
<console>:9: error: missing arguments for method hello;
follow this method with `_' if you want to treat it as a partially applied function
hello.hashCode
^
Woops, hello is not a value (in the JVM sense)! Not having an hashcode is a proof of it.
Let's get a Function1 out of the hello method
scala> hello _
res10: String => String = <function1>
scala> (hello _).hashCode
res11: Int = 1710358635
A function is a value, so it has an hashcode.

What's the difference between fun and fun() in Scala?

Here are two method declaration:
def fun = "x"
def fun() = "x"
Since they both need no parameter and return a String, what's the difference besides invoking way?
Besides being right on the convention for no side effect for functions without parameters, there IS a difference between 'fun' and 'fun()' in Scala.
'fun' is called a 'parameterless' function, whereas 'fun()' is function with an 'empty parameter list'.
To make a long story short:
scala> def fun() = "x"
fun: ()java.lang.String
scala> fun
res0: java.lang.String = x
scala> fun()
res1: java.lang.String = x
scala> def fun = "y"
fun: java.lang.String
scala> fun
res2: java.lang.String = y
scala> fun()
<console>:9: error: not enough arguments for method apply: (index: Int)Char in class StringOps.
Unspecified value parameter index.
fun()
^
It's just a convention:
obj.fun //accessing like property with no side-effects
obj.fun() //ordinary method call, return value, but might also have side-effects
Prefer () version to emphasize that this is a method as opposed to simple property.
Note that this is just a convention, a way to document code, the compiler does not enforce the rules above.
Functions without () are usually used to express functionality without side effects, as #Tomasz noted (e.g. length of string - as far you have the same string, length would be the same)
If you define function without parentheses, you can't use them when you call function:
scala> def fun = "x"
fun: java.lang.String
scala> fun
res0: java.lang.String = x
scala> fun()
<console>:9: error: not enough arguments for method apply: (n: Int)Char in trait StringLike.
Unspecified value parameter n.
fun()
^
scala> def fun() = "x"
fun: ()java.lang.String
//now you may use () or may not - it is up to you
scala> fun
res2: java.lang.String = x
scala> fun()
res3: java.lang.String = x
(Addenda) You can find the "pure vs side effect" convention here : Scala Style Guide Chapter 3.4.2