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

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

Related

Function type, function value and function object in scala

I am new in scala and reading Programming in scala. I find the terms function type, function value and function objects in various pages in the book. For instance:
For instance, where other languages might have objects and functions as two different concepts, in Scala a function value is an object. Function types are classes that can be inherited by subclasses.
Can you please explain function type, function value and function objects and the differences between them? Also what does the above quote mean?
Let me start with non-function type, value and object.
scala> val foo:String = "bar"
foo: String = bar
Here, type is String, value is bar and object instance is foo. Note that, value is essentially an object of type String. For example, (just to get the idea between value and object):
scala> val foo_copy = foo
foo_copy: String = bar
Here, object foo is assigned to foo_copy. Since foo is object in above case, it is a value for object foo_copy.
Now, let me come to function example:
In scala, function is a value and you can assign it to variable.
scala> val foo: (String, String) => String = (a:String, b:String) => a + b
foo: (String, String) => String = <function2>
Here, function type is (String, String) => String (take 2 string parameter and return value of type string) and expression (a:String, b:String) => a + b is a function literal which is compiled into a class and then it is instantiated at runtime as function value. In code above, <function2> is a function value which is essentially an object. Note, don't confuse function value with value that you get from this function invocation.
Finally, foo is a function object of type (String, String) => String and here as well both function object and function value are same. Note that, function value is instance of some class that extends to FunctionN traits. That means:
type: (String, String) => String = Function2[String, String] //2 - number of parameter
Therefore, a class can extends to a function type. class A extends ((String, String) => String) is actually translated to class A extends Function2[String, String] by Scala. Furthermore, a function type can be used as parameter type in function and these functions are higher ordered functions.
In Scala functions are no different from "ordinary" values.
val inc: Int => Int = x => x + 1
is the same concept as
val s: String = "hello world"
For any val x: T = e, x is the name of the value whose type is T, and x is the result of evaluating e.
inc is a value/object just like s is a value/object. I think value and object are essentially the same thing here.
val f: Int => String = i.toString
f is a value that holds a reference to a function, I guess it could be called a function value.
Int => String is a function type, a type that corresponds to a function from integer to string.
f is also an object (I've never read function object), you can for instance call f.toString and f.hashCode, like you would on any other object.
Practically, a Scala programmer only needs to know the following three rules to use functions and function values properly:
Methods defined by def and function literals defined by => are functions. It is defined in page 143, Chapter 8 in the book of Programming in Scala, 4th edition.
Function values are objects that can be passed around as any values. Function literals and partially applied functions are function values.
You can leave off the underscore of a partially applied function if a function value is required at a point in the code. For example: someNumber.foreach(println)
In the Programming in Scala book, object and value are used interchangeably. Therefore, function value and function object are the same thing.

Difference between underscore (_) and triple question marks (???) in scala

I am in the middle of writing some code so I wanted to leave a method unimplemented which I am calling but that pathflow is not hitting based on input I am providing. The method looks like this
object HbaseStore {
def get() = _
}
But the above code threw an exception
HbaseStore.scala:24: error: unbound placeholder parameter
[INFO] def get() = _
But when I replaced _ with ??? code executed successfully. I am just curious to know what is the difference between these two. As far as I know, _ provides default values so I assumed it would define an empty function here and return Nothing.
_ is a placeholder syntax, which is used to bind values. Placeholder syntax is used in many scenarios, for example:
In case of list:
val x = List(1,2,3,4,5)
//To print each value we can do:
x.map(res => println(res))
//Now, we can use placeholder syntax to bind res value.
x.map(println(_))
Pattern matching:
val x = "some value"
x match {
case x:String => //convert to lowercase and print.
case res#_ => //here, type doesnot matter I just want to get that value and print as it is. println(res)
So, basically, you use placeholder syntax if you want to have the value without knowing its type.
On the other hand, ??? is assigned to method or variables as value in case you don't want to provide implementation.
e.g. def doSomething() => ???
here, doSomething() method is not implemented, and you need to provide or override implementation later. Note, that you cannot use variables/methods without implementations and you will get exception in case you try to invoke it. e.g. doSomething() will fail in above case.
If you want to use _ as a default value you need to provide a type of this value. For example var x: Any = _ will be initialized with null but var x: Int = _ will be initialized with 0.
Regarding ??? :
You can click on the definition of ??? in IDE:
def ??? : Nothing = throw new NotImplementedError
Since Nothing is a subtype of any given type, it works.

Using Type parameter in Scala Functions

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.

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.