package org.enumerable.lambda.support.scala;
import clojure.lang.IFn;
import groovy.lang.Closure;
import org.enumerable.lambda.Fn1;
import org.enumerable.lambda.Lambda;
import org.enumerable.lambda.enumerable.Enumerable;
import org.enumerable.lambda.support.clojure.ClojureTest;
import org.enumerable.lambda.support.clojure.LambdaClojure;
import org.enumerable.lambda.support.groovy.GroovyTest;
import org.enumerable.lambda.support.groovy.LambdaGroovy;
import org.enumerable.lambda.support.javascript.JavaScriptTest;
import org.enumerable.lambda.support.javascript.LambdaJavaScript;
import org.enumerable.lambda.support.jruby.JRubyTest;
import org.enumerable.lambda.support.jruby.LambdaJRuby;
import org.jruby.RubyProc;
import org.junit.Test;
import scala.Function1;
import scala.Function2;
import scala.tools.nsc.Interpreter;
import scala.tools.nsc.Settings;
import sun.org.mozilla.javascript.internal.Function;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.PrintStream;
import java.util.List;
import static java.util.Arrays.asList;
import static org.enumerable.lambda.Parameters.*;
import static org.enumerable.lambda.support.scala.LambdaScala.*;
import static org.junit.Assert.*;
@SuppressWarnings({ "unchecked", "deprecation" })
public class ScalaTest {
static ScalaInterpreter scala = new ScalaInterpreter();
@Test
public void interactingWithScala() {
scala.bind("f", "Function1[Int, Int]", function(n, n * 2));
assertEquals(4, scala.eval("f(2);"));
scala.bind("f", "Function1[Boolean, Boolean]", function(b, !b));
assertTrue((Boolean) scala.eval("f(false);"));
scala.bind("f", "Function1[String, String]", function(s, s.toUpperCase()));
assertEquals("HELLO", scala.eval("f(\"hello\");"));
scala.bind("f", "Function[Any, Any]", function(obj, obj));
assertNull(scala.eval("f(null);"));
}
@Test
public void fullScalaFunctionTypesAreCreatedWithNoAbstractMethods() {
FunctionFn1<Integer, Integer> function = function(n, n * 2);
Function1<Integer, Integer> composed = (Function1<Integer, Integer>) function.compose(function);
assertEquals(8, (int) composed.apply(2));
}
@Test
public void convertFnToFunction() throws ScriptException {
Function1<String, String> f = toFunction(Lambda.λ(s, s.toUpperCase()));
scala.bind("f", "Function1[String, String]", f);
assertEquals("HELLO", scala.eval("f(\"hello\");"));
}
@Test
public void convertFunctionToFn() throws ScriptException {
Function1<String, String> f = (Function1<String, String>) scala.eval("(s: String) => s.toUpperCase");
assertEquals("HELLO", toFn1(f).call("hello"));
}
@Test
public void interactingWithEnumerableJava() throws Exception {
List<Integer> list = asList(1, 2, 3);
Fn1<Integer, Integer> block = toFn1((Function1<Integer, Integer>) scala.eval("(n: Int) => n * 2"));
assertEquals(asList(2, 4, 6), Enumerable.collect(list, block));
}
@Test
public void interactingWithClojure() throws Exception {
IFn star = (IFn) ClojureTest.getClojureEngine().eval("*");
Function2<Object, Object, Object> times = toFunction(LambdaClojure.toFn2(star));
assertEquals(6L, times.apply(2, 3));
scala.bind("timesClojure", "Function2[Any, Any, Any]", times);
assertEquals(120L, scala.eval("List(1, 2, 3, 4, 5).reduceLeft(timesClojure)"));
}
@Test
public void interactingWithJRuby() throws Exception {
RubyProc proc = (RubyProc) JRubyTest.getJRubyEngine().eval(":*.to_proc");
Function2<Object, Object, Object> times = toFunction(LambdaJRuby.toFn2(proc));
assertEquals(6L, times.apply(2, 3));
scala.bind("timesRuby", "Function2[Any, Any, Any]", times);
assertEquals(120L, scala.eval("List(1, 2, 3, 4, 5).reduceLeft(timesRuby)"));
}
@Test
public void interactingWithJavaScript() throws Exception {
ScriptEngine js = JavaScriptTest.getJavaScriptEngine();
Function f = (Function) js.eval("var f = function(n, m) { return n * m; }; f;");
Function2<Object, Object, Object> times = toFunction(LambdaJavaScript.toFn2(f));
assertEquals(6.0, times.apply(2, 3));
scala.bind("timesJS", "Function2[Any, Any, Any]", times);
assertEquals(120.0, scala.eval("List(1, 2, 3, 4, 5).reduceLeft(timesJS)"));
}
@Test
public void interactingWithGroovy() throws Exception {
ScriptEngine groovy = GroovyTest.getGroovyEngine();
Closure<?> closure = (Closure<?>) groovy.eval("{ n, m -> n * m }");
Function2<Object, Object, Object> times = toFunction(LambdaGroovy.toFn2(closure));
assertEquals(6, times.apply(2, 3));
scala.bind("timesGroovy", "Function2[Any, Any, Any]", times);
assertEquals(120, scala.eval("List(1, 2, 3, 4, 5).reduceLeft(timesGroovy)"));
}
@Test
public void enumerableJavaLambdasCanBeEmbeddedInScala() throws Exception {
// def toUpperCase() = {
// λ(s, s.toUpperCase)
// }
assertEquals("HELLO", EnumerableJavaScalaTest.toUpperCase().call("hello"));
}
public static class ScalaInterpreter {
static Interpreter interpreter;
static {
Settings settings = new Settings();
settings.bootclasspath().tryToSetFromPropertyValue("lib/scala-library-2.9.1.jar" + File.pathSeparator
+ "lib/scala-compiler-2.9.1.jar");
interpreter = new Interpreter(settings);
}
public void bind(String name, String scalaType, Object value) {
PrintStream realOut = System.out;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
System.setOut(new PrintStream(out));
interpreter.bind(name, scalaType, value);
} catch (RuntimeException e) {
realOut.println(out);
throw e;
} finally {
System.setOut(realOut);
}
}
public Object eval(String expression) {
PrintStream realOut = System.out;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
System.setOut(new PrintStream(out));
Object[] _result = new Object[1];
bind("_result", "Array[Any]", _result);
interpreter.interpret("_result(0) = " + expression);
return _result[0];
} catch (RuntimeException e) {
realOut.println(out);
throw e;
} finally {
System.setOut(realOut);
}
}
}
public static ScalaInterpreter getScalaInterpreter() {
return scala;
}
}