Java code
package lambda_cache_example_java;
interface Semigroup1<A> {
public A append(A a1, A a2);
}
interface Semigroup2<A> {
public A append(A a1, A a2);
public interface Foo{}
public class Bar{}
}
class Main {
static Semigroup1<Integer> intSemigroup1() {
return (a1, a2) -> a1 + a2;
}
static Semigroup2<Integer> intSemigroup2() {
return (a1, a2) -> a1 + a2;
}
public static void main(String[] args) {
Semigroup1<Integer> x1 = intSemigroup1();
Semigroup1<Integer> x2 = intSemigroup1();
System.out.println(x1);
System.out.println(x2);
System.out.println(x1 == x2); // same instance
Semigroup2<Integer> y1 = intSemigroup2();
Semigroup2<Integer> y2 = intSemigroup2();
System.out.println(y1);
System.out.println(y2);
System.out.println(y1 == y2); // same instance as well
}
}
Scala code (version 2.12.0)
package lambda_cache_example_scala
trait Semigroup1[A] {
def append(a1: A, a2: A): A
}
trait Semigroup2[A] {
def append(a1: A, a2: A): A
trait Foo
}
object Main {
def intSemigroup1(): Semigroup1[Int] =
(a1, a2) => a1 + a2
def intSemigroup2(): Semigroup2[Int] =
(a1, a2) => a1 + a2
def main(args: Array[String]): Unit = {
val x1 = intSemigroup1()
val x2 = intSemigroup1()
println(x1)
println(x2)
println(x1 eq x2) // same instance
val y1 = intSemigroup2()
val y2 = intSemigroup2()
println(y1)
println(y2)
println(y1 eq y2) // not same
}
}
result
$ sbt "runMain lambda_cache_example_java.Main" "runMain lambda_cache_example_scala.Main"
[info] Running lambda_cache_example_java.Main
lambda_cache_example_java.Main$$Lambda$9/1908283686@44939bb7
lambda_cache_example_java.Main$$Lambda$9/1908283686@44939bb7
true
lambda_cache_example_java.Main$$Lambda$10/2119574930@7f206457
lambda_cache_example_java.Main$$Lambda$10/2119574930@7f206457
true
[success] Total time: 0 s, completed 2016/11/24 15:09:56
[info] Running lambda_cache_example_scala.Main
lambda_cache_example_scala.Main$$$Lambda$11/2085010450@7b408c6e
lambda_cache_example_scala.Main$$$Lambda$11/2085010450@7b408c6e
true
lambda_cache_example_scala.Main$$anonfun$intSemigroup2$2@c5329e5
lambda_cache_example_scala.Main$$anonfun$intSemigroup2$2@752d3cd9
false
[success] Total time: 0 s, completed 2016/11/24 15:09:57
When considering Sala vs. Java, you should know some of Java’s notable drawbacks. Java consumes more memory and is significantly slower than natively compiled languages like C or C++ Java’s default GUI applications written in Java and the Swing toolkit look quite different from native applications What Is Scala?
Scala has a “lazy evaluation” feature that allows the programmer to defer time-consuming computations until they’re needed, using the keyword “lazy.” Java has no such option.
But, in any case "Lambda Expressions" would probably be more clear in context. You should generally assume Java 8's approach is at least as efficient and possibly more efficient than the anonymous class approach.
Scala is a general-purpose, high-level, multi-paradigm programming language. It is a pure object-oriented programming language which also provides the support to the functional programming approach. There is no concept of primitive data as everything is an object in Scala.
Scala has path-dependent types. Although not obvious from your example, one could construct nested traits where the trait Foo
inside of one for instance of Semigroup2
is not at all compatible with the the Foo
from another instance of Semigroup2
. This post and this answer seem like good explanations of path dependent types.
This means that an instance of Semigroup2
is defined also by its inner trait, so a closure must be made when referencing one of its methods. Since that closure is re-made on the fly every time we try to reference that method, it isn't surprising the anonymous functions are different.
In Java, this is not the case. Semigroup2<A>.Foo
is a type (unlike in Scala where you need an instance of Semigroup[A]
to identify a type Foo
).
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