-
Notifications
You must be signed in to change notification settings - Fork 48
Simple Usage of Sandbox
Hu JiaJun edited this page Nov 29, 2020
·
1 revision
import java.util.ArrayList;
import java.util.List;
public class qaTest {
public static void displayResults(List<Boolean> rList) {
int marks = 0;
for (boolean a : rList) {
if (a) {
marks++;
}
}
System.out.printf("You got %d questions correct.%n", marks);
}
public static void main(String[] args) {
List<Boolean> results = new ArrayList<>();
List<QA> questions = new ArrayList<>();
questions.add(new MCQ("What is 1+1?", 'A'));
questions.add(new TFQ("The sky is blue (T/F)", 'T'));
questions.add(new MCQ("Which animal is an elephant?", 'C'));
questions.add(new TFQ("A square is a circle (T/F)", 'F'));
for (QA q : questions) {
Sandbox.make(q)
.map(QA::displayQuestion)
.map(QA::getAnswer)
.consume(results::add);
}
displayResults(results);
}
}
import java.util.Scanner;
abstract class QA {
String question;
char correctAnswer;
public QA(String question, char ans) {
this.question = question;
this.correctAnswer = ans;
}
abstract boolean getAnswer();
public QA displayQuestion() {
System.out.println(this.question);
return this;
}
public char getInput() {
Scanner sc = new Scanner(System.in);
System.out.print("=> ");
char result = sc.next().charAt(0);
System.out.println("");
return result;
}
}
class MCQ extends QA {
public MCQ(String question, char ans) {
super(question, ans);
}
@Override
boolean getAnswer() {
char answer = this.getInput();
if (answer < 'A' || answer > 'E') {
throw new InvalidMCQException("Invalid MCQ answer");
}
return this.correctAnswer == answer;
}
}
class TFQ extends QA {
public TFQ(String question, char ans) {
super(question, ans);
}
@Override
boolean getAnswer() {
char answer = this.getInput();
if (answer != 'T' && answer != 'F') {
throw new InvalidTFQException("Invalid TFQ answer");
}
return this.correctAnswer == answer;
}
}
class InvalidQuestionException extends IllegalArgumentException {
public InvalidQuestionException(String mesg) {
super(mesg);
}
}
class InvalidMCQException extends InvalidQuestionException {
public InvalidMCQException(String mesg) {
super(mesg);
}
}
class InvalidTFQException extends InvalidQuestionException {
public InvalidTFQException(String mesg) {
super(mesg);
}
}
/**
* Class Sandbox is a Functor, and is an immutable class.
* It's purpose is to separate exception handling from the main
* sequence of mapping.
*/
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Consumer;
import java.util.Objects;
public final class Sandbox<T> {
private final T thing;
private final Exception exception;
private Sandbox(T thing, Exception ex) {
this.thing = thing;
this.exception = ex;
}
public T getThing() {
return this.thing;
}
public static <T> Sandbox<T> make(T thing) {
// The instantiated object cannot be null
return new Sandbox<T>(Objects.requireNonNull(thing), null);
}
public static <T> Sandbox<T> makeEmpty() {
return new Sandbox<T>(null, null);
}
public boolean isEmpty() {
return this.thing == null;
}
public boolean hasNoException() {
return this.exception == null;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof Sandbox) {
Sandbox<?> other = (Sandbox<?>) obj;
return this.thing.equals(other.thing) &&
this.exception.equals(other.exception);
}
return false;
}
public <U> Sandbox<U> map(Function<T, U> f) {
return map(f, "");
}
// return new Sandbox Object
public <U> Sandbox<U> map(Function<T, U> f, String errorMessage) {
if (this.isEmpty()) {
return new Sandbox<U>(null, this.exception);
}
try {
U result = f.apply(this.thing);
return new Sandbox<U>(result, null);
}
// If result throws exception, such as unknown command, too many arguments
catch (Exception ex) {
return new Sandbox<U>(null,
new Exception(errorMessage, ex));
}
}
/**
* consume calls the Consumer argument with the thing.
* Exceptions, if any, are handled here.
*/
public void consume(Consumer<T> eat) {
if (this.isEmpty() && !this.hasNoException())
handleException();
if (!this.isEmpty() && this.hasNoException())
eat.accept(this.thing);
}
private void handleException() {
System.err.printf(this.exception.getMessage());
Throwable t = this.exception.getCause();
if (t != null) {
String msg = t.getMessage();
if (msg != null)
System.err.printf(": %s", msg);
}
System.err.println("");
}
public <U> Sandbox<U> flatMap(Function<T, Sandbox<U>> f) {
return flatMap(f, "");
}
public <U> Sandbox<U> flatMap(Function<T, Sandbox<U>> f, String errorMessage) {
if (this.isEmpty()) {
return new Sandbox<U>(null, this.exception);
}
try {
return f.apply(this.thing);
}
// If result throws exception
catch (Exception ex) {
return new Sandbox<U>(null,
new Exception(errorMessage, ex));
}
}
public <U,R> Sandbox<R> combine(Sandbox<U> s,
BiFunction<T,U,R> binOp) {
return this.flatMap(t1 ->
s.map(t2 -> binOp.apply(t1, t2)));
}
}
Peer Learning
Codecrunch Contributions
Piazza Contributions
Wiki Contributions
Guides
Setting Up Checkstyle
Setting Up Java
Setting Up MacVim
Setting Up Sunfire
Setting Up Unix For Mac
Setting Up Unix For Windows
Setting Up Vim
Setting up SSH Config
CS2030 Contents
Lecture 1 SummaryCompile-run vs Run-time Summary
Quick Guide To Abstraction
Generics and Variance of Types
Comparable vs Comparator
Summary of completable future
CS2030S Notes
ELI5 Optional.map vs Optional.flatMap
PECS Example Code
Java Collection Framework (Iterator)
Generic
Generic Type Parameter and Generic Wildcard
Calculator
Lambda-Expression
Single Abstract Method (SAM)
Method Reference
Functional Interfaces 2
Simple Usage of Sandbox
Associative-but-not-commutative
Higher Order function
Functional Programming
Calculator With Functor
Eager Evaluation VS Lazy Evaluation
Simple Usage of Lazy Evaluation
Lazy Evaluation for LazyList
Lazy Evaluation for BinaryTree
Stream
Parallel Stream
Optional
Simple Usage of Stream
Asynchronous Programming
Notes on CompletableFuture
Notes on CompletableFuture 2
Simple Usage of CompletableFuture
Mind Map
Exception Handling
Links
CS2030 Java Style Guide
CS2030 Javadoc Specification
JDK 11 Download Link
JDK 11 API Docs
Codecrunch
Piazza Forum