Converting String arguments to Char in Scala - scala

Example code:
object test {
def main(args: Array[String]) {
println(args(0).toChar)
}
}
I have two arguments. The first one is a single letter, whereas the second one is a sequence of letters.
How can I convert the first string argument to Char? I tried the toChar function, but without success (error: value toChar is not a member of String).

args(0).toCharArray converts a string to an array
if you are sure you want only the first char, try args(0).head or more safely: args(0).headOption

Related

Scala passing varargs to another function that takes varargs

Why varargs can't be passed as another varargs without :_* ?
object Main {
def main(s: Array[String]): Unit = {
def someFunction(varars: String*) = {
someOtherFunction(varars) // Compilation ERRRO
someOtherFunction(varars:_*) // Works, but why ?
}
def someOtherFunction(someOtherVarars: String*): Unit = {
}
}
}
It's because varars is a single argument - an array of strings (note, that I'm not writing Array[String], because it is not the java Array, more details here), whereas by looking at the signature def someOtherFunction(someOtherVarars: String*): Unit, we can tell, that someOtherFunction takes multiple arguments of type String each. You cannot simply pass an array as the parameter to someOtherFunction, you need to "unfold" it first.
In other words an argument can be passed to someOtherFunction it has to be marked as a sequence argument. It would not make much sense to be able to pass varargs and varargs(1) to the single function. It's described in SLS ยง4.6.2.
"varargs"parameter means it can take any number of strings as an argument(i.e., a varargs field).
def someFunction(varars: String*): Seq[String] = {
varars }
if you define the above method and check for type of "varars" it has now become Seq[String] when you are using it. But when you pass it to another method which is expecting variableArgs type. It mismatch as it has become Seq[String] which should be converted to variable arguments using (someOtherVarars: _*).
_* operator tells the compiler to pass each element of the sequence as a separate argument, instead of passing it as a single argument.

Understanding Scala Syntax

I have code below and I wanted to know what does Seq[String] = List() mean?
Does it mean it takes sequence of strings and converts it into List()?
def somefuncname(input: Seq[String] = List()): Unit = {
//Some Code
}
First try to understand the below function signature.
def somefuncname(input: Seq[String]): Unit = {
//Some Code
}
The above code is a function declaration. Its a function which takes 1 argument called input which is of type Seq[String]. That means it takes sequence or list of strings as input and returns nothing Unit
Now, what does = mean?
= after the input argument of the function means default value for the function argument. If you are not interested in passing a custom "sequence of strings" then you can rely on the default argument of already passed.
Now, what does List() mean?
List() returns sequence of 0 elements or empty sequence. That means function is taking empty elements as default argument
alternatively you can also pass Seq() as default argument. It also means empty sequence
def somefuncname(input: Seq[String] = Seq()): Unit = {
//Some Code
}
Now to use the function in any of the following ways
somefuncname() // Now input is empty sequence of strings
somefuncname(Seq("apple", "cat"))
somefuncname(List("apple", "cat"))
input is of type Seq[String] and it has a default value of empty list (List()).
Having a default value means so that if you call the function without passing an argument it would get the default value

How to make spark udf accept a list with different data types?

My underlying function is defined like this:
def rowToSHA1(s: Seq[Any]): String = {
//return sha1 of sequence
}
}
Here is the definition of my udf:
val toSha = udf[String, Seq[Any]](rowToSHA1)
df.withColumn("shavalue",(toSha(array($"id",$"name",$"description",$"accepted")))
It works when i pass only a list of string as parameter but i get an error when there is a boolean.
org.apache.spark.sql.AnalysisException: cannot resolve 'array(`id`, `name`,
`description`, `accepted`)' due to data type mismatch: input to function
array should all be the same type, but it's [string, string, string,
boolean];;
I'm exploring the use of a generic function, is it a good idea?
FIX: converted my column to string before applying the function
df.withColumn("shavalue",(toSha(array($"id",$"name",$"description",$"accepted".cast("string)))
The best solution I know for this kind of situation is just convert everything to String, When you read/create the DataFrame make sure everything is String or convert it at some point. Later you can convert if back to any other type.

what input do scala case classes accept?

The code below seems to work fine. But my question is that why the function is defined to take Strings as input but on the bottom, it has accepted some input integers?
case class
TempData(year:Int, month:String, Prec:Double, Maxtemp:Int, Meantemp:Int, Mintemp:Int)
def parseLine(line:String):TempData = {
val p = line.split(",")
TempData(p(1).toInt, p(3).toString, p(5).toDouble, p(6).toInt, p(8).toInt, p(10).toInt)
}
//> parseLine: (line: String)Tests.TempData
parseLine("Verizon, 2017, Alpha, October, gentlemen, 10.3, 5, Dallas, 67, schools, 42")
//> res0: Tests.TempData = TempData(2017, October, 10.3, 5, 67, 42)
The defined function parseLine(line: String) takes String type arguments, and you have passed it correctly. The confusion is that you are considering the numbers present in the string as integers(Int) which is incorrect. The numbers present in the string are of type String only because you have enclosed them in quotes. You can also reason out for using toInt for converting the the numbers from String to Int type.
Your function takes one single String as an argument..
def parseLine(line: String): TempData
And one single String is exactly what is passed to it:
scala> "Verizon,2017,Alpha,October,gentlemen,10.3,5,Dallas,67,schools,42"
res0: String = Verizon,2017,Alpha,October,gentlemen,10.3,5,Dallas,67,schools,42
The numbers are just plain text and are a part of that String, there are no integers involved. It's the body of your function that splits the String and extracts Ints from it.
edit: regarding the title of your post: all of that has nothing to do with your TempData case class. It seems that you are confusing the call of the case class constructor with the call to parseLine.

scala variable arguments :_*

could someone bring more shed on following piece of scala code which is not fully clear to me? I have following function defined
def ids(ids: String*) = {
_builder.ids(ids: _*)
this
}
Then I am trying to pass variable argument list to this function as follows:
def searchIds(kind: KindOfThing, adIds:String*) = {
...
ids(adIds)
}
Firstly, ids(adIds) piece doesn't work which is a bit odd at first as error message says: Type mismatch, expected: String, actual: Seq[String]. This means that variable arguments lists are not typed as collections or sequences.
In order to fix this use the trick ids(adIds: _*).
I am not 100% sure how :_* works, could someone put some shed on it?
If I remember correctly : means that operation is applied to right argument instead to left, _ means "apply" to passed element, ...
I checked String and Sequence scaladoc but wasn't able to find :_* method.
Could someone explain this?
Thx
You should look at your method definitions:
def ids(ids: String*)
Here you're saying that this method takes a variable number of strings, eg:
def ids(id1: String, id2: String, id3: String, ...)
Then the second method:
def searchIds(kind: KindOfThing, adIds:String*)
This also takes a variable number of string, which are packaged into a Seq[String], so adIds is actually a Seq, but your first method ids doesn't take a Seq, it takes N strings, that's why ids(adIds: _*) works.
: _* this is called the splat operator, what that's doing is splatting the Seq into N strings.