In this Java class:
import java.util.function.*;
public class T {
public String func(String a) {
System.out.println("There we go: " + a);
return a;
}
public static void main(String... args) {
final Supplier<T> c = T::new;
final BiFunction<T, String, String> f = T::func;
final T t = c.get();
final String v = f.apply(t, "something");
System.out.println(v);
}
}
I can get a method reference to the constructor of T
and to the instance method func
.
Is there a way to do the same in scala, i.e. to get
val c: () => T = ??? // default constructor of T as function
val f: (T, String) => String = ??? // instance method func of T as function
without wrapping them like that:
val c: () => T = () => new T
val f: (T, String) => String = (t, arg) => t.func(arg)
i.e. is there a way which is as elegant as the Java 8 way to get constructor and instance method references to obtain scala functions for these things?
First, let's have a look at a literal translation of the Java code to Scala:
class T {
def func(a:String) : String = {
println(s"There we go: $a")
a
}
}
object T {
def main(args: Array[String]) = {
val supplier = () => new T
val f = (t:T) => t.func _
val t = supplier()
val v = f(t)("something")
println(v)
}
}
In Scala, functions are first class citizens, hence there's no need to have particular constructions for "things that generate", like the Java Supplier
, as it's modeled as a function: f: () => T
(same thing goes for its counterpart, the Consumer
as f: T => ()
)
We just said that functions are first class citizens, so let's see a version of the above using this paradigm:
object Tfunc {
// let's remove the println side-effect from a function.
val func: String => String = a => s"There we go: $a"
def main(args: Array[String]) = {
println(func("something"))
}
}
In Scala, there's no counterpart to obtain a constructor reference, but if the aim is to use a functional approach, Scala object
s offer a simple construct to hold functions and do not require to be instantiated.
Exactly the way you do in java 8, you can't. For a class constructor I think there's no way to do that, except the way you did.
For functions you can use parameters placeholders which are "cleaner" in my opinion.
var t = new T()
var func = t.func _
func("a")
If you use a case class
then you can use the apply
method.
case class C(a: String)
var d = C.apply _
d("c")
You can use the apply
function for normal classes too, but you have to implement it yourself. For case classes they are implemented automatically.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With