add lab6
This commit is contained in:
24
Lab6/And.java
Normal file
24
Lab6/And.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
class And implements Cond {
|
||||||
|
private Cond lVal;
|
||||||
|
private Cond rVal;
|
||||||
|
|
||||||
|
public And(Cond lVal, Cond rVal) {
|
||||||
|
this.lVal = lVal;
|
||||||
|
this.rVal = rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean eval() {
|
||||||
|
return this.lVal.eval() && this.rVal.eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + this.lVal + " & " + this.rVal + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cond neg() {
|
||||||
|
return new Or(lVal.neg(), rVal.neg());
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Lab6/Bool.java
Normal file
24
Lab6/Bool.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import cs2030s.fp.Constant;
|
||||||
|
|
||||||
|
class Bool implements Cond {
|
||||||
|
private Boolean val;
|
||||||
|
|
||||||
|
public Bool(Constant<Boolean> val) {
|
||||||
|
this.val = val.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean eval() {
|
||||||
|
return this.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.val.toString().substring(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cond neg() {
|
||||||
|
return new Not(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
76
Lab6/CS2030STest.java
Normal file
76
Lab6/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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
4
Lab6/Cond.java
Normal file
4
Lab6/Cond.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
interface Cond {
|
||||||
|
boolean eval();
|
||||||
|
Cond neg();
|
||||||
|
}
|
||||||
19
Lab6/Lab6.h
Normal file
19
Lab6/Lab6.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/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 Combiner.java cs2030s/fp/Combiner.java
|
||||||
|
mv Constant.java cs2030s/fp/Constant.java
|
||||||
|
mv Immutator.java cs2030s/fp/Immutator.java
|
||||||
|
mv Immutatorable.java cs2030s/fp/Immutatorable.java
|
||||||
|
mv Lazy.java cs2030s/fp/Lazy.java
|
||||||
|
mv Memo.java cs2030s/fp/Memo.java
|
||||||
|
|
||||||
|
javac cs2030s/fp/*.java
|
||||||
|
javac *.java
|
||||||
162
Lab6/Lab6.java
Normal file
162
Lab6/Lab6.java
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
import cs2030s.fp.*;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
class Lab6 {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test1() {
|
||||||
|
Lazy<Integer> mod1 = Lazy.from(2030);
|
||||||
|
System.out.println(mod1.toString());
|
||||||
|
|
||||||
|
Lazy<String> mod2 = Lazy.from(() -> "CS2030S");
|
||||||
|
System.out.println(mod2.toString());
|
||||||
|
|
||||||
|
Lazy<String> hello = Lazy.from(() -> {
|
||||||
|
System.out.println("world!");
|
||||||
|
return "hello";
|
||||||
|
});
|
||||||
|
System.out.println(hello.get().toString());
|
||||||
|
System.out.println(hello.get().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test2() {
|
||||||
|
Memo<Integer> mod1 = Memo.from(2030);
|
||||||
|
System.out.println(mod1.toString());
|
||||||
|
|
||||||
|
Memo<String> mod2 = Memo.from(() -> "CS2030S");
|
||||||
|
System.out.println(mod2.toString());
|
||||||
|
System.out.println(mod2.get());
|
||||||
|
System.out.println(mod2.toString());
|
||||||
|
|
||||||
|
Memo<String> hello = Memo.from(() -> {
|
||||||
|
System.out.println("world!");
|
||||||
|
return "hello";
|
||||||
|
});
|
||||||
|
System.out.println(hello.get().toString());
|
||||||
|
System.out.println(hello.get().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test3() {
|
||||||
|
Constant<String> password = () -> "123456";
|
||||||
|
Lazy<String> lazy = Lazy.from(password);
|
||||||
|
System.out.println(lazy.toString());
|
||||||
|
System.out.println(lazy.transform(str -> str.substring(0, 1)).toString());
|
||||||
|
|
||||||
|
Memo<String> memo = Memo.from(password);
|
||||||
|
System.out.println(memo.toString());
|
||||||
|
System.out.println(memo.transform(str -> str.substring(0, 1)).toString());
|
||||||
|
System.out.println(memo.transform(str -> str.substring(0, 1)).get().toString());
|
||||||
|
System.out.println(memo.toString());
|
||||||
|
|
||||||
|
Immutator<Integer, String> len = str -> {
|
||||||
|
System.out.println("length");
|
||||||
|
return str.length();
|
||||||
|
};
|
||||||
|
Lazy<Integer> lazyLen = lazy.transform(len);
|
||||||
|
System.out.println(lazyLen.toString());
|
||||||
|
System.out.println(lazyLen.get());
|
||||||
|
System.out.println(lazyLen.get());
|
||||||
|
|
||||||
|
Memo<Integer> step1 = Memo.from(1010);
|
||||||
|
Memo<Integer> step2 = step1.transform(i -> i * 2);
|
||||||
|
Memo<Integer> step3 = step2.next(i -> Memo.from(i + 10));
|
||||||
|
System.out.println(step1.toString());
|
||||||
|
System.out.println(step2.toString());
|
||||||
|
System.out.println(step3.toString());
|
||||||
|
System.out.println(step3.get());
|
||||||
|
System.out.println(step2.toString());
|
||||||
|
System.out.println(step1.toString());
|
||||||
|
|
||||||
|
Memo<Integer> noErr = Memo.from(0);
|
||||||
|
Memo<Integer> err = noErr.transform(x -> 1/x);
|
||||||
|
try {
|
||||||
|
System.out.println(err.get());
|
||||||
|
} catch(ArithmeticException ae) {
|
||||||
|
System.out.println(ae.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test4() {
|
||||||
|
Combiner<String, Integer, Integer> concat = (x, y) -> {
|
||||||
|
System.out.println("combine");
|
||||||
|
return x.toString() + y.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
Memo<Integer> twenty, thirty, modInt;
|
||||||
|
twenty = Memo.from(() -> 20);
|
||||||
|
thirty = Memo.from(() -> 30);
|
||||||
|
modInt = twenty.combine(thirty, (x, y) -> x * 100 + y);
|
||||||
|
Memo<String> modStr = twenty.combine(thirty, concat);
|
||||||
|
|
||||||
|
System.out.println(twenty.toString());
|
||||||
|
System.out.println(thirty.toString());
|
||||||
|
System.out.println(modInt.toString());
|
||||||
|
System.out.println(modStr.toString());
|
||||||
|
System.out.println(modStr.get().toString());
|
||||||
|
System.out.println(twenty.toString());
|
||||||
|
System.out.println(thirty.toString());
|
||||||
|
System.out.println(modInt.toString());
|
||||||
|
|
||||||
|
Combiner<String, Integer, Double> comb = (x, y) -> x.toString() + " + " + y.toString();
|
||||||
|
Memo<String> s = modInt.combine(Memo.from(0.1), comb);
|
||||||
|
System.out.println(s.toString());
|
||||||
|
System.out.println(s.get());
|
||||||
|
System.out.println(modInt.toString());
|
||||||
|
|
||||||
|
Memo<Integer> x1 = Memo.from(1);
|
||||||
|
for (int i = 0; i < 10; i ++) {
|
||||||
|
final Memo<Integer> y1 = x1; // final just to ensure it is unchanged
|
||||||
|
final int j = i;
|
||||||
|
x1 = Memo.from(() -> { System.out.println(j); return y1.get() + y1.get(); });
|
||||||
|
}
|
||||||
|
System.out.println(x1.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test5() {
|
||||||
|
Constant<Boolean> t = new Constant<>() {
|
||||||
|
public Boolean init() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Constant<Boolean> f = new Constant<>() {
|
||||||
|
public Boolean init() {
|
||||||
|
String res = "";
|
||||||
|
for (int i=0; i<100000; i++) {
|
||||||
|
res += i;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Cond cond = new And(new Or(new Bool(t), new Bool(f)), new Not(new Not(new Bool(t))));
|
||||||
|
|
||||||
|
System.out.println(cond.toString());
|
||||||
|
System.out.println(cond.neg().toString());
|
||||||
|
System.out.println(cond.neg().neg().toString());
|
||||||
|
System.out.println(cond.eval());
|
||||||
|
System.out.println(cond.neg().toString());
|
||||||
|
System.out.println(cond.neg().neg().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Lab6/Lab6.pdf
Normal file
BIN
Lab6/Lab6.pdf
Normal file
Binary file not shown.
21
Lab6/Not.java
Normal file
21
Lab6/Not.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
class Not implements Cond {
|
||||||
|
private Cond val;
|
||||||
|
|
||||||
|
public Not(Cond val) {
|
||||||
|
this.val = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean eval() {
|
||||||
|
return !this.val.eval();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "!(" + this.val + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cond neg() {
|
||||||
|
return this.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Lab6/Or.java
Normal file
24
Lab6/Or.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
class Or implements Cond {
|
||||||
|
private Cond lVal;
|
||||||
|
private Cond rVal;
|
||||||
|
|
||||||
|
public Or(Cond lVal, Cond rVal) {
|
||||||
|
this.lVal = lVal;
|
||||||
|
this.rVal = rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean eval() {
|
||||||
|
return this.lVal.eval() || this.rVal.eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + this.lVal + " | " + this.rVal + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cond neg() {
|
||||||
|
return new And(lVal.neg(), rVal.neg());
|
||||||
|
}
|
||||||
|
}
|
||||||
37
Lab6/Test1.java
Normal file
37
Lab6/Test1.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import cs2030s.fp.Constant;
|
||||||
|
import cs2030s.fp.Lazy;
|
||||||
|
|
||||||
|
public class Test1 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CS2030STest we = new CS2030STest();
|
||||||
|
|
||||||
|
Lazy<Integer> mod1 = Lazy.from(2030);
|
||||||
|
we.expect(
|
||||||
|
"Lazy<Integer> mod1 = Lazy.from(2030)",
|
||||||
|
mod1.toString(),
|
||||||
|
"2030"
|
||||||
|
);
|
||||||
|
|
||||||
|
Lazy<String> mod2 = Lazy.from(() -> "CS2030S");
|
||||||
|
we.expect(
|
||||||
|
"Lazy<String> mod2 = Lazy.from(\"CS2030S\")",
|
||||||
|
mod2.toString(),
|
||||||
|
"CS2030S"
|
||||||
|
);
|
||||||
|
|
||||||
|
Lazy<String> hello = Lazy.from(() -> {
|
||||||
|
System.out.println("world!");
|
||||||
|
return "hello";
|
||||||
|
});
|
||||||
|
we.expect(
|
||||||
|
"hello.get() // warning: we do not check print output",
|
||||||
|
hello.get().toString(),
|
||||||
|
"hello"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"hello.get() // warning: we do not check print output",
|
||||||
|
hello.get().toString(),
|
||||||
|
"hello"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
42
Lab6/Test2.java
Normal file
42
Lab6/Test2.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import cs2030s.fp.Constant;
|
||||||
|
import cs2030s.fp.Memo;
|
||||||
|
|
||||||
|
public class Test2 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CS2030STest we = new CS2030STest();
|
||||||
|
|
||||||
|
Memo<Integer> mod1 = Memo.from(2030);
|
||||||
|
we.expect(
|
||||||
|
"Memo<Integer> mod1 = Memo.from(2030)",
|
||||||
|
mod1.toString(),
|
||||||
|
"2030"
|
||||||
|
);
|
||||||
|
|
||||||
|
Memo<String> mod2 = Memo.from(() -> "CS2030S");
|
||||||
|
we.expect(
|
||||||
|
"Memo<String> mod2 = Memo.from(\"CS2030S\")",
|
||||||
|
mod2.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"mod2.get()",
|
||||||
|
mod2.get().toString(),
|
||||||
|
"CS2030S"
|
||||||
|
);
|
||||||
|
|
||||||
|
Memo<String> hello = Memo.from(() -> {
|
||||||
|
System.out.println("world!");
|
||||||
|
return "hello";
|
||||||
|
});
|
||||||
|
we.expect(
|
||||||
|
"hello.get() // warning: we do not check print output",
|
||||||
|
hello.get(),
|
||||||
|
"hello"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"hello.get() // warning: we do not check print output",
|
||||||
|
hello.get(),
|
||||||
|
"hello"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
134
Lab6/Test3.java
Normal file
134
Lab6/Test3.java
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
import cs2030s.fp.Constant;
|
||||||
|
import cs2030s.fp.Immutator;
|
||||||
|
import cs2030s.fp.Lazy;
|
||||||
|
import cs2030s.fp.Memo;
|
||||||
|
|
||||||
|
public class Test3 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CS2030STest we = new CS2030STest();
|
||||||
|
|
||||||
|
Constant<String> password = () -> "123456";
|
||||||
|
Lazy<String> lazy = Lazy.from(password);
|
||||||
|
|
||||||
|
we.expect(
|
||||||
|
"lazy",
|
||||||
|
lazy.toString(),
|
||||||
|
"123456"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"lazy.transform(str -> str.substring(0, 1))",
|
||||||
|
lazy.transform(str -> str.substring(0, 1)).toString(),
|
||||||
|
"1"
|
||||||
|
);
|
||||||
|
|
||||||
|
Memo<String> memo = Memo.from(password);
|
||||||
|
we.expect(
|
||||||
|
"memo",
|
||||||
|
memo.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"memo.transform(str -> str.substring(0, 1))",
|
||||||
|
memo.transform(str -> str.substring(0, 1)).toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"memo.transform(str -> str.substring(0, 1)).get()",
|
||||||
|
memo.transform(str -> str.substring(0, 1)).get().toString(),
|
||||||
|
"1"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"memo",
|
||||||
|
memo.toString(),
|
||||||
|
"123456"
|
||||||
|
);
|
||||||
|
|
||||||
|
Immutator<Integer, String> len = str -> {
|
||||||
|
System.out.println("length");
|
||||||
|
return str.length();
|
||||||
|
};
|
||||||
|
Lazy<Integer> lazyLen = lazy.transform(len);
|
||||||
|
we.expect(
|
||||||
|
"lazyLen // warning: we do not check print output",
|
||||||
|
lazyLen.toString(),
|
||||||
|
"6"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"lazyLen.get() // warning: we do not check print output",
|
||||||
|
lazyLen.get(),
|
||||||
|
6
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"lazyLen.get() // warning: we do not check print output",
|
||||||
|
lazyLen.get(),
|
||||||
|
6
|
||||||
|
);
|
||||||
|
|
||||||
|
Memo<Integer> memoLen = memo.transform(len);
|
||||||
|
we.expect(
|
||||||
|
"memoLen // warning: we do not check print output",
|
||||||
|
memoLen.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"memoLen.get() // warning: we do not check print output",
|
||||||
|
memoLen.get(),
|
||||||
|
6
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"memoLen.get() // warning: we do not check print output",
|
||||||
|
memoLen.get(),
|
||||||
|
6
|
||||||
|
);
|
||||||
|
|
||||||
|
Memo<Integer> step1 = Memo.from(1010);
|
||||||
|
Memo<Integer> step2 = step1.transform(i -> i * 2);
|
||||||
|
Memo<Integer> step3 = step2.next(i -> Memo.from(i + 10));
|
||||||
|
we.expect(
|
||||||
|
"step1",
|
||||||
|
step1.toString(),
|
||||||
|
"1010"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"step2",
|
||||||
|
step2.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"step3",
|
||||||
|
step3.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"step3.get()",
|
||||||
|
step3.get(),
|
||||||
|
2030
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"step2",
|
||||||
|
step2.toString(),
|
||||||
|
"2020"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"step1",
|
||||||
|
step1.toString(),
|
||||||
|
"1010"
|
||||||
|
);
|
||||||
|
|
||||||
|
Memo<Integer> noErr = Memo.from(0);
|
||||||
|
Memo<Integer> err = noErr.transform(x -> 1/x);
|
||||||
|
try {
|
||||||
|
we.expect(
|
||||||
|
"err.get()",
|
||||||
|
err.get(),
|
||||||
|
""
|
||||||
|
);
|
||||||
|
} catch(ArithmeticException ae) {
|
||||||
|
we.expect(
|
||||||
|
"err.get()",
|
||||||
|
ae.getMessage(),
|
||||||
|
"/ by zero"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
92
Lab6/Test4.java
Normal file
92
Lab6/Test4.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
import cs2030s.fp.Combiner;
|
||||||
|
import cs2030s.fp.Memo;
|
||||||
|
|
||||||
|
public class Test4 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CS2030STest we = new CS2030STest();
|
||||||
|
|
||||||
|
Combiner<String, Integer, Integer> concat = (x, y) -> {
|
||||||
|
System.out.println("combine");
|
||||||
|
return x.toString() + y.toString();
|
||||||
|
};
|
||||||
|
|
||||||
|
Memo<Integer> twenty, thirty, modInt;
|
||||||
|
twenty = Memo.from(() -> 20);
|
||||||
|
thirty = Memo.from(() -> 30);
|
||||||
|
modInt = twenty.combine(thirty, (x, y) -> x * 100 + y);
|
||||||
|
Memo<String> modStr = twenty.combine(thirty, concat);
|
||||||
|
|
||||||
|
we.expect(
|
||||||
|
"twenty",
|
||||||
|
twenty.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"thirty",
|
||||||
|
thirty.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"modInt",
|
||||||
|
modInt.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"modStr",
|
||||||
|
modStr.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
|
||||||
|
we.expect(
|
||||||
|
"modStr.get()",
|
||||||
|
modStr.get().toString(),
|
||||||
|
"2030"
|
||||||
|
);
|
||||||
|
|
||||||
|
we.expect(
|
||||||
|
"twenty",
|
||||||
|
twenty.toString(),
|
||||||
|
"20"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"thirty",
|
||||||
|
thirty.toString(),
|
||||||
|
"30"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"modInt",
|
||||||
|
modInt.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
|
||||||
|
Combiner<String, Integer, Double> comb = (x, y) -> x.toString() + " + " + y.toString();
|
||||||
|
Memo<String> s = modInt.combine(Memo.from(0.1), comb);
|
||||||
|
we.expect(
|
||||||
|
"s",
|
||||||
|
s.toString(),
|
||||||
|
"?"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"s.get()",
|
||||||
|
s.get(),
|
||||||
|
"2030 + 0.1"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"modInt",
|
||||||
|
modInt.toString(),
|
||||||
|
"2030"
|
||||||
|
);
|
||||||
|
|
||||||
|
Memo<Integer> x1 = Memo.from(1);
|
||||||
|
for (int i = 0; i < 10; i ++) {
|
||||||
|
final Memo<Integer> y1 = x1; // final just to ensure it is unchanged
|
||||||
|
final int j = i;
|
||||||
|
x1 = Memo.from(() -> { System.out.println(j); return y1.get() + y1.get(); });
|
||||||
|
}
|
||||||
|
we.expect(
|
||||||
|
"x.get()",
|
||||||
|
x1.get(),
|
||||||
|
1024
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
55
Lab6/Test5.java
Normal file
55
Lab6/Test5.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import cs2030s.fp.Constant;
|
||||||
|
import cs2030s.fp.Memo;
|
||||||
|
|
||||||
|
public class Test5 {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
CS2030STest we = new CS2030STest();
|
||||||
|
|
||||||
|
Constant<Boolean> t = new Constant<>() {
|
||||||
|
public Boolean init() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Constant<Boolean> f = new Constant<>() {
|
||||||
|
public Boolean init() {
|
||||||
|
String res = "";
|
||||||
|
for (int i=0; i<100000; i++) {
|
||||||
|
res += i;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Cond cond = new And(new Or(new Bool(t), new Bool(f)), new Not(new Not(new Bool(t))));
|
||||||
|
|
||||||
|
we.expect(
|
||||||
|
"cond",
|
||||||
|
cond.toString(),
|
||||||
|
"((? | ?) & !(!(?)))"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"cond.neg()",
|
||||||
|
cond.neg().toString(),
|
||||||
|
"((!(?) & !(?)) | !(?))"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"cond.neg().neg()",
|
||||||
|
cond.neg().neg().toString(),
|
||||||
|
"((? | ?) & ?)"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"cond.eval()",
|
||||||
|
cond.eval(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"cond.neg()",
|
||||||
|
cond.neg().toString(),
|
||||||
|
"((!(t) & !(?)) | !(t))"
|
||||||
|
);
|
||||||
|
we.expect(
|
||||||
|
"cond.neg().neg()",
|
||||||
|
cond.neg().neg().toString(),
|
||||||
|
"((t | ?) & t)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Lab6/cs2030s/fp/Action.java
Normal file
18
Lab6/cs2030s/fp/Action.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package cs2030s.fp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a function that acts on a value.
|
||||||
|
* CS2030S Lab 5
|
||||||
|
* AY22/23 Semester 1
|
||||||
|
*
|
||||||
|
* @param <T> The type of the input value.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
interface Action<T> {
|
||||||
|
/**
|
||||||
|
* The functional method to act on the value t.
|
||||||
|
*
|
||||||
|
* @param t The input value.
|
||||||
|
*/
|
||||||
|
void call(T t);
|
||||||
|
}
|
||||||
17
Lab6/cs2030s/fp/Actionable.java
Normal file
17
Lab6/cs2030s/fp/Actionable.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package cs2030s.fp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a container that can act on its content.
|
||||||
|
* CS2030S Lab 5
|
||||||
|
* AY22/23 Semester 1
|
||||||
|
*
|
||||||
|
* @param <T> The type of the content.
|
||||||
|
*/
|
||||||
|
interface Actionable<T> {
|
||||||
|
/**
|
||||||
|
* The method to act on its content.
|
||||||
|
*
|
||||||
|
* @param f The action.
|
||||||
|
*/
|
||||||
|
void act(Action<? super T> f);
|
||||||
|
}
|
||||||
176
Lab6/cs2030s/fp/Actually.java
Normal file
176
Lab6/cs2030s/fp/Actually.java
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract T unwrap() throws Exception;
|
||||||
|
|
||||||
|
public abstract T except(Constant<? extends T> 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 T except(Constant<? extends T> 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 Object except(Constant<? extends Object> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23
Lab6/cs2030s/fp/Combiner.java
Normal file
23
Lab6/cs2030s/fp/Combiner.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package cs2030s.fp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a function that combines two values into one. The two inputs
|
||||||
|
* and the result can be of different types.
|
||||||
|
* CS2030S Lab 5
|
||||||
|
* AY20/21 Semester 2
|
||||||
|
*
|
||||||
|
* @param <R> The type of the return value
|
||||||
|
* @param <S> The type of the first input value
|
||||||
|
* @param <T> The type of the second input value
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Combiner<R, S, T> {
|
||||||
|
/**
|
||||||
|
* The functional method to combines two values into one.
|
||||||
|
*
|
||||||
|
* @param s The first input value
|
||||||
|
* @param t The second input value
|
||||||
|
* @return The value after combining s and t.
|
||||||
|
*/
|
||||||
|
R combine(S s, T t);
|
||||||
|
}
|
||||||
18
Lab6/cs2030s/fp/Constant.java
Normal file
18
Lab6/cs2030s/fp/Constant.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package cs2030s.fp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a function to initialise a constant value.
|
||||||
|
* CS2030S Lab 5
|
||||||
|
* AY22/23 Semester 1
|
||||||
|
*
|
||||||
|
* @param <T> The type of the constant value.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Constant<T> {
|
||||||
|
/**
|
||||||
|
* The functional method to initialise the constant.
|
||||||
|
*
|
||||||
|
* @return The constant value.
|
||||||
|
*/
|
||||||
|
T init();
|
||||||
|
}
|
||||||
20
Lab6/cs2030s/fp/Immutator.java
Normal file
20
Lab6/cs2030s/fp/Immutator.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package cs2030s.fp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a function that immutate one value into another, possible of different types.
|
||||||
|
* CS2030S Lab 5
|
||||||
|
* AY22/23 Semester 1
|
||||||
|
*
|
||||||
|
* @param <R> The type of the result value.
|
||||||
|
* @param <P> The type of the input value.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Immutator<R, P> {
|
||||||
|
/**
|
||||||
|
* The functional method to immutate the value p.
|
||||||
|
*
|
||||||
|
* @param p The input value.
|
||||||
|
* @return The value after applying the given immutation on p.
|
||||||
|
*/
|
||||||
|
R invoke(P p);
|
||||||
|
}
|
||||||
18
Lab6/cs2030s/fp/Immutatorable.java
Normal file
18
Lab6/cs2030s/fp/Immutatorable.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package cs2030s.fp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a container that can transforms its content to produce another container containing the immutated element, possible of different types.
|
||||||
|
* CS2030S Lab 5
|
||||||
|
* AY22/23 Semester 1
|
||||||
|
*
|
||||||
|
* @param <T> The type of the content.
|
||||||
|
*/
|
||||||
|
public interface Immutatorable<T> {
|
||||||
|
/**
|
||||||
|
* The method to produce another container with immutated element.
|
||||||
|
*
|
||||||
|
* @param f The immutator.
|
||||||
|
* @return A new container containing the immutated element.
|
||||||
|
*/
|
||||||
|
<R> Immutatorable<R> transform(Immutator<? extends R, ? super T> f);
|
||||||
|
}
|
||||||
5
Lab6/cs2030s/fp/Lazy.java
Normal file
5
Lab6/cs2030s/fp/Lazy.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package cs2030s.fp;
|
||||||
|
|
||||||
|
public class Lazy<T> /* implements Immutatorable<T> */ {
|
||||||
|
private Constant<? extends T> init;
|
||||||
|
}
|
||||||
5
Lab6/cs2030s/fp/Memo.java
Normal file
5
Lab6/cs2030s/fp/Memo.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package cs2030s.fp;
|
||||||
|
|
||||||
|
public class Memo<T> extends Lazy<T> {
|
||||||
|
private Actually<T> value;
|
||||||
|
}
|
||||||
1
Lab6/input/Test1.in
Normal file
1
Lab6/input/Test1.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1
|
||||||
1
Lab6/input/Test2.in
Normal file
1
Lab6/input/Test2.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2
|
||||||
1
Lab6/input/Test3.in
Normal file
1
Lab6/input/Test3.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3
|
||||||
1
Lab6/input/Test4.in
Normal file
1
Lab6/input/Test4.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
4
|
||||||
1
Lab6/input/Test5.in
Normal file
1
Lab6/input/Test5.in
Normal file
@@ -0,0 +1 @@
|
|||||||
|
5
|
||||||
6
Lab6/output/Test1.out
Normal file
6
Lab6/output/Test1.out
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
2030
|
||||||
|
CS2030S
|
||||||
|
world!
|
||||||
|
hello
|
||||||
|
world!
|
||||||
|
hello
|
||||||
7
Lab6/output/Test2.out
Normal file
7
Lab6/output/Test2.out
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
2030
|
||||||
|
?
|
||||||
|
CS2030S
|
||||||
|
CS2030S
|
||||||
|
world!
|
||||||
|
hello
|
||||||
|
hello
|
||||||
19
Lab6/output/Test3.out
Normal file
19
Lab6/output/Test3.out
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
123456
|
||||||
|
1
|
||||||
|
?
|
||||||
|
?
|
||||||
|
1
|
||||||
|
123456
|
||||||
|
length
|
||||||
|
6
|
||||||
|
length
|
||||||
|
6
|
||||||
|
length
|
||||||
|
6
|
||||||
|
1010
|
||||||
|
?
|
||||||
|
?
|
||||||
|
2030
|
||||||
|
2020
|
||||||
|
1010
|
||||||
|
/ by zero
|
||||||
23
Lab6/output/Test4.out
Normal file
23
Lab6/output/Test4.out
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
?
|
||||||
|
?
|
||||||
|
?
|
||||||
|
?
|
||||||
|
combine
|
||||||
|
2030
|
||||||
|
20
|
||||||
|
30
|
||||||
|
?
|
||||||
|
?
|
||||||
|
2030 + 0.1
|
||||||
|
2030
|
||||||
|
9
|
||||||
|
8
|
||||||
|
7
|
||||||
|
6
|
||||||
|
5
|
||||||
|
4
|
||||||
|
3
|
||||||
|
2
|
||||||
|
1
|
||||||
|
0
|
||||||
|
1024
|
||||||
6
Lab6/output/Test5.out
Normal file
6
Lab6/output/Test5.out
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
((? | ?) & !(!(?)))
|
||||||
|
((!(?) & !(?)) | !(?))
|
||||||
|
((? | ?) & ?)
|
||||||
|
true
|
||||||
|
((!(t) & !(?)) | !(t))
|
||||||
|
((t | ?) & t)
|
||||||
Reference in New Issue
Block a user