(Scala) How to convert List into a Seq - scala

I have a function like
def myFunction(i:Int*) = i.map(a => println(a))
but I have a List of Int's.
val myList:List[Int] = List(1,2,3,4)
Desired output:
1
2
3
4
How can I programmatically convert myList so it can be inserted into myFunction?

Looking at your desired input and output, you want to pass a List where a varargs argument is expected.
A varargs method can receive zero or more arguments of same type.
The varargs parameter has type of Array[T] actually.
But you can pass any Seq to it, by using "varargs ascription/expansion" (IDK if there is an official name for this):
myFunction(myList: _*)

Related

Scala. Need for loop where the iterations return a growing list

I have a function that takes a value and returns a list of pairs, pairUp.
and a key set, flightPass.keys
I want to write a for loop that runs pairUp for each value of flightPass.keys, and returns a big list of all these returned values.
val result:List[(Int, Int)] = pairUp(flightPass.keys.toSeq(0)).toList
for (flight<- flightPass.keys.toSeq.drop(1))
{val result:List[(Int, Int)] = result ++ pairUp(flight).toList}
I've tried a few different variations on this, always getting the error:
<console>:23: error: forward reference extends over definition of value result
for (flight<- flightPass.keys.toSeq.drop(1)) {val result:List[(Int, Int)] = result ++ pairUp(flight).toList}
^
I feel like this should work in other languages, so what am I doing wrong here?
First off, you've defined result as a val, which means it is immutable and can't be modified.
So if you want to apply "pairUp for each value of flightPass.keys", why not map()?
val result = flightPass.keys.map(pairUp) //add .toList if needed
A Scala method which converts a List of values into a List of Lists and then reduces them to a single List is called flatMap which is short for map then flatten. You would use it like this:
flightPass.keys.toSeq.flatMap(k => pairUp(k))
This will take each 'key' from flightPass.keys and pass it to pairUp (the mapping part), then take the resulting Lists from each call to pairUp and 'flatten' them, resulting in a single joined list.

Scala: expanding Array of arguments into List gives error

I am attempting to pass a list of parameters to a function.
scala> val a = Array("col1", "col2")
a: Array[String] = Array(col1, col2)
I'm trying to use the :_* notation, but it's not working: and I cannot for the life of me work out why!
val edges = all_edges.select(a:_*)
<console>:27: error: overloaded method value select with alternatives:
(col: String,cols: String*)org.apache.spark.sql.DataFrame <and>
(cols: org.apache.spark.sql.Column*)org.apache.spark.sql.DataFrame
cannot be applied to (String)
This, however, does work:
val edges = all_edges.select("col1", "col2")
Not sure if it is relevant, but all_edges is a spark dataframe which I am attempting to only keep columns by specifying them in a list.
scala> all_edges
res4: org.apache.spark.sql.DataFrame
Any ideas? I've been trying to work out the syntax from eg. Passing elements of a List as parameters to a function with variable arguments but don't seem to be getting far
Edit: Just found How to "negative select" columns in spark's dataframe - but I am confused as to why the syntax twocol.select(selectedCols.head, selectedCols.tail: _*) is necessary?
If you want to pass strings, the signature of the function indicates that you have to pass at least one:
(col: String,cols: String*)org.apache.spark.sql.DataFrame
So you have to single out the first argument of your list : Spark cannot from the type of a Traversable alone determine that it is not empty.
val edges = all_edges.select(a.head, a.tail: _*)
Now, that's the dirty version of it. If you want to do this rigorously, you should check the list is not empty yourself:
val edges = a.headOption.map( (fst) => all_edges.select(fst, a.drop(1))

how to convert map into repeated tuple in scala

I have a method that accepts repeated tuples
myfn(attributes: (String, Any)*)
can I convert a map to a repeated tuple ?
for example
val m = Map ("a1"->1,"a2"->8) // convert to tuple
myfn(m1)
Sure, why not?
def function(myMap.toList(): _*)

What does param: _* mean in Scala?

Being new to Scala (2.9.1), I have a List[Event] and would like to copy it into a Queue[Event], but the following Syntax yields a Queue[List[Event]] instead:
val eventQueue = Queue(events)
For some reason, the following works:
val eventQueue = Queue(events : _*)
But I would like to understand what it does, and why it works? I already looked at the signature of the Queue.apply function:
def apply[A](elems: A*)
And I understand why the first attempt doesn't work, but what's the meaning of the second one? What is :, and _* in this case, and why doesn't the apply function just take an Iterable[A] ?
a: A is type ascription; see What is the purpose of type ascriptions in Scala?
: _* is a special instance of type ascription which tells the compiler to treat a single argument of a sequence type as a variable argument sequence, i.e. varargs.
It is completely valid to create a Queue using Queue.apply that has a single element which is a sequence or iterable, so this is exactly what happens when you give a single Iterable[A].
This is a special notation that tells the compiler to pass each element as its own argument, rather than all of it as a single argument. See here.
It is a type annotation that indicates a sequence argument and is mentioned as an "exception" to the general rule in section 4.6.2 of the language spec, "Repeated Parameters".
It is useful when a function takes a variable number of arguments, e.g. a function such as def sum(args: Int*), which can be invoked as sum(1), sum(1,2) etc. If you have a list such as xs = List(1,2,3), you can't pass xs itself, because it is a List rather than an Int, but you can pass its elements using sum(xs: _*).
For Python folks:
Scala's _* operator is more or less the equivalent of Python's *-operator.
Example
Converting the scala example from the link provided by Luigi Plinge:
def echo(args: String*) =
for (arg <- args) println(arg)
val arr = Array("What's", "up", "doc?")
echo(arr: _*)
to Python would look like:
def echo(*args):
for arg in args:
print "%s" % arg
arr = ["What's", "up", "doc?"]
echo(*arr)
and both give the following output:
What's
up
doc?
The Difference: unpacking positional parameters
While Python's *-operator can also deal with unpacking of positional parameters/parameters for fixed-arity functions:
def multiply (x, y):
return x * y
operands = (2, 4)
multiply(*operands)
8
Doing the same with Scala:
def multiply(x:Int, y:Int) = {
x * y;
}
val operands = (2, 4)
multiply (operands : _*)
will fail:
not enough arguments for method multiply: (x: Int, y: Int)Int.
Unspecified value parameter y.
But it is possible to achieve the same with scala:
def multiply(x:Int, y:Int) = {
x*y;
}
val operands = (2, 4)
multiply _ tupled operands
According to Lorrin Nelson this is how it works:
The first part, f _, is the syntax for a partially applied function in which none of the arguments have been specified. This works as a mechanism to get a hold of the function object. tupled returns a new function which of arity-1 that takes a single arity-n tuple.
Futher reading:
stackoverflow.com - scala tuple unpacking

Syntax sugar: _* for treating Seq as method parameters

I just noticed this construct somewhere on web:
val list = List(someCollection: _*)
What does _* mean? Is this a syntax sugar for some method call? What constraints should my custom class satisfy so that it can take advantage of this syntax sugar?
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 f(args: String*) = ... //varargs parameter, use as an Array[String]
val list = List("a", "b", "c")
f(list : _*)
That's scala syntax for exploding an array. Some functions take a variable number of arguments and to pass in an array you need to append : _* to the array argument.
Variable (number of) Arguments are defined using *.
For example,
def wordcount(words: String*) = println(words.size)
wordcount expects a string as parameter,
scala> wordcount("I")
1
but accepts more Strings as its input parameter (_* is needed for Type Ascription)
scala> val wordList = List("I", "love", "Scala")
scala> wordcount(wordList: _*)
3