Skip to content

Instantly share code, notes, and snippets.

@MrAIring
Last active January 23, 2016 12:59
Show Gist options
  • Select an option

  • Save MrAIring/1d635425327dd6aa56fb to your computer and use it in GitHub Desktop.

Select an option

Save MrAIring/1d635425327dd6aa56fb to your computer and use it in GitHub Desktop.
Multiple results in Java
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
public class Result<Ok, Err> {
private Ok ok;
private Err err;
private boolean isOk;
private Result(Ok ok, Err err, boolean isOk){
this.ok = ok;
this.err = err;
this.isOk = isOk;
}
public static <Ok, Err> Result<Ok, Err> ok(Ok ok) {
return new Result<>(ok, null, true);
}
public static <Ok, Err> Result<Ok, Err> err(Err err) {
return new Result<>(null, err, false);
}
public static <Ok, Err> Result<Ok, Err> fromOptional(Optional<Ok> optional, Err err) {
if (optional.isPresent())
return new Result<>(optional.get(), null, true);
else
return new Result<>(null, err, false);
}
public void handle (Consumer<Ok> ifOk, Consumer<Err> ifErr) {
if (isOk)
ifOk.accept(ok);
else
ifErr.accept(err);
}
public <T> T project(Function<Ok, T> mapOk, Function<Err, T> mapError) {
if (isOk)
return mapOk.apply(ok);
else
return mapError.apply(err);
}
public <T, U> Result<T, U> mapAll(Function<Ok, T> mapOk, Function<Err, U> mapError) {
if (isOk)
return ok(mapOk.apply(ok));
else
return err(mapError.apply(err));
}
public Optional<Ok> toOptional() {
if (isOk)
return Optional.ofNullable(ok);
else
return Optional.empty();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Result<?, ?> result = (Result<?, ?>) o;
if (isOk != result.isOk) return false;
if (ok != null ? !ok.equals(result.ok) : result.ok != null) return false;
return !(err != null ? !err.equals(result.err) : result.err != null);
}
@Override
public int hashCode() {
int result = ok != null ? ok.hashCode() : 0;
result = 31 * result + (err != null ? err.hashCode() : 0);
result = 31 * result + (isOk ? 1 : 0);
return result;
}
@Override
public String toString() {
if (isOk)
return "Result(Ok(" + ok + "))";
else
return "Result(Err(" + err + "))";
}
}
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
public class ResultQuadruple<Ok, Err1, Err2, Err3> {
private Ok ok;
private Err1 err1;
private Err2 err2;
private Err3 err3;
private enum Status {
OK, ERR1, ERR2, ERR3
}
private Status status;
public ResultQuadruple(Ok ok, Err1 err1, Err2 err2, Err3 err3, Status status) {
this.ok = ok;
this.err1 = err1;
this.err2 = err2;
this.err3 = err3;
this.status = status;
}
public static <Ok, Err1, Err2, Err3> ResultQuadruple<Ok, Err1, Err2, Err3> ok(Ok ok) {
return new ResultQuadruple<>(ok, null, null, null, Status.OK);
}
public static <Ok, Err1, Err2, Err3> ResultQuadruple<Ok, Err1, Err2, Err3> err1(Err1 err) {
return new ResultQuadruple<>(null, err, null, null, Status.ERR1);
}
public static <Ok, Err1, Err2, Err3> ResultQuadruple<Ok, Err1, Err2, Err3> err2(Err2 err) {
return new ResultQuadruple<>(null, null, err, null, Status.ERR2);
}
public static <Ok, Err1, Err2, Err3> ResultQuadruple<Ok, Err1, Err2, Err3> err3(Err3 err) {
return new ResultQuadruple<>(null, null, null, err, Status.ERR3);
}
public void handle (Consumer<Ok> ifOk, Consumer<Err1> ifErr1, Consumer<Err2> ifErr2, Consumer<Err3> ifErr3) {
switch (status) {
case OK : ifOk.accept(ok); break;
case ERR1: ifErr1.accept(err1); break;
case ERR2: ifErr2.accept(err2); break;
default : ifErr3.accept(err3);
}
}
public <T> T project(Function<Ok, T> mapOk, Function<Err1, T> mapErr1, Function<Err2, T> mapErr2, Function<Err3, T> mapErr3) {
switch (status) {
case OK : return mapOk.apply(ok);
case ERR1: return mapErr1.apply(err1);
case ERR2: return mapErr2.apply(err2);
default : return mapErr3.apply(err3);
}
}
public <T, U, W, X> ResultQuadruple<T, U, W, X> mapAll(Function<Ok, T> mapOk, Function<Err1, U> mapErr1, Function<Err2, W> mapErr2, Function<Err3, X> mapErr3) {
switch (status) {
case OK : return ok(mapOk.apply(ok));
case ERR1: return err1(mapErr1.apply(err1));
case ERR2: return err2(mapErr2.apply(err2));
default : return err3(mapErr3.apply(err3));
}
}
public boolean isOk() {
return status == Status.OK;
}
public boolean isError() {
return status != Status.OK;
}
public boolean isError1() {
return status == Status.ERR1;
}
public boolean isError2() {
return status == Status.ERR2;
}
public boolean isError3() {
return status == Status.ERR3;
}
public Optional<Ok> toOptional() {
if (isOk())
return Optional.ofNullable(ok);
else
return Optional.empty();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ResultQuadruple<?, ?, ?, ?> that = (ResultQuadruple<?, ?, ?, ?>) o;
if (ok != null ? !ok.equals(that.ok) : that.ok != null) return false;
if (err1 != null ? !err1.equals(that.err1) : that.err1 != null) return false;
if (err2 != null ? !err2.equals(that.err2) : that.err2 != null) return false;
if (err3 != null ? !err3.equals(that.err3) : that.err3 != null) return false;
return status == that.status;
}
@Override
public int hashCode() {
int result = ok != null ? ok.hashCode() : 0;
result = 31 * result + (err1 != null ? err1.hashCode() : 0);
result = 31 * result + (err2 != null ? err2.hashCode() : 0);
result = 31 * result + (err3 != null ? err3.hashCode() : 0);
result = 31 * result + status.hashCode();
return result;
}
@Override
public String toString() {
switch (status) {
case OK : return "Result(Ok(" + ok + "))";
case ERR1: return "Result(Err(" + err1 + "))";
case ERR2: return "Result(Err(" + err2 + "))";
default : return "Result(Err(" + err3 + "))";
}
}
}
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
public class ResultTriple<Ok, Err1, Err2> {
private Ok ok;
private Err1 err1;
private Err2 err2;
private enum Status {
OK, ERR1, ERR2
}
private Status status;
private ResultTriple(Ok ok, Err1 err1, Err2 err2, Status status){
this.ok = ok;
this.err1 = err1;
this.err2 = err2;
this.status = status;
}
public static <Ok, Err1, Err2> ResultTriple<Ok, Err1, Err2> ok(Ok ok) {
return new ResultTriple<>(ok, null, null, Status.OK);
}
public static <Ok, Err1, Err2> ResultTriple<Ok, Err1, Err2> err1(Err1 err) {
return new ResultTriple<>(null, err, null, Status.ERR1);
}
public static <Ok, Err1, Err2> ResultTriple<Ok, Err1, Err2> err2(Err2 err) {
return new ResultTriple<>(null, null, err, Status.ERR2);
}
public void handle (Consumer<Ok> ifOk, Consumer<Err1> ifErr1, Consumer<Err2> ifErr2) {
switch (status) {
case OK : ifOk.accept(ok); break;
case ERR1: ifErr1.accept(err1); break;
default : ifErr2.accept(err2);
}
}
public <T> T project(Function<Ok, T> mapOk, Function<Err1, T> mapErr1, Function<Err2, T> mapErr2) {
switch (status) {
case OK : return mapOk.apply(ok);
case ERR1: return mapErr1.apply(err1);
default : return mapErr2.apply(err2);
}
}
public <T, U, W> ResultTriple<T, U, W> mapAll(Function<Ok, T> mapOk, Function<Err1, U> mapErr1, Function<Err2, W> mapErr2) {
switch (status) {
case OK : return ok(mapOk.apply(ok));
case ERR1: return err1(mapErr1.apply(err1));
default : return err2(mapErr2.apply(err2));
}
}
public boolean isOk() {
return status == Status.OK;
}
public boolean isError() {
return status != Status.OK;
}
public boolean isError1() {
return status == Status.ERR1;
}
public boolean isError2() {
return status == Status.ERR2;
}
public Optional<Ok> toOptional() {
if (isOk())
return Optional.ofNullable(ok);
else
return Optional.empty();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ResultTriple<?, ?, ?> that = (ResultTriple<?, ?, ?>) o;
if (ok != null ? !ok.equals(that.ok) : that.ok != null) return false;
if (err1 != null ? !err1.equals(that.err1) : that.err1 != null) return false;
if (err2 != null ? !err2.equals(that.err2) : that.err2 != null) return false;
return status == that.status;
}
@Override
public int hashCode() {
int result = ok != null ? ok.hashCode() : 0;
result = 31 * result + (err1 != null ? err1.hashCode() : 0);
result = 31 * result + (err2 != null ? err2.hashCode() : 0);
result = 31 * result + status.hashCode();
return result;
}
@Override
public String toString() {
if (isOk())
return "Result(Ok(" + ok + "))";
else if (isError1())
return "Result(Err(" + err1 + "))";
else
return "Result(Err(" + err2 + "))";
}
}
Result<InputStream, FileNotFoundException> openFileStream(String filename) {
try {
return Result.ok(new FileInputStream(filename));
} catch (FileNotFoundException e) {
return Result.err(e);
}
}
...
InputStream defaultStream = System.in;
InputStream workWithStream = openFileStream("no such file").project(
stream -> stream,
notFound -> defaultStream
);
openFileStream("no such file").handle(
stream -> workWithStream(inputStream),
err -> System.out.println("Failed to open file " + err.getMessage())
);
openFileStream().toOptional()
.map(stream -> extractInfoFromStream(stream))
.ifPresent(System.out::println);
...
public interface AuthenticationService {
...
ResultTriple<Token, AuthenticationFailed, ServerConnectionFailed> signIn(String login, String password);
}
...
stubFor(postToLoginApi.willReturn(aResponse()
.withFault(Fault.MALFORMED_RESPONSE_CHUNK)));
assertTrue(
authService.signIn("login", "password").project(
token -> false,
authenticationFailed -> false,
serverConnectionFailed -> true)
);
...
boolean isSuccessful = authService.signIn("login", "password").project(
token -> {
assertEquals(token.getTokenString(), "test_token");
assertTrue(authService.isSignedIn());
return true;
},
authenticationFailed -> false,
serverConnectionFailed -> false
);
assertTrue(isSuccessful);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment