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.
Related
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).
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.
Referring to following question in SO, what is the usefulness of passing Unit to a function instead of () or vice versa?
Functions without arguments, with unit as argument in scala
From what I can tell you would like to know what is the difference between these two method definitions, and why one would use Unit over () in the function parameter.
def func1(f:Unit=>String) = {
println(f)
}
def func2(f:()=>String) = {
println(f)
}
the difference can be highlighted by looking at the output of this code:
func1(Unit => "hello")
func2(() => "hello" )
you may be surprised to see this output:
<function1>
<function0>
Unit=>String is actually a function with 1 parameter. While ()=>String is a function with 0 parameters.
In Scala () could mean two things
it could be used for Unit e.g. val x:Unit = ()
it can be use to represent no parameters.
In func2, it is a function with no parameters.
"Unit" in func1 is actually the abstract class in the scala package (of which there is only one value "Unit" or "()"). So when the function Unit => String was defined, what we defined was a function that takes a parameter of type Unit as a parameter, and returns a value. Not a Function that takes no parameters.
A final tweak to the code to highlight the difference:
def func1(f:Unit=>String) = {
println(f(Unit))
}
def func2(f:()=>String) = {
println(f())
//println(f(Unit)) - does not compile
}
func1(Unit => "hello")
func2(() => "hello" )
Will output hello twice.
I'd suggest that func2 or () is generally what people want, and not func1 or "Unit"
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.
I think I still have not fully understood what type () represent during function definition. So I can't come up concrete example of each case: () => Int; Unit=> Int.
Can someone give me an easy example of function literal with type () => Int and type Unit=>Int respectively? After that, I think I can learn what () is exactly is.
Thanks
*EDIT: * destin says they are same. But the following test seems to indicate otherwise: () can't be used in place expecting Unit.
scala> def inCase[A] ( b :Boolean, ifTrue : Unit => A, ifFalse : Unit => A ) : A =
| b match {
| case True => ifTrue()
| case _ => ifFalse()
| }
inCase: [A](b: Boolean, ifTrue: Unit => A, ifFalse: Unit => A)A
scala> inCase( True, () => 1, () => -1 )
<console>:11: error: type mismatch;
found : () => Int
required: Unit => ?
inCase( True, () => 1, () => -1 )
() in a function type is not a type at all, nor is it a value. () => is simply syntax to indicate a function that takes zero arguments. See the BNF notation in section 3.2.9 of the Scala specification.
When you see (Type1, Type2, Type3) => Type4, the () surrounds all of the argument types that the function takes. (Type1, Type2, Type3) is not a tuple type here -- the parentheses are just syntax. So when you see () => Type4, you have an argument list that takes zero parameters. Single argument functions are special, in that you can omit the parentheses.
Functions with no arguments, specified without the (), simply => Type4 are by-name parameters (which look like values, but are implemented as functions that get called implicitly when you try to evaluate their value.) They're defined in section 4.6.1 of the spec.
Parentheses can mean a bunch of other things in other contexts.
Parentheses in a function type declaration anywhere other than right before the => indicate a tuple type, and these can't be empty. (Section 3.2.5)
Empty parentheses () are the return value of functions whose return type is Unit. (Section 12.2.3) This actually becomes a real value in certain contexts, for example println(println("foo")) will print
foo <--- the argument to the inner println
() <--- the argument to the outer println
Parentheses are also syntax for function arguments when you make a function call, something that you're probably already aware of. These can be empty. They're defined in section 6.6 of the spec.
Parentheses are also syntax for function arguments when you define a method using def. These are described in section 4.6 of the spec.
Parentheses are also the syntax for creating tuple values (Section 6.9). If they're not empty, you get a TupleN where N is the number of values inside of the parentheses. If they are empty, the type of this expression is Unit. (Sections 6.9, 12.2.3)
I changed your example, to have both notations (and to use the more popular Boolean):
def inCase[A] (b:Boolean, ifTrue: ()=> A, ifFalse: Unit => A): A = b match {
case true => ifTrue ()
case _ => ifFalse ()
}
inCase (true, () => 1, (Unit) => -1)
Then I have to use the same notation on the calling site.
() is the only instance of the type Unit.
So () => Int as signature of a partial function means: takes the Unit object, does something and gives an Int.
Unit => Int means: takes any Unit object, does something and gives an Int.
Edit
"Scala’s Unit type roughly corresponds to void in Java; it is used whenever a function does not return an interesting result. In fact, because Scala is an expressionoriented language, every function returns some result. If no explicit return expression is given, the value (), which is pronounced “unit”, is assumed. This value is
of type Unit. Unit-returning functions are also called procedures. Here’s a more
“expression-oriented” formulation of the swap function in the first implementation
of quicksort, which makes this explicit:
def swap(i: Int, j: Int): Unit = {
val t = xs(i); xs(i) = xs(j); xs(j) = t
()
}
The result value of this function is simply its last expression – a return keyword is
not necessary. Note that functions returning an explicit value always need an “=”
before their body or defining expression."
Source: Programming in Scala - Martin Odersky (Page 14)