Understanding Scala Syntax - scala

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

Related

Passing a function as a parameter, why the => symbol is required in my scenerio?

case class User(id: Int)
def Transform(u: User): String = u.id.toString()
def Process[A](f: A => String): String = "hello"
val u = User(123)
println(Process(u => Transform(u))) // Scenerio#1 works fine
println(Process(Transform(u))) // error
println(Process[User](Transform(u))) // error
I'm a little confused as to why I need the => in Scenerio#1
I have a function Process that takes a function. The function requires:
a parameter of type A
return value of String.
Now I have a function named Transform that takes a parameter of type A (a User) and returns a string.
Why can't I pass in:
Process(Transform(u))
I am passing it a function that meets the requirements am I not? (I guess not but I don't understand!)
I guess I still don't understand what the following notation really means:
Process(u => Transform(u))
As you already noticed, Transform is of type User => String, therefore, you can just pass it as a parameter to Process:
val process1: String = Process(u => Transform(u))
val process2: String = Process(Transform)
val process3: String = Process[User](Transform)
All of the above are exactly the same, and outputs hello.
def Process[A](f: A => String) method in your code is expecting a function definition as argument whose input parameter type should A and return type should be String.
Case 1:
println(Process(u => Transform(u)))
You are passing function definition so it is working fine as per expectation.
Case 2:
println(Process(Transform(u))) // error
println(ProcessUser) // error
You are not passing function definition here as expected by Process function instead you are passing the function call Transform(u) which will return the value and pass as argument to Process function.
You can refer high order function in scala using this link (https://docs.scala-lang.org/tour/higher-order-functions.html).

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.

Trying to skip implicit parameter list

I'd like to call a function returned by a function with an implicit parameter, simply and elegantly. This doesn't work:
def resolveA(implicit a: A): String => String = { prefix =>
s"$prefix a=$a"
}
case class A(n: Int)
implicit val a = A(1)
println(resolveA("-->")) // won't compile
I've figured out what's going on: Scala sees the ("-->") and thinks it's an attempt to explicitly fill in the implicit parameter list. I want to pass that as the prefix argument, but Scala sees it as the a argument.
I've tried some alternatives, like putting an empty parameter list () before the implicit one, but so far I've always been stopped by the fact that Scala thinks the argument to the returned function is an attempt to fill in the implicit parameter list of resolveA.
What's a nice way to do what I'm trying to do here, even if it's not as nice as the syntax I tried above?
Another option would be to use the apply method of the String => String function returned by resolveA. This way the compiler won't confuse the parameter lists, and is a little shorter than writing implicltly[A].
scala> resolveA[A].apply("-->")
res3: String = --> a=A(1)

Why in Scala function defined without empty parentheses doesn't behave like function?

Consider the following 2 objects
object TestObj1 {
def testMethod = "Some text"
}
object TestObj2 {
def testMethod() = "Some text"
}
and if I call those methods directly, they do what I expect
scala> TestObj1.testMethod
res1: String = Some text
scala> TestObj2.testMethod
res2: String = Some text
But now if we define following function
def functionTakingFunction(callback: () => String) {
println("Call returns: " + callback())
}
and try to call it, the method defined without () is not accepted.
scala> functionTakingFunction(TestObj1.testMethod)
<console>:10: error: type mismatch;
found : String
required: () => String
functionTakingFunction(TestObj1.testMethod)
^
scala> functionTakingFunction(TestObj2.testMethod)
Call returns: Some text
I also noticed that you can't call the TestObj1.testMethod using parentheses, since it already is a String. But what is causing this behavior?
You are not passing the method, you're invoking it and then passing its result into the call.
If you want to pass the method, you first have to convert it into a function, and pass that:
functionTakingFunction(TestObj1.testMethod _)
Here the testMethod is converted into a partially applied function (said to be "tied").
The reason you have to do that is because TestObj1.testMethod does not evaluate to function0 (which is what need to be passed to functionTakingFunction), but to a String because of the way it is declared (without parentheses).
It works on TestObj2 because the testMethod is defined with parentheses and thus just typing TestObj2.testMethod does not invoke it.
functionTakingFunction(TestObj1.testFunction) is called as functionTakingFunction("Some text") - it is evaluated rather than passed
Here, you are not passing the function. What you are trying to do is evaluate TestObj1.testFunction and then pass that result to functionTakingFunction
But if you see the definition of functionTakingFunction, it says clearly
def functionTakingFunction(callback: () => String)
means this function expects a function with Return Type as Unit. But TestObj1.testFunction is having no return type.
The difference between Unit Return Type and No Return Type is:
No Return Type means this method will not return anything
Unit Return Type means this method will return something which is having no meaningful value.
Hope it helps you now. Happy coding and enjoy Scala.

When is a scala partial function not a partial function?

While creating a map of String to partial functions I ran into unexpected behavior. When I create a partial function as a map element it works fine. When I allocate to a val it invokes instead. Trying to invoke the check generates an error. Is this expected? Am I doing something dumb? Comment out the check() to see the invocation. I am using scala 2.7.7
def PartialFunctionProblem() = {
def dream()() = {
println("~Dream~");
new Exception().printStackTrace()
}
val map = scala.collection.mutable.HashMap[String,()=>Unit]()
map("dream") = dream() // partial function
map("dream")() // invokes as expected
val check = dream() // unexpected invocation
check() // error: check of type Unit does not take parameters
}
For convenience, Scala lets you omit empty parens when calling a method, but it's clever enough to see that the expected type in the first case is ()=>Unit, so it doesn't remove all the parens for you; instead, it converts the method into a function for you.
In the val check case, however, it looks just like a function call result getting assigned to a variable. In fact, all three of these do the exact same thing:
val check = dream
val check = dream()
val check = dream()()
If you want to turn the method into a function, you place _ after the method in place of the argument list(s). Thus,
val check = dream() _
will do what you want.
Well, the problem is that you got it all wrong. :-)
Here are some conceptual mistakes:
def dream()() = {
println("~Dream~");
new Exception().printStackTrace()
}
This is not a partial function. This is a curried method with two empty parameter lists which returns Unit.
val map = scala.collection.mutable.HashMap[String,()=>Unit]()
The type of the values in this map is not partial function, but function. Specifically, Function0[Unit]. A partial function would have type PartialFunction[T, R].
map("dream") = dream() // partial function
What happens here is that Scala converts the partially applied method into a function. This is not a simple assignment. Scala does the conversion because the type inferencer can guess the correct type.
val check = dream() // unexpected invocation
Here there's no expected type to help the type inferencer. However, empty parameter lists can be ommitted, so this is just a method call.