2. What’s this?
• github.com/m3dev/scalaflavor4j
• A pure Java library
• NOT a wrapper of scala-library.jar
• Function, Seq, Range, Option, Map, ParSeq...
• Already used by some apps at M3, Inc.
3. Motivation
• “For fun”
• To get along with legacy Java systems
• Help co-workers ease into Scala (showing
them that Scala has a lot of useful APIs)
• Might be useful as a Scala educational tool
for Java programmers
4. Function
// val getLength = (str: String) => if (str == null) 0 else str.length
// val len = getLength(“foo”)
import com.m3.scalaflavor4j.*;
F1<String,Integer> getLength = new F1<String,Integer>() {
public Integer _(String str) { // apply method definition
return str == null ? 0 : str.length();
}
};
final int len = getLength.apply(“foo”); // -> 3
final int len = getLength._(“foo”); // -> 3
5. Option
// val opt = Option(“something”)
Option<String> opt = Option._(“something”);
opt.isDefined(); // -> true
opt.getOrNull(); // -> “something”
Option<String> none = Option._(null);
none.getOrElse(“”); // -> “”
opt.map(new F1<String,String>() { ... }) // apply F1 if Some
.getOrElse(new F0<String>() { ... }); // apply F0 if None
6. Example(Option)
class UserService {
public User findById(String id) { return DB.findUserById(id); }
}
User user = userService.findById(“123”)); // user might be null
↓
class UserService {
public Option<User> findById(String id) {
return Option._(DB.findUserById(id));
} // Explicitly state that User might be null
}
8. #map(F1)
// val values = Seq(1,2,3,4,5) map { i => i *i }
Seq<Integer> values = Seq._(1,2,3,4,5).map(
new F1<Integer, Integer>() {
public Integer _(Integer i) { return i * i; }
}
);
// -> 1,4,9,16,25
9. #flatMap(F1)
// val values = Seq(1,2,3) flatMap { i => 1 to i }
Seq<Integer> values = Seq._(1,2,3).flatMap(
new F1<Integer, CollectionLike<Integer>>() {
public Seq<Integer> _(Integer i) {
return SInt._(1).to(i);
}
}
);
// -> 1,1,2,1,2,3
// * CollectionLike accepts Seq and Option
10. #filter(F1)
// val values = Seq(1,2,3,4,5) filter { i => i > 1 }
Seq<Integer> values = Seq._(1,2,3,4,5).filter(
new PredicateF1<Integer>() {
public Boolean _(Integer i) { return i > 1; }
}
);
// -> 3,4,5
// * PredicatedF1<A> is just an alias of F1<A,Boolean>
11. #foldLeft(F2)
// val values = Seq(1,2,3,4,5).foldLeft(0){ (z,i) => z + i }
Seq<Integer> values = Seq._(1,2,3,4,5).foldLeft(
new FoldLeftF2<Integer,Integer>() {
public Integer _(Integer z, Integer i) { return z + i; }
}
);
// ->15
// * FoldLeft2<A,B> is just an alias of F2<A,B,A>
13. Example(Seq)
List<Integer> input = Arrays.asList(3,2,5,0,4,1);
List<Integer> result = new ArrayList<Integer>();
for ( Integer i : input ) {
if ( i != null && i > 2 ) { result.add(i * i); }
}
↓
Seq._(input).filter(new PredicateF1<Integer>() {
public Boolean _(Integer i) { return i != null && i >2; }
}).map(new F1<Integer, Integer>() {
public Integer _(Integer i) { return i * i; }
}).toList(); // No mutable state, Separation
14. ParSeq
// val values = (1 to 100).par.map { i => i *i }
Seq<Integer> values = SInt._(1).to(100).par().map(
new F1<Integer, Integer>() {
public Integer _(Integer i) {
System.out.println(Thread.currentThread.getId());
return i * i;
} // Using Fork/Join framework(Available on JDK6)
}
);
// -> 1,4,9,16,25
15. Range
// val range: Seq[Int] = 1 to 10
// val range: Seq[Long] = 1L to 10L
Seq<Integer> range = SInt._(1).to(10);
Seq<Long> range = SLong._(1).until(11);
for(int i=0; i<10; i++) { ... }
↓
SInt._(0).until(10).foreach { ... }
16. Map
// val map = Map(1 -> “foo”, 2 -> “bar”)
import java.util.*;
Map<Integer, String> javaMap = new HashMap<>();
SMap<Integer, String> map = SMap._(javaMap);
// map,flatMap,filter,foreach, etc. are available
map.filter(new PredicateF1<Tuple2<Integer,String>>() {...});
map.map(new F1<Tuple2<Integer,String>>() {...});
17. ConcurrentOps
// import scala.concurrent.ops._
// spawn { println(“On a different thread!”) }
new Thread(new Runnable() { public void run() {
System.out.println(“On a different thread!”);
}}).start();
↓
import static com.m3.scalaflavor4j.ConcurrentOps.*;
spawn(new VoidF0() { public void _() {
System.out.println(“On a different thread!”);
}}); // using Fork/Join