Last active
November 28, 2020 00:36
-
-
Save RayStarkMC/ddb4ffaacda7ecfe23ad94f55fe71a0b to your computer and use it in GitHub Desktop.
巨大な合成関数を生成した時のスタックオーバーフロー対策
This file contains hidden or 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
package raystark.eflib.function.notnull.composer; | |
import org.jetbrains.annotations.NotNull; | |
import raystark.eflib.function.notnull.NF1; | |
import raystark.eflib.util.OneShotState; | |
import java.util.Deque; | |
import java.util.LinkedList; | |
public final class ComposerNF1<T1, R> { | |
private final Deque<NF1<?, ?>> functions; | |
private final OneShotState state; | |
private ComposerNF1(NF1<? super T1, ? extends R> init) { | |
var functions = new LinkedList<NF1<?, ?>>(); | |
functions.add(init); | |
this.functions = functions; | |
this.state = OneShotState.newInstance(); | |
} | |
private ComposerNF1(Deque<NF1<?, ?>> functions) { | |
this.functions = functions; | |
this.state = OneShotState.newInstance(); | |
} | |
public <V> @NotNull ComposerNF1<T1, V> then(@NotNull NF1<? super R, ? extends V> after) { | |
return state.transitionThrowing( | |
() -> { functions.offerLast(after); return new ComposerNF1<>(functions); }, | |
() -> new IllegalStateException("This composer has already been operated.") | |
); | |
} | |
public <V1> @NotNull ComposerNF1<V1, R> compose1(@NotNull NF1<? super V1, ? extends T1> before) { | |
return state.transitionThrowing( | |
() -> { functions.offerFirst(before); return new ComposerNF1<>(functions); }, | |
() -> new IllegalStateException("This composer has already been operated.") | |
); | |
} | |
public @NotNull NF1<T1, R> compound() { | |
return state.transitionThrowing( | |
() -> new CompoundNF1<>(functions), | |
() -> new IllegalStateException("This composer has already been operated.") | |
); | |
} | |
public static <T1, R> @NotNull ComposerNF1<T1, R> of(@NotNull NF1<? super T1, ? extends R> nf1) { | |
return new ComposerNF1<>(nf1); | |
} | |
public static <T1, R, V> | |
@NotNull ComposerNF1<T1, V> concat(ComposerNF1<? super T1, ? extends R> left, ComposerNF1<? super R, ? extends V> right) { | |
var lefts = left.state.transitionThrowing( | |
() -> left.functions, | |
() -> new IllegalStateException("This composer has already been operated.") | |
); | |
var rights = right.state.transitionThrowing( | |
() -> right.functions, | |
() -> new IllegalStateException("This composer has already been operated.") | |
); | |
lefts.addAll(rights); | |
return new ComposerNF1<>(lefts); | |
} | |
} |
This file contains hidden or 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
package raystark.eflib.function.notnull.composer; | |
import org.jetbrains.annotations.NotNull; | |
import raystark.eflib.function.notnull.NF1; | |
import java.util.Deque; | |
import java.util.Iterator; | |
public class CompoundNF1<T1, R> implements NF1<T1, R> { | |
private final Deque<NF1<?, ?>> functions; | |
CompoundNF1(Deque<NF1<?, ?>> functions) { | |
this.functions = functions; | |
} | |
@Override | |
public @NotNull R apply(@NotNull T1 t1) { | |
Iterator<NF1<?, ?>> iterator = functions.iterator(); | |
Object value = t1; | |
while(iterator.hasNext()) { | |
//functionsはT1 -> T2, T2 -> T3, ... , TN -> Rのように型が連続した関数のリストであるため安全 | |
@SuppressWarnings("unchecked") | |
var function = (NF1<Object, Object>) iterator.next(); | |
value = function.apply(value); | |
} | |
//functionsの最後の関数の型は必ずRであるので安全 | |
@SuppressWarnings("unchecked") | |
var ret = (R) value; | |
return ret; | |
} | |
} |
This file contains hidden or 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
import raystark.eflib.function.notnull.NF1; | |
import raystark.eflib.function.notnull.NF2; | |
import raystark.eflib.function.notnull.composer.ComposerNF1; | |
import java.math.BigInteger; | |
import java.util.stream.Collector; | |
import java.util.stream.Collectors; | |
import java.util.stream.IntStream; | |
public class Debug { | |
public static void main(String[] args) { | |
var foldLeftFrom50 = Collectors2.foldLeft(BigInteger.valueOf(50), BigInteger::subtract); | |
System.out.println(IntStream.rangeClosed(1, 10_000_000).mapToObj(BigInteger::valueOf).collect(foldLeftFrom50)); | |
//System.out.println(IntStream.rangeClosed(1, 10_000_000).boxed().parallel().collect(Collectors2.foldLeft(50, (Integer a, Integer b) -> a - b))); | |
} | |
} | |
/* | |
* foldLeft/foldRight Collector | |
* | |
* Copyright(c) gakuzzzz | |
* | |
* This software is released under the MIT License. | |
* http://opensource.org/licenses/mit-license.php | |
*/ | |
class Collectors2 { | |
public static <T1, T2> Collector<T1, ?, T2> foldRight(final T2 init, final NF2<? super T1, ? super T2, ? extends T2> nf2) { | |
return Collectors.mapping( | |
t1 -> nf2.apply(t1)::apply, | |
Collectors.collectingAndThen( | |
Collectors.<NF1<T2, T2>, ComposerNF1<T2, T2>>reducing( | |
ComposerNF1.of(NF1.identity()), | |
ComposerNF1::of, | |
ComposerNF1::concat | |
), | |
composer -> composer.compound().apply(init) | |
) | |
); | |
} | |
public static <T1, T2> Collector<T1, ?, T2> foldLeft(final T2 init, final NF2<? super T2, ? super T1, ? extends T2> nf2) { | |
return Collectors.mapping( | |
t1 -> nf2.swap2().apply(t1)::apply, | |
Collectors.collectingAndThen( | |
Collectors.<NF1<T2, T2>, ComposerNF1<T2, T2>>reducing( | |
ComposerNF1.of(NF1.identity()), | |
ComposerNF1::of, | |
ComposerNF1::concat | |
), | |
composer -> composer.compound().apply(init) | |
) | |
); | |
} | |
} |
This file contains hidden or 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
package raystark.eflib.util; | |
import org.jetbrains.annotations.NotNull; | |
import raystark.eflib.function.A; | |
import raystark.eflib.function.notnull.NS; | |
import raystark.eflib.option.Option; | |
import raystark.eflib.option.Option.None; | |
import raystark.eflib.option.Option.Some; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
/** | |
* 一度限りの状態遷移をするオートマトンを表すインターフェース。 | |
*/ | |
public interface OneShotState { | |
default boolean isInit() { | |
return !isFinished(); | |
} | |
boolean isFinished(); | |
@NotNull | |
<R> Option<R> transition(@NotNull NS<? extends R> ifInit); | |
default void transition(@NotNull A ifInit) { | |
transition(() -> ifInit).orElse(() -> {}).run(); | |
} | |
@NotNull | |
default <R> R transition(@NotNull NS<? extends R> ifInit, @NotNull NS<? extends R> ifFinished) { | |
return this.<R>transition(ifInit).orElse(ifFinished); | |
} | |
default void transition(@NotNull A ifInit, @NotNull A ifFinished) { | |
transition(() -> ifInit, () -> ifFinished).run(); | |
} | |
default <R, X extends Exception> | |
@NotNull R transitionThrowing(@NotNull NS<? extends R> ifInit, @NotNull NS<? extends X> throwing) throws X { | |
return transition(ifInit).orElseThrow(throwing); | |
} | |
default <X extends Exception> | |
void transitionThrowing(@NotNull A ifInit, @NotNull NS<? extends X> throwing) throws X { | |
transition(() -> ifInit).orElseThrow(throwing).run(); | |
} | |
static @NotNull OneShotState newInstance() { | |
return new OneShotState() { | |
private final AtomicBoolean isFinished = new AtomicBoolean(); | |
@Override | |
public boolean isFinished() { | |
return isFinished.get(); | |
} | |
@Override | |
public @NotNull <R> Option<R> transition(@NotNull NS<? extends R> ifInit) { | |
return checkFinished() ? None.of() : Some.of(ifInit.get()); | |
} | |
private boolean checkFinished() { | |
return isFinished.getAndSet(true); | |
} | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment