feat: update structure
This commit is contained in:
76
cs2030s/labs/Lab5/CS2030STest.java
Normal file
76
cs2030s/labs/Lab5/CS2030STest.java
Normal file
@@ -0,0 +1,76 @@
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import javax.tools.DiagnosticCollector;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class CS2030STest {
|
||||
|
||||
private static final String ANSI_RESET = "\u001B[0m";
|
||||
private static final String ANSI_RED = "\u001B[31m";
|
||||
private static final String ANSI_GREEN = "\u001B[32m";
|
||||
|
||||
public void expect(String test, Object output, Object expect) {
|
||||
System.out.print(test);
|
||||
if ((expect == null && output == null) || output.equals(expect)) {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
} else {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
System.out.println(" expected: " + expect);
|
||||
System.out.println(" got this: " + output);
|
||||
}
|
||||
}
|
||||
|
||||
public static String clean(String txt) {
|
||||
String res = "";
|
||||
for (int i=0; i<txt.length(); i++) {
|
||||
if (txt.charAt(i) != '\r' && txt.charAt(i) != '\n') {
|
||||
res += txt.charAt(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public void expectPrint(String test, Object expect, ByteArrayOutputStream baos, PrintStream old) {
|
||||
System.out.flush();
|
||||
System.setOut(old);
|
||||
expect(test, CS2030STest.clean(baos.toString()), expect);
|
||||
}
|
||||
|
||||
public void expectCompile(String test, String statement, boolean success) {
|
||||
System.out.print(test);
|
||||
|
||||
class JavaSourceFromString extends SimpleJavaFileObject {
|
||||
final String code;
|
||||
|
||||
JavaSourceFromString(String code) {
|
||||
super(URI.create("string:///TempClass.java"), Kind.SOURCE);
|
||||
this.code = "class TempClass {void foo(){" + code + ";}}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
boolean noError = ToolProvider
|
||||
.getSystemJavaCompiler()
|
||||
.getTask(null, null, new DiagnosticCollector<>(), null, null,
|
||||
List.of(new JavaSourceFromString(statement)))
|
||||
.call();
|
||||
|
||||
if (noError != success) {
|
||||
System.out.println(".. " + ANSI_RED + "failed" + ANSI_RESET);
|
||||
if (!success) {
|
||||
System.out.println(" expected compilation error but it compiles fine.");
|
||||
} else {
|
||||
System.out.println(" expected the statement to compile without errors but it does not.");
|
||||
}
|
||||
} else {
|
||||
System.out.println(".. " + ANSI_GREEN + "ok" + ANSI_RESET);
|
||||
}
|
||||
}
|
||||
}
|
||||
17
cs2030s/labs/Lab5/Lab5.h
Normal file
17
cs2030s/labs/Lab5/Lab5.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
mkdir cs2030s
|
||||
cd cs2030s
|
||||
mkdir fp
|
||||
cd ..
|
||||
|
||||
mv Action.java cs2030s/fp/Action.java
|
||||
mv Actionable.java cs2030s/fp/Actionable.java
|
||||
mv Actually.java cs2030s/fp/Actually.java
|
||||
mv Constant.java cs2030s/fp/Constant.java
|
||||
mv Immutator.java cs2030s/fp/Immutator.java
|
||||
mv Immutatorable.java cs2030s/fp/Immutatorable.java
|
||||
mv Transformer.java cs2030s/fp/Transformer.java
|
||||
|
||||
javac cs2030s/fp/*.java
|
||||
javac *.java
|
||||
222
cs2030s/labs/Lab5/Lab5.java
Normal file
222
cs2030s/labs/Lab5/Lab5.java
Normal file
@@ -0,0 +1,222 @@
|
||||
import cs2030s.fp.Action;
|
||||
import cs2030s.fp.Actually;
|
||||
import cs2030s.fp.Constant;
|
||||
import cs2030s.fp.Immutator;
|
||||
import cs2030s.fp.Transformer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
class Lab5 {
|
||||
|
||||
public static String getGrade(String module, String student, String assessment,
|
||||
Map<String, Map<String, Map<String, String>>> db) {
|
||||
Constant<Actually<Map<String, Map<String, Map<String, String>>>>> constantDb = () -> Actually.ok(db);
|
||||
|
||||
Constant<String> constantNoEntry = () -> "No such entry";
|
||||
|
||||
Immutator<Actually<Map<String, Map<String, String>>>, Map<String, Map<String, Map<String, String>>>> getModule = param -> Actually
|
||||
.ok(param.get(module));
|
||||
|
||||
Immutator<Actually<Map<String, String>>, Map<String, Map<String, String>>> getStudent = param -> Actually
|
||||
.ok(param.get(student));
|
||||
|
||||
Immutator<Actually<String>, Map<String, String>> getAssessment = param -> Actually
|
||||
.ok(param.get(assessment).toString());
|
||||
|
||||
return constantDb.init().next(getModule).next(getStudent).next(getAssessment).except(constantNoEntry);
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Create a scanner to read from standard input.
|
||||
Scanner sc = new Scanner(System.in);
|
||||
|
||||
// Read a single integer from the test file
|
||||
// and then run the appropriate test case
|
||||
switch (sc.nextInt()) {
|
||||
case 1:
|
||||
test1();
|
||||
break;
|
||||
case 2:
|
||||
test2();
|
||||
break;
|
||||
case 3:
|
||||
test3();
|
||||
break;
|
||||
case 4:
|
||||
test4();
|
||||
break;
|
||||
case 5:
|
||||
test5();
|
||||
break;
|
||||
case 6:
|
||||
test6();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void test1() {
|
||||
String none = null;
|
||||
|
||||
System.out.println(Actually.err(new ArithmeticException("Err")).equals(Actually.err(new Exception("Err"))));
|
||||
System.out.println(Actually.err(new ArithmeticException("Err")).equals(Actually.err(new Exception("Error"))));
|
||||
System.out.println(Actually.err(new ArithmeticException("Err")).equals(Actually.err(new Exception(none))));
|
||||
System.out.println(Actually.err(new ArithmeticException(none)).equals(Actually.err(new Exception(none))));
|
||||
System.out.println(Actually.err(new ArithmeticException("Err")).equals(Actually.ok("Err")));
|
||||
System.out.println(Actually.ok("Err").equals(Actually.ok("Err")));
|
||||
System.out.println(Actually.ok("Err").equals(Actually.err(new Exception("Error"))));
|
||||
System.out.println(Actually.ok("Err").equals("Err"));
|
||||
System.out.println(Actually.ok(null).equals(Actually.ok("Err")));
|
||||
System.out.println(Actually.ok(null).equals(Actually.ok(null)));
|
||||
System.out.println(Actually.ok(null).equals("Err"));
|
||||
System.out.println(Actually.ok(null).equals(null));
|
||||
}
|
||||
|
||||
public static void test2() {
|
||||
Constant<Integer> zero = new Constant<>() {
|
||||
public Integer init() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
Action<Integer> print = new Action<>() {
|
||||
public void call(Integer i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
Actually.<Number>ok(0).unwrap().toString();
|
||||
} catch (Exception e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
|
||||
Actually.<Integer>ok(9).finish(print);
|
||||
Actually.<Integer>err(new Exception("Err")).finish(print);
|
||||
System.out.println(Actually.<Number>ok(9).except(zero).toString());
|
||||
System.out.println(Actually.<Number>err(new ArithmeticException("div by 0")).except(zero).toString());
|
||||
System.out.println(Actually.<Number>err(new ArithmeticException("div by 0")).unless(4).toString());
|
||||
System.out.println(Actually.<Number>ok(0).unless(4).toString());
|
||||
}
|
||||
|
||||
public static void test3() {
|
||||
Immutator<Integer, Integer> inc = new Immutator<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p + 1;
|
||||
}
|
||||
};
|
||||
Immutator<Integer, Integer> inv = new Immutator<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return 1 / p;
|
||||
}
|
||||
};
|
||||
Immutator<Number, Integer> incNum = new Immutator<>() {
|
||||
public Number invoke(Integer p) {
|
||||
return p + 1;
|
||||
}
|
||||
};
|
||||
Immutator<Number, Integer> invNum = new Immutator<>() {
|
||||
public Number invoke(Integer p) {
|
||||
return 1 / p;
|
||||
}
|
||||
};
|
||||
|
||||
System.out.println(Actually.<Integer>ok(0).transform(inc).toString());
|
||||
System.out.println(Actually.<Integer>ok(0).transform(inv).toString());
|
||||
System.out.println(Actually.ok(0).transform(inc).toString());
|
||||
System.out.println(Actually.ok(0).transform(inv).toString());
|
||||
System.out.println(Actually.<Integer>ok(0).transform(incNum).toString());
|
||||
System.out.println(Actually.<Integer>ok(0).transform(invNum).toString());
|
||||
System.out.println(Actually.ok(0).transform(incNum).toString());
|
||||
System.out.println(Actually.ok(0).transform(invNum).toString());
|
||||
}
|
||||
|
||||
public static void test4() {
|
||||
Transformer<Integer, Integer> inc = new Transformer<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p + 1;
|
||||
}
|
||||
};
|
||||
Transformer<Integer, Integer> sqr = new Transformer<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p * p;
|
||||
}
|
||||
};
|
||||
|
||||
Transformer<Integer, Integer> sqrPlusOneA = sqr.before(inc);
|
||||
Transformer<Integer, Integer> sqrPlusOneB = inc.after(sqr);
|
||||
Transformer<Integer, Integer> plusOneSqrA = sqr.after(inc);
|
||||
Transformer<Integer, Integer> plusOneSqrB = inc.before(sqr);
|
||||
|
||||
System.out.println(sqrPlusOneA.invoke(2).toString());
|
||||
System.out.println(sqrPlusOneA.invoke(2).toString());
|
||||
System.out.println(plusOneSqrA.invoke(2).toString());
|
||||
System.out.println(plusOneSqrB.invoke(2).toString());
|
||||
}
|
||||
|
||||
public static void test5() {
|
||||
Immutator<Actually<Integer>, Integer> half = new Immutator<>() {
|
||||
public Actually<Integer> invoke(Integer p) {
|
||||
if (p % 2 == 0) {
|
||||
return Actually.<Integer>ok(p / 2);
|
||||
} else {
|
||||
return Actually.<Integer>err(new Exception("odd number"));
|
||||
}
|
||||
}
|
||||
};
|
||||
Immutator<Actually<Integer>, Integer> inc = new Immutator<>() {
|
||||
public Actually<Integer> invoke(Integer p) {
|
||||
return Actually.<Integer>ok(p + 1);
|
||||
}
|
||||
};
|
||||
Immutator<Actually<Integer>, Integer> make = new Immutator<>() {
|
||||
public Actually<Integer> invoke(Integer p) {
|
||||
return Actually.<Integer>ok(p);
|
||||
}
|
||||
};
|
||||
Constant<Integer> zero = new Constant<>() {
|
||||
public Integer init() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
System.out.println(make.invoke(0).next(inc).next(inc).next(half).toString());
|
||||
System.out.println(make.invoke(0).next(inc).next(half).next(inc).toString());
|
||||
System.out.println(make.invoke(0).next(inc).next(inc).next(half).except(zero).toString());
|
||||
System.out.println(make.invoke(0).next(inc).next(half).next(inc).except(zero).toString());
|
||||
}
|
||||
|
||||
public static void test6() {
|
||||
Map<String, Map<String, Map<String, String>>> nus = Map.of(
|
||||
"CS2030S", Map.of(
|
||||
"Steve", Map.of(
|
||||
"lab1", "A",
|
||||
"lab2", "A-",
|
||||
"lab3", "A+",
|
||||
"lab4", "B",
|
||||
"pe1", "C"),
|
||||
"Tony", Map.of(
|
||||
"lab1", "C",
|
||||
"lab2", "C",
|
||||
"lab3", "B-",
|
||||
"lab4", "B+",
|
||||
"pe1", "A")),
|
||||
"CS2040S", Map.of(
|
||||
"Steve", Map.of(
|
||||
"lab1", "A",
|
||||
"lab2", "A+",
|
||||
"lab3", "A+",
|
||||
"lab4", "A",
|
||||
"midterm", "A+")));
|
||||
|
||||
System.out.println(getGrade("CS2030S", "Steve", "lab1", nus));
|
||||
System.out.println(getGrade("CS2030S", "Steve", "lab2", nus));
|
||||
System.out.println(getGrade("CS2040S", "Steve", "lab3", nus));
|
||||
System.out.println(getGrade("CS2040S", "Steve", "lab4", nus));
|
||||
System.out.println(getGrade("CS2030S", "Tony", "lab1", nus));
|
||||
System.out.println(getGrade("CS2030S", "Tony", "midterm", nus));
|
||||
System.out.println(getGrade("CS2040S", "Tony", "lab4", nus));
|
||||
System.out.println(getGrade("CS2040S", "Bruce", "lab4", nus));
|
||||
}
|
||||
}
|
||||
BIN
cs2030s/labs/Lab5/Lab5.pdf
Normal file
BIN
cs2030s/labs/Lab5/Lab5.pdf
Normal file
Binary file not shown.
24
cs2030s/labs/Lab5/Test0.java
Normal file
24
cs2030s/labs/Lab5/Test0.java
Normal file
@@ -0,0 +1,24 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test0 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
we.expectCompile("Actually<Object> a = new Actually<>() should not compile",
|
||||
"cs2030s.fp.Actually<Object> a = new cs2030s.fp.Actually<>();", false);
|
||||
we.expectCompile("Actually.Success<Object> s should not compile",
|
||||
"cs2030s.fp.Actually.Success<Object> s;", false);
|
||||
we.expectCompile("Actually.Failure f should not compile",
|
||||
"cs2030s.fp.Actually.Failure f;", false);
|
||||
|
||||
we.expectCompile("Actually<String> success = Actually.ok(\"success\") should compile",
|
||||
"cs2030s.fp.Actually<String> success = cs2030s.fp.Actually.ok(\"success\");", true);
|
||||
we.expectCompile("Actually<Integer> none = Actually.ok(null) should compile",
|
||||
"cs2030s.fp.Actually<Integer> none = cs2030s.fp.Actually.ok(null);", true);
|
||||
we.expectCompile("Actually<Integer> four = Actually.ok(4) should compile",
|
||||
"cs2030s.fp.Actually<Integer> four = cs2030s.fp.Actually.ok(4);", true);
|
||||
we.expectCompile("Actually<Object> div0 = Actually.err(new ArithmeticException(\"Divide by 0\")) should compile",
|
||||
"cs2030s.fp.Actually<Object> div0 = cs2030s.fp.Actually.err(new ArithmeticException(\"Divide by 0\"));", true);
|
||||
}
|
||||
}
|
||||
73
cs2030s/labs/Lab5/Test1.java
Normal file
73
cs2030s/labs/Lab5/Test1.java
Normal file
@@ -0,0 +1,73 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test1 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
String none = null;
|
||||
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(\"Err\")).equals(Actually.err(new Exception(\"Err\")))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException("Err")).equals(cs2030s.fp.Actually.err(new Exception("Err"))),
|
||||
true
|
||||
);
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(\"Err\")).equals(Actually.err(new Exception(\"Error\")))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException("Err")).equals(cs2030s.fp.Actually.err(new Exception("Error"))),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(\"Err\")).equals(Actually.err(new Exception(null)))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException("Err")).equals(cs2030s.fp.Actually.err(new Exception(none))),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(null)).equals(Actually.err(new Exception(null)))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException(none)).equals(cs2030s.fp.Actually.err(new Exception(none))),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.err(new ArithmeticException(\"Err\")).equals(Actually.ok(\"Err\"))",
|
||||
cs2030s.fp.Actually.err(new ArithmeticException("Err")).equals(cs2030s.fp.Actually.ok("Err")),
|
||||
false
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"Actually.ok(\"Err\").equals(Actually.ok(\"Err\"))",
|
||||
cs2030s.fp.Actually.ok("Err").equals(cs2030s.fp.Actually.ok("Err")),
|
||||
true
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(\"Err\").equals(Actually.err(new Exception(\"Error\")))",
|
||||
cs2030s.fp.Actually.ok("Err").equals(cs2030s.fp.Actually.err(new Exception("Error"))),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(\"Err\").equals(\"Err\")",
|
||||
cs2030s.fp.Actually.ok("Err").equals("Err"),
|
||||
false
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"Actually.ok(null).equals(Actually.ok(\"Err\"))",
|
||||
cs2030s.fp.Actually.ok(null).equals(cs2030s.fp.Actually.ok("Err")),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(null).equals(Actually.ok(null))",
|
||||
cs2030s.fp.Actually.ok(null).equals(cs2030s.fp.Actually.ok(null)),
|
||||
true
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(null).equals(\"Err\")",
|
||||
cs2030s.fp.Actually.ok(null).equals("Err"),
|
||||
false
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(null).equals(null)",
|
||||
cs2030s.fp.Actually.ok(null).equals(null),
|
||||
false
|
||||
);
|
||||
}
|
||||
}
|
||||
72
cs2030s/labs/Lab5/Test2.java
Normal file
72
cs2030s/labs/Lab5/Test2.java
Normal file
@@ -0,0 +1,72 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test2 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
PrintStream old = System.out;
|
||||
ByteArrayOutputStream baos;
|
||||
PrintStream ps;
|
||||
|
||||
cs2030s.fp.Constant<Integer> zero = new cs2030s.fp.Constant<>() {
|
||||
public Integer init() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Action<Integer> print = new cs2030s.fp.Action<>() {
|
||||
public void call(Integer i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
we.expect(
|
||||
"Actually.<Number>ok(0).unwrap()",
|
||||
cs2030s.fp.Actually.<Number>ok(0).unwrap().toString(),
|
||||
"0"
|
||||
);
|
||||
} catch(Exception e) {
|
||||
System.out.println("Unexpected error occurs");
|
||||
}
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
cs2030s.fp.Actually.<Integer>ok(9).finish(print);
|
||||
we.expectPrint("Actually.<Integer>ok(9).finish(print)",
|
||||
"9",
|
||||
baos,
|
||||
old);
|
||||
|
||||
baos = new ByteArrayOutputStream();
|
||||
ps = new PrintStream(baos);
|
||||
System.setOut(ps);
|
||||
cs2030s.fp.Actually.<Integer>err(new Exception("Err")).finish(print);
|
||||
we.expectPrint("Actually.<Integer>err(new Exception(\"Err\")).finish(print)",
|
||||
"",
|
||||
baos,
|
||||
old);
|
||||
|
||||
we.expect(
|
||||
"Actually.<Number>ok(9).except(zero)",
|
||||
cs2030s.fp.Actually.<Number>ok(9).except(zero).toString(),
|
||||
"9"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.<Number>err(new ArithmeticException(\"div by 0\")).except(zero)",
|
||||
cs2030s.fp.Actually.<Number>err(new ArithmeticException("div by 0")).except(zero).toString(),
|
||||
"0"
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"Actually.<Number>err(new ArithmeticException(\"div by 0\")).unless(4)",
|
||||
cs2030s.fp.Actually.<Number>err(new ArithmeticException("div by 0")).unless(4).toString(),
|
||||
"4"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.<Number>ok(0).unless(4)",
|
||||
cs2030s.fp.Actually.<Number>ok(0).unless(4).toString(),
|
||||
"0"
|
||||
);
|
||||
}
|
||||
}
|
||||
71
cs2030s/labs/Lab5/Test3.java
Normal file
71
cs2030s/labs/Lab5/Test3.java
Normal file
@@ -0,0 +1,71 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test3 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
cs2030s.fp.Immutator<Integer,Integer> inc = new cs2030s.fp.Immutator<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p+1;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<Integer,Integer> inv = new cs2030s.fp.Immutator<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return 1/p;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<Number,Integer> incNum = new cs2030s.fp.Immutator<>() {
|
||||
public Number invoke(Integer p) {
|
||||
return p+1;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<Number,Integer> invNum = new cs2030s.fp.Immutator<>() {
|
||||
public Number invoke(Integer p) {
|
||||
return 1/p;
|
||||
}
|
||||
};
|
||||
|
||||
we.expect(
|
||||
"Actually.<Integer>ok(0).transform(inc)",
|
||||
cs2030s.fp.Actually.<Integer>ok(0).transform(inc).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.<Integer>ok(0).transform(inv)",
|
||||
cs2030s.fp.Actually.<Integer>ok(0).transform(inv).toString(),
|
||||
"[java.lang.ArithmeticException] / by zero"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(0).transform(inc)",
|
||||
cs2030s.fp.Actually.ok(0).transform(inc).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(0).transform(inv)",
|
||||
cs2030s.fp.Actually.ok(0).transform(inv).toString(),
|
||||
"[java.lang.ArithmeticException] / by zero"
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"Actually.<Integer>ok(0).transform(incNum)",
|
||||
cs2030s.fp.Actually.<Integer>ok(0).transform(incNum).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.<Integer>ok(0).transform(invNum)",
|
||||
cs2030s.fp.Actually.<Integer>ok(0).transform(invNum).toString(),
|
||||
"[java.lang.ArithmeticException] / by zero"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(0).transform(incNum)",
|
||||
cs2030s.fp.Actually.ok(0).transform(incNum).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"Actually.ok(0).transform(invNum)",
|
||||
cs2030s.fp.Actually.ok(0).transform(invNum).toString(),
|
||||
"[java.lang.ArithmeticException] / by zero"
|
||||
);
|
||||
}
|
||||
}
|
||||
45
cs2030s/labs/Lab5/Test4.java
Normal file
45
cs2030s/labs/Lab5/Test4.java
Normal file
@@ -0,0 +1,45 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test4 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
cs2030s.fp.Transformer<Integer,Integer> inc = new cs2030s.fp.Transformer<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p+1;
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Transformer<Integer,Integer> sqr = new cs2030s.fp.Transformer<>() {
|
||||
public Integer invoke(Integer p) {
|
||||
return p*p;
|
||||
}
|
||||
};
|
||||
|
||||
cs2030s.fp.Transformer<Integer,Integer> sqrPlusOneA = sqr.before(inc);
|
||||
cs2030s.fp.Transformer<Integer,Integer> sqrPlusOneB = inc.after(sqr);
|
||||
cs2030s.fp.Transformer<Integer,Integer> plusOneSqrA = sqr.after(inc);
|
||||
cs2030s.fp.Transformer<Integer,Integer> plusOneSqrB = inc.before(sqr);
|
||||
|
||||
we.expect(
|
||||
"sqrPlusOneA.invoke(2)",
|
||||
sqrPlusOneA.invoke(2).toString(),
|
||||
"5"
|
||||
);
|
||||
we.expect(
|
||||
"sqrPlusOneB.invoke(2)",
|
||||
sqrPlusOneA.invoke(2).toString(),
|
||||
"5"
|
||||
);
|
||||
we.expect(
|
||||
"plusOneSqrA.invoke(2)",
|
||||
plusOneSqrA.invoke(2).toString(),
|
||||
"9"
|
||||
);
|
||||
we.expect(
|
||||
"plusOneSqrB.invoke(2)",
|
||||
plusOneSqrB.invoke(2).toString(),
|
||||
"9"
|
||||
);
|
||||
}
|
||||
}
|
||||
55
cs2030s/labs/Lab5/Test5.java
Normal file
55
cs2030s/labs/Lab5/Test5.java
Normal file
@@ -0,0 +1,55 @@
|
||||
import java.io.PrintStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
public class Test5 {
|
||||
public static void main(String[] args) {
|
||||
CS2030STest we = new CS2030STest();
|
||||
|
||||
cs2030s.fp.Immutator<cs2030s.fp.Actually<Integer>,Integer> half = new cs2030s.fp.Immutator<>() {
|
||||
public cs2030s.fp.Actually<Integer> invoke(Integer p) {
|
||||
if (p%2 == 0) {
|
||||
return cs2030s.fp.Actually.<Integer>ok(p/2);
|
||||
} else {
|
||||
return cs2030s.fp.Actually.<Integer>err(new Exception("odd number"));
|
||||
}
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<cs2030s.fp.Actually<Integer>,Integer> inc = new cs2030s.fp.Immutator<>() {
|
||||
public cs2030s.fp.Actually<Integer> invoke(Integer p) {
|
||||
return cs2030s.fp.Actually.<Integer>ok(p+1);
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Immutator<cs2030s.fp.Actually<Integer>,Integer> make = new cs2030s.fp.Immutator<>() {
|
||||
public cs2030s.fp.Actually<Integer> invoke(Integer p) {
|
||||
return cs2030s.fp.Actually.<Integer>ok(p);
|
||||
}
|
||||
};
|
||||
cs2030s.fp.Constant<Integer> zero = new cs2030s.fp.Constant<>() {
|
||||
public Integer init() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
we.expect(
|
||||
"make.invoke(0).next(inc).next(inc).next(half)",
|
||||
make.invoke(0).next(inc).next(inc).next(half).toString(),
|
||||
"<1>"
|
||||
);
|
||||
we.expect(
|
||||
"make.invoke(0).next(inc).next(half).next(inc)",
|
||||
make.invoke(0).next(inc).next(half).next(inc).toString(),
|
||||
"[java.lang.Exception] odd number"
|
||||
);
|
||||
|
||||
we.expect(
|
||||
"make.invoke(0).next(inc).next(inc).next(half).except(zero)",
|
||||
make.invoke(0).next(inc).next(inc).next(half).except(zero).toString(),
|
||||
"1"
|
||||
);
|
||||
we.expect(
|
||||
"make.invoke(0).next(inc).next(half).next(inc).except(zero)",
|
||||
make.invoke(0).next(inc).next(half).next(inc).except(zero).toString(),
|
||||
"0"
|
||||
);
|
||||
}
|
||||
}
|
||||
14
cs2030s/labs/Lab5/cs2030s/fp/Action.java
Normal file
14
cs2030s/labs/Lab5/cs2030s/fp/Action.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
/**
|
||||
* The Action interface that can be called
|
||||
* on an object of type T to act.
|
||||
* Contains a single abstract method call.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
public interface Action<T> {
|
||||
void call(T item);
|
||||
}
|
||||
15
cs2030s/labs/Lab5/cs2030s/fp/Actionable.java
Normal file
15
cs2030s/labs/Lab5/cs2030s/fp/Actionable.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
/**
|
||||
* The Actionable interface that can
|
||||
* act when given an action.
|
||||
* Contains a single abstract method act.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
// act consumes the T and passes it to action, thus super
|
||||
public interface Actionable<T> {
|
||||
public void act(Action<? super T> action);
|
||||
}
|
||||
179
cs2030s/labs/Lab5/cs2030s/fp/Actually.java
Normal file
179
cs2030s/labs/Lab5/cs2030s/fp/Actually.java
Normal file
@@ -0,0 +1,179 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
public abstract class Actually<T> implements Immutatorable<T>, Actionable<T> {
|
||||
|
||||
public static <T> Actually<T> ok(T value) {
|
||||
return new Success<T>(value);
|
||||
}
|
||||
|
||||
public static <T> Actually<T> err(Exception e) {
|
||||
// It is okay to do an unchecked cast here as failure types don't use
|
||||
// the value T.
|
||||
@SuppressWarnings("unchecked")
|
||||
Actually<T> failure = (Actually<T>) new Failure(e);
|
||||
return failure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract <R> Actually<R> transform(Immutator<? extends R, ? super T> immutator);
|
||||
|
||||
public abstract T unwrap() throws Exception;
|
||||
|
||||
public abstract <U extends T> T except(Constant<? extends U> c);
|
||||
|
||||
public abstract void finish(Action<? super T> action);
|
||||
|
||||
public abstract <U extends T> T unless(U other);
|
||||
|
||||
public abstract <R> Actually<R> next(Immutator<? extends Actually<? extends R>, ? super T> immutator);
|
||||
|
||||
private static class Success<T> extends Actually<T> {
|
||||
private final T value;
|
||||
|
||||
private Success(T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T unwrap() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends T> T except(Constant<? extends U> c) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(Action<? super T> action) {
|
||||
action.call(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends T> T unless(U other) {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Actually<R> next(Immutator<? extends Actually<? extends R>, ? super T> immutator) {
|
||||
try {
|
||||
// it is okay to cast from <? extends R> to <R>
|
||||
@SuppressWarnings("unchecked")
|
||||
Actually<R> result = (Actually<R>) immutator.invoke(this.value);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
return Actually.err(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Actually<R> transform(Immutator<? extends R, ? super T> immutator) {
|
||||
try {
|
||||
return Actually.ok(immutator.invoke(this.value));
|
||||
} catch (Exception e) {
|
||||
return Actually.err(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(Action<? super T> action) {
|
||||
action.call(this.value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<" + value + ">";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Success<?>) {
|
||||
Success<?> other = (Success<?>) obj;
|
||||
if (this.value == other.value) {
|
||||
return true;
|
||||
}
|
||||
if (this.value != null && this.value.equals(other.value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Failure extends Actually<Object> {
|
||||
private final Exception e;
|
||||
|
||||
Failure(Exception e) {
|
||||
this.e = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unwrap() throws Exception {
|
||||
throw e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U> U except(Constant<? extends U> c) {
|
||||
return c.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unless(Object other) {
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(Action<? super Object> action) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Actually<R> transform(Immutator<? extends R, ? super Object> immutator) {
|
||||
return Actually.err(this.e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Actually<R> next(Immutator<? extends Actually<? extends R>, ? super Object> immutator) {
|
||||
return Actually.err(this.e);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(Action<? super Object> action) {
|
||||
// Do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + e.getClass().getName() + "] " + e.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Failure) {
|
||||
Failure other = (Failure) obj;
|
||||
if (this.e == other.e) {
|
||||
return true;
|
||||
}
|
||||
if (this.e == null || other.e == null) {
|
||||
return false;
|
||||
}
|
||||
if (this.e.getMessage() == null || other.e.getMessage() == null) {
|
||||
return false;
|
||||
}
|
||||
return this.e.getMessage() == other.e.getMessage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
5
cs2030s/labs/Lab5/cs2030s/fp/Constant.java
Normal file
5
cs2030s/labs/Lab5/cs2030s/fp/Constant.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
public interface Constant<T> {
|
||||
T init();
|
||||
}
|
||||
14
cs2030s/labs/Lab5/cs2030s/fp/Immutator.java
Normal file
14
cs2030s/labs/Lab5/cs2030s/fp/Immutator.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
/**
|
||||
* The Immutator interface that can transform
|
||||
* to type T2, an object of type T1.
|
||||
* Contains a single abstract method invoke.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
public interface Immutator<R, P> {
|
||||
public R invoke(P param);
|
||||
}
|
||||
15
cs2030s/labs/Lab5/cs2030s/fp/Immutatorable.java
Normal file
15
cs2030s/labs/Lab5/cs2030s/fp/Immutatorable.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
/**
|
||||
* The Immutatorable interface that can
|
||||
* transform when given something that is
|
||||
* Immutator.
|
||||
* Contains a single abstract method transform.
|
||||
* CS2030S Lab 4
|
||||
* AY22/23 Semester 1
|
||||
* @author Yadunand Prem (10B)
|
||||
*/
|
||||
|
||||
public interface Immutatorable<T> {
|
||||
public <R> Immutatorable<R> transform(Immutator<? extends R, ? super T> immutator);
|
||||
}
|
||||
23
cs2030s/labs/Lab5/cs2030s/fp/Transformer.java
Normal file
23
cs2030s/labs/Lab5/cs2030s/fp/Transformer.java
Normal file
@@ -0,0 +1,23 @@
|
||||
package cs2030s.fp;
|
||||
|
||||
public abstract class Transformer<R, P> implements Immutator<R, P> {
|
||||
public <N> Transformer<R, N> after(Transformer<P, N> g) {
|
||||
Transformer<R, P> f = this;
|
||||
return new Transformer<R, N>() {
|
||||
@Override
|
||||
public R invoke(N param) {
|
||||
return f.invoke(g.invoke(param));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public <T> Transformer<T, P> before(Transformer<T, R> g) {
|
||||
Transformer<R, P> f = this;
|
||||
return new Transformer<T, P>() {
|
||||
@Override
|
||||
public T invoke(P param) {
|
||||
return g.invoke(f.invoke(param));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user