Created
May 14, 2015 22:22
-
-
Save danieldietrich/29c9590714719921c30b to your computer and use it in GitHub Desktop.
Match.of(value).when(function).get()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* / \____ _ ______ _____ / \____ ____ _____ | |
* / \__ \/ \ / \__ \ / __// \__ \ / \/ __ \ Javaslang | |
* _/ // _\ \ \/ / _\ \\_ \/ // _\ \ /\ \__/ / Copyright 2014-2015 Daniel Dietrich | |
* /___/ \_____/\____/\_____/____/\___\_____/_/ \_/____/ Licensed under the Apache License, Version 2.0 | |
*/ | |
package javaslang.control; | |
import javaslang.Function1; | |
import java.lang.invoke.MethodType; | |
import java.util.Objects; | |
import java.util.Optional; | |
import java.util.function.Supplier; | |
public interface Match2<T, R> extends Valences.Univalent<R> { | |
<U extends T> Match2<T, R> when(Function1<U, ? extends R> f); | |
static <T> Of<T> of(T value) { | |
return new Of<>(value); | |
} | |
final class Of<T> { | |
private final T value; | |
private Of(T value) { | |
this.value = value; | |
} | |
public <R> Typed<T, R> as(Class<R> type) { | |
Objects.requireNonNull(type, "type is null"); | |
return new Typed<>(value); | |
} | |
@SuppressWarnings("unchecked") | |
public <U extends T, R> Match2<T, R> when(Function1<U, ? extends R> f) { | |
Objects.requireNonNull(f, "f is null"); | |
final MethodType type = f.getType(); | |
return matches(value, type) ? new Matched<>(f.apply((U) value)) : new Unmatched<>(value); | |
} | |
// method declared here because Java 8 does not support private interface methods | |
private static boolean matches(Object obj, MethodType type) { | |
// the compiler may add additional parameters to the lambda, our parameter is the last one | |
final Class<?> parameterType = type.parameterType(type.parameterCount() - 1); | |
return obj != null && parameterType.isAssignableFrom(obj.getClass()); | |
} | |
} | |
final class Typed<T, R> { | |
private final T value; | |
private Typed(T value) { | |
this.value = value; | |
} | |
@SuppressWarnings("unchecked") | |
public <U extends T> Match2<T, R> when(Function1<U, ? extends R> f) { | |
Objects.requireNonNull(f, "f is null"); | |
final MethodType type = f.getType(); | |
return Of.matches(value, type) ? new Matched<>(f.apply((U) value)) : new Unmatched<>(value); | |
} | |
} | |
final class Matched<T, R> implements Match2<T, R> { | |
private final R result; | |
private Matched(R result) { | |
this.result = result; | |
} | |
@Override | |
public <U extends T> Matched<T, R> when(Function1<U, ? extends R> f) { | |
return this; | |
} | |
@Override | |
public R get() { | |
return result; | |
} | |
@Override | |
public R orElse(R other) { | |
return result; | |
} | |
@Override | |
public R orElseGet(Supplier<? extends R> other) { | |
return result; | |
} | |
@Override | |
public <X extends Throwable> R orElseThrow(Supplier<X> exceptionSupplier) throws X { | |
return result; | |
} | |
@Override | |
public Option<R> toOption() { | |
return new Some<>(result); | |
} | |
@Override | |
public Optional<R> toJavaOptional() { | |
return Optional.ofNullable(result); // caution: may be empty if result is null | |
} | |
} | |
final class Unmatched<T, R> implements Match2<T, R> { | |
private final T value; | |
private Unmatched(T value) { | |
this.value = value; | |
} | |
@SuppressWarnings("unchecked") | |
@Override | |
public <U extends T> Match2<T, R> when(Function1<U, ? extends R> f) { | |
final MethodType type = f.getType(); | |
return Of.matches(value, type) ? new Matched<>(f.apply((U) value)) : this; | |
} | |
@Override | |
public R get() { | |
throw new MatchError(value); | |
} | |
@Override | |
public R orElse(R other) { | |
return other; | |
} | |
@Override | |
public R orElseGet(Supplier<? extends R> other) { | |
return other.get(); | |
} | |
@Override | |
public <X extends Throwable> R orElseThrow(Supplier<X> exceptionSupplier) throws X { | |
throw exceptionSupplier.get(); | |
} | |
@Override | |
public Option<R> toOption() { | |
return None.instance(); | |
} | |
@Override | |
public Optional<R> toJavaOptional() { | |
return Optional.empty(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment