scalaflavor4j
DESCRIPTION
ScalaFlavor4J provides you Scala flavored useful API in Java. https://github.com/m3dev/scalaflavor4jTRANSCRIPT
ScalaFlavor4J- Scala flavored API in Java -
Kazuhiro Sera @seratch
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.
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
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”); // -> 3final int len = getLength._(“foo”); // -> 3
Option
// val opt = Option(“something”)
Option<String> opt = Option._(“something”);opt.isDefined(); // -> trueopt.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
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}
Seq
// val seq = Seq(1,2,3,4,5)
Seq<Integer> seq = Seq._(1,2,3,4,5)
import java.util.*;List<Integer> javaList = Arrays.asList(1,2,3,4,5);Seq<Integer> seq = Seq._(javaList);javaList = seq.toList();
#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
#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
#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>
#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>
#foreach(VoidF1)
// Seq(1,2,3) foreach { i => println(i) }
Seq<Integer> values = Seq._(1,2,3).foreach( new VoidF1<Integer>() { public void _(Integer i) { System.out.println(i); } }); // -> Displayed “1” “2” “3”
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
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
Range
// val range: Seq[Int] = 1 to 10// val range: Seq[Long] = 1L to 10LSeq<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 { ... }
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 availablemap.filter(new PredicateF1<Tuple2<Integer,String>>() {...});map.map(new F1<Tuple2<Integer,String>>() {...});
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
ExceptionControl
// import scala.util.control.Exception._// val result = catching(classOf[Exception]) withApply {// (t: Throwable) => “ng”;// } apply { “ok” }
import static com.m3.scalaflavor4j.ExceptionControl.*;String result = catching(Exception.class) .withApply(new F1<Throwable>() { public String _(Throwable t) { return “ng”; } }) .apply(new F0<String>() { public String _() { return “ok”; } });
Example(catching)
String result;try { result = “ok”;} catch (AException ae) { result = “ng”; } catch (BException be) { result = “ng”; }↓String result = catching(AException.class, BException.class) .withApply(new F1<Throwable>() { public String _(Throwable t) { return “ng”; } }) .apply(new F0<String>() { public String _() { return “ok”; } });
andThen(You)
• More information -> https://github.com/m3dev/scalaflavor4j
• Feature requests welcome
• Pull requests welcome
• Let’s enjoy Java with ScalaFlavor4J!