package com.googlecode.totallylazy.functions; import com.googlecode.totallylazy.*; import java.util.concurrent.Callable; import static com.googlecode.totallylazy.Pair.pair; public interface Function1<A, B> extends Functor<B> { B call(A a) throws Exception; default B apply(A a) { return Functions.call(this, a); } default Function0<B> deferApply(A a) { return Callables.deferApply(this, a); } default Function0<B> callConcurrently(A a) { return Callers.callConcurrently(deferApply(a)); } default Function1<A, B> lazy() { return Lazy1.lazy(this); } default Function1<A, B> sleep(int millis) { return Sleepy1.sleepy(this, millis); } default Function1<A, Option<B>> optional() { return Exceptions.optional(this); } default Function1<A, Either<Exception, B>> either() { return Exceptions.either(this); } default Function1<A, Either<Exception, B>> orException() { return either(); } default Function1<A, B> orElse(B result) { return Exceptions.orElse(this, result); } @Override default <C> Function1<A, C> map(Function1<? super B, ? extends C> callable) { return Callables.compose(this, callable); } default <C> Function1<A, C> then(Function1<? super B, ? extends C> callable) { return map(callable); } default <C> Function1<A, C> then(Callable<? extends C> callable) { return Callables.compose(this, callable); } default Function1<A, B> interruptable() { return Functions.interruptable(this); } default Function1<A, Function0<B>> deferExecution() { return Callables.deferReturn(this); } default Function1<A, Pair<A, B>> capturing() { return original -> pair(original, Function1.this.apply(original)); } default Function1<A, B> time() { return Time1.time1(this); } default Function1<A, B> time(Function1<? super Number, ?> reporter) { return Time1.time1(this, reporter); } default Option<B> $(Option<? extends A> applicative) { return applicative.applicate(Option.some(this)); } default <L> Either<L, B> $(Either<L, ? extends A> applicative) { return applicative.applicate(Either.<L, Function1<A, B>>right(this)); } default Sequence<B> $(Sequence<? extends A> applicative) { return applicative.applicate(Sequences.one(this)); } }