Using Type parameter in Scala Functions - scala

I'm trying to implement the Boolean Type in Scala, and i found an example using this signature :
abstract class Boolean {
def ifThenElse[T](t : => T , e : => T) : T
... }
My questions is :
When we should use the type Parameter after the function name like this funcName[T].
What does t : => T mean ?
Thank you

As for the first question:
1.When we should use the type Parameter after the function name like this funcName[T]
if you want this function can be used by different type, it's appreciate that put the generic type after function name as funcName[T]. For example, you have a function like this
def myFunction[T](param1: T){/*process*/}
you want to pass the parameter param1 and param2 to myFunction. These two parameters are defined as following
val param1: Int = 10
val param2: String = "test"
Though param1 and param2 have different types, you can call the function myFunction(param1) and also myFunction(param2)
Then, let's talk about the second question
2.What does t : => T mean ?
It's a by-name parameter. what's it? The following gives you more details:
t: => T has the same meaning as t: () => T, instead of inputing the words () => T, you can choose => T as for t
Another example: if you want to has an assertion, you may define the function like this:
def myAssert(predicate: () => Boolean) =
if(!predicate()) throw new AssertionError
then you can use it as following
myAssert(() => 5 > 3)
The usage is so ugly, is it? You may want to use it like this
myAssert(5 > 3)
at this time, the by-name parameter will be on the stage. Just define your function by the help of by-name parameter
def myAssert(predicate: => Boolean) = //leave out '()'
if(!predicate) throw new AssertionError //leave out '()'
then, you can use myAssert as above
myAssert(5 > 3)
Notes: A by-name type, in which the empty parameter list, (), is left out, is only allowed for parameters. There is no such thing as a by-name variable or a by-name field.
Good luck with you.

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).

Why _ (underscore) of type Unit and () treated differently?

I have a method which returns Future[Unit], so when I call whenReady
These two options work: whenReady(doItAsync())(_ => {}) and whenReady(doItAsync()) { _ => }
but this doesn't: whenReady(doItAsync())(() => {})
Are not _ of type Unit and empty params list equivalent in this case?
Although type Unit is similar to void from other languages it is not exactly the same.
This particular trouble comes from a limitation in Java (and thus Scala) generics implementation: they are implemented using type erasure. Particularly it means that generic method can't change the number of arguments. Now what happens when type parameter is Unit? We still must have the same number of arguments and also can't magically change return type to return nothing (void) because this will be a different signature. So the answer is to use some fake type with only fakes values: scala.runtime.BoxedUnit. And thus Unit might represent actual parameter that you don't need but has to be there. And so type signature () => {} doesn't match that because it takes no parameters.
Note also that in Java itself there is the same issue and thus there is a similar thing called java.lang.Void
Update:
To make the point more clear consider following generic vs. non-generic code:
def foo(f: () => String) = println(f())
def fooGeneric[T](arg: T, f: (T) => String) = println(f(arg))
foo(() => "Non-generic")
fooGeneric[Unit]((), (_) => "generic")
Note that also logically fooGeneric[Unit] is the same as foo, you still have to pass first argument and pass function that accept an (useless) argument as the second parameter.
Are not _ of type Unit and empty params list equivalent in this case?
No. _ => {} defines a function with single parameter (which happens in this context to have type Unit), () => {} defines a function with no parameters. Their types are Unit => Unit and () => Unit, or without syntactic sugar Function1[Unit, Unit] and Function0[Unit]. These types aren't actually related: neither of them is a subtype of the other.
You can write a single-argument anonymous function taking Unit with () using pattern-matching: { case () => ... }. But there is no point to doing that.

Scala :Returning a Function with variable argument from another function

My requirement is to return a function from another function in scala which takes variable argument i.e while executing the returned function , i can pass multiple argument at runtime.
My code looks like :
object VarArgTest {
def getFunction(): (Map[String, String],Map[String, Any]*) => Any={
(arg:Map[String,String], arg2:Map[String,Any]*) => "random"//this gives compilation error
}
}
In code , i want to return a function which take , Map[String,String] as one argument ,while the other Map[String,Any] should be optional to it.
But i get compilation error in return statement as follow:
type mismatch; found : (Map[String,String], Map[String,Any]) required: (Map[String,String], Map[String,Any]*) ⇒ Any
Can anyone help , what have i missed here?
Note: My requirement is that returned function can take either one argument (Map[String,String]) or it can take two arguments max (Map[String,String], Map[String,Any])
Thanks
It's impossible to use varargs in anonymous function.
You can get your piece of code working by making the returned function nested instead of anonymous like this:
object VarArgTest {
def getFunction(): (Map[String, String],Map[String, Any]*) => Any = {
def nestedFunction(arg:Map[String,String], arg2:Map[String,Any]*) = "random"
nestedFunction
}
}
However since you don't need multiple instances of Map[String, Any] but either none or one, you would be better off using Option[Map[String, Any]], providing None when it is not needed.

Writing a function that returns => T

I'm trying to write a simple converter that turns a java.util.Function into a scala.Function1:
def toScalaProducer[T](f: JavaFunction0[T]) : => T = => f()
Here is another variant that works well:
def toScalaFunction[T](f: JavaFunction0[T]) : () => T =
() => f.apply()
The problem is that I want to pass the converted function into an existing Scala API, but that API only accepts arguments of type => T, not of type () => T.
Is there a way to write the toScalaProducer function?
() => T is the type for a function that takes no arguments and returns something of type T
=> T is the type for a value T that is lazily evaluated. For instance:
def myFunc(t: => Int): Unit = {
// Do something with t
}
myFunc(reallyExpensiveFunctionProducingAnInt())
Here, reallyExpensiveFunctionProducingAnInt could take a long time to run, but will only be executed if the value t is used in myFunc. If you just use type Int instead of => Int it will have been called before myFunc is entered.
Have a look here for more information: Scala's lazy arguments: How do they work?
So if your toScalaProducer function simply executed the Java function and had a return value of T, it should work fine with the API. It will only be executed when needed, so in many ways will behave like passing a function.

How to read a chain of Scala function parameters

I am trying to read the parameter-list of the following 2 functions:
1. def foo(action: => String => String) = "bar"
2. def foo(action: => () => String => String) = "bar"
A function named "foo" which receives a function named "action" which receives/returns ???
A function named "foo" which receives a function named "action" which returns a function which returns ???
action is a passed-by-name function that takes a String and returns a String.
action is a passed-by-name function that takes nothing to return a function that takes a String and returns a String
Now you might ask, "Well, what does it mean for a parameter to be passed-by-name?" Alright... that's a whole different can of worms. Basically, a passed by name parameter is only evaluated when it's used in the function, and every time that it's used in the function. What this allows for is something like short-circuiting, as follows
def orOperator(left: Boolean, right: => Boolean) : Boolean = if (left) true else right
In this case, the operator will short-circuit (and terminate without computing/evaluating right) if it finds left to be true.
So... what you have with these parameters is something similar. They are functions that do not evaluate—for some reason—unless/until they are named in the function body. I don't understand the motivation for that, but... that's how it is. I hope that helps.