diff --git a/common/addons/command-locate/src/main/java/com/dfsek/terra/addons/commands/locate/BiomeLocator.java b/common/addons/command-locate/src/main/java/com/dfsek/terra/addons/commands/locate/BiomeLocator.java index 3655d3266..fb6ba483c 100644 --- a/common/addons/command-locate/src/main/java/com/dfsek/terra/addons/commands/locate/BiomeLocator.java +++ b/common/addons/command-locate/src/main/java/com/dfsek/terra/addons/commands/locate/BiomeLocator.java @@ -16,6 +16,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.IntStream; import java.util.stream.Stream; +import static com.dfsek.terra.api.util.function.FunctionUtils.*; public class BiomeLocator { @@ -76,7 +77,7 @@ public class BiomeLocator { .mapToObj(z -> new int[]{ minX, z }); // Fixed X (min), varying Z Optional> ringResult = Stream.of(northSide, eastSide, southSide, westSide) - .flatMap(Function.identity()) + .flatMap(identity()) .parallel() .map(coords -> check( provider, @@ -93,10 +94,10 @@ public class BiomeLocator { .findFirst(); // findFirst() respects encounter order (North -> East -> South -> West) if(ringResult.isPresent()) { - return Maybe.fromOptional(ringResult); + return fromOptional(ringResult); } } - return Maybe.nothing(); + return nothing(); }); } @@ -120,16 +121,16 @@ public class BiomeLocator { // Iterate from bottom to top of the world using the step for(int y = minHeight; y < maxHeight; y += step) { if(filter.test(provider.getBiome(x, y, z, seed))) { - return Maybe.just(Either.left(Vector3Int.of(x, y, z))); + return just(left(Vector3Int.of(x, y, z))); } } - return Maybe.nothing(); + return nothing(); } else { // 2D Mode: Check only the base biome // We use a flatMap approach here to be safe with Optionals inside the stream return provider.getBaseBiome(x, z, seed) .filter(filter) - .map(b -> Either.right(Vector2Int.of(x, z))); + .map(b -> right(Vector2Int.of(x, z))); } } } \ No newline at end of file diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/Registry.java b/common/api/src/main/java/com/dfsek/terra/api/registry/Registry.java index accdb945e..61c357c31 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/registry/Registry.java +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/Registry.java @@ -29,6 +29,7 @@ import java.util.function.Function; import com.dfsek.terra.api.registry.key.RegistryKey; import com.dfsek.terra.api.util.reflection.TypeKey; +import static com.dfsek.terra.api.util.function.FunctionUtils.*; public interface Registry extends TypeLoader { @@ -96,11 +97,11 @@ public interface Registry extends TypeLoader { default Either getByID(String id) { return getByID(id, map -> { - if(map.isEmpty()) return Either.left(new NoSuchElement("No such value \"" + id + "\"")); + if(map.isEmpty()) return left(new NoSuchElement("No such value \"" + id + "\"")); if(map.size() == 1) { - return Either.right(map.values().stream().findFirst().get()); // only one value. + return right(map.values().stream().findFirst().get()); // only one value. } - return Either.left(new AmbiguousKey("ID \"" + id + "\" is ambiguous; matches: " + map + return left(new AmbiguousKey("ID \"" + id + "\" is ambiguous; matches: " + map .keySet() .stream() .map(RegistryKey::toString) diff --git a/common/api/src/main/java/com/dfsek/terra/api/registry/key/RegistryKey.java b/common/api/src/main/java/com/dfsek/terra/api/registry/key/RegistryKey.java index 65049fbd3..c9af65910 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/registry/key/RegistryKey.java +++ b/common/api/src/main/java/com/dfsek/terra/api/registry/key/RegistryKey.java @@ -4,6 +4,7 @@ import com.dfsek.terra.api.error.Invalid; import com.dfsek.terra.api.error.InvalidKey; import com.dfsek.terra.api.util.generic.data.types.Either; import com.dfsek.terra.api.util.generic.data.types.Maybe; +import static com.dfsek.terra.api.util.function.FunctionUtils.*; import java.util.Objects; import java.util.regex.Pattern; @@ -33,12 +34,12 @@ public final class RegistryKey implements StringIdentifiable, Namespaced { public static Either parse(String key) { if(key.chars().filter(c -> c == ':').count() != 1) { - return Either.left(new InvalidKey("Malformed RegistryKey: " + key)); + return left(new InvalidKey("Malformed RegistryKey: " + key)); } String namespace = key.substring(0, key.indexOf(":")); String id = key.substring(key.indexOf(":") + 1); - return Either.right(new RegistryKey(namespace, id)); + return right(new RegistryKey(namespace, id)); } public static RegistryKey of(String namespace, String id) { diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/function/FunctionUtils.java b/common/api/src/main/java/com/dfsek/terra/api/util/function/FunctionUtils.java index 795f136d1..cc04fa506 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/function/FunctionUtils.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/function/FunctionUtils.java @@ -2,12 +2,14 @@ package com.dfsek.terra.api.util.function; import com.dfsek.terra.api.util.generic.data.types.Either; +import com.dfsek.terra.api.util.generic.data.types.Maybe; import com.dfsek.terra.api.util.generic.data.types.Pair; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import java.util.Objects; +import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; @@ -17,6 +19,30 @@ import java.util.function.Supplier; public final class FunctionUtils { private FunctionUtils() { } + public static Function identity() { + return Function.identity(); + } + + public static Maybe just(T t) { + return Maybe.just(t); + } + + public static Maybe nothing() { + return Maybe.nothing(); + } + + public static Either left(L l) { + return Either.left(l); + } + + public static Either right(R r) { + return Either.right(r); + } + + public static Maybe fromOptional(Optional op) { + return Maybe.fromOptional(op); + } + @Contract("_ -> new") public static @NotNull Function lift(@NotNull Consumer c) { Objects.requireNonNull(c); @@ -26,6 +52,17 @@ public final class FunctionUtils { }; } + @Contract("_ -> new") + public static @NotNull Function lift(@NotNull Supplier c) { + Objects.requireNonNull(c); + return co -> c.get(); + } + + @Contract("_ -> new") + public static @NotNull Function lift(@NotNull R c) { + return lift(() -> c); + } + @Contract("_ -> fail") public static @NotNull U throw_(@NotNull T e) throws T { throw e; diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java index 7a60c1713..b95c29bc9 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/data/types/Either.java @@ -7,8 +7,6 @@ package com.dfsek.terra.api.util.generic.data.types; -import com.dfsek.terra.api.util.function.FunctionUtils; - import com.dfsek.terra.api.util.generic.control.Monad; import com.dfsek.terra.api.util.generic.data.BiFunctor; @@ -20,28 +18,29 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; +import static com.dfsek.terra.api.util.function.FunctionUtils.*; public sealed interface Either extends Monad>, BiFunctor> { static T collapse(Either either) { - return either.collect(Function.identity(), Function.identity()); + return either.collect(identity(), identity()); } @SuppressWarnings("unchecked") static Either toEither(Optional o, L de) { - return (Either) o.map(Either::right).orElseGet(() -> left(de)); + return (Either) o.map(Either::right).orElseGet(() -> Either.left(de)); } @NotNull @Contract("_ -> this") default Either ifLeft(@NotNull Consumer action) { - return mapLeft(FunctionUtils.lift(action)); + return mapLeft(lift(action)); } @NotNull @Contract("_ -> this") default Either ifRight(@NotNull Consumer action) { - return mapRight(FunctionUtils.lift(action)); + return mapRight(lift(action)); } // Either is a functor in its right parameter. @@ -52,7 +51,7 @@ public sealed interface Either extends Monad>, BiFunctor @NotNull Either pure(@NotNull T1 t) { - return right(t); + return Either.right(t); } @Override @@ -64,13 +63,27 @@ public sealed interface Either extends Monad>, BiFunctor @NotNull Either mapRight(@NotNull Function f); - Maybe getLeft(); + @Override + @NotNull + default Either bimap(@NotNull Function left, @NotNull Function right) { + return (Either) BiFunctor.super.bimap(left, right); + } - Maybe getRight(); + default Maybe getLeft() { + return collapse(bimap(Maybe::just, lift(Maybe::nothing))); + } - boolean isLeft(); + default Maybe getRight() { + return collapse(bimap(lift(Maybe::nothing), Maybe::just)); + } - boolean isRight(); + default boolean isLeft() { + return collapse(bimap(lift(true), lift(false))); + } + + default boolean isRight() { + return collapse(bimap(lift(false), lift(true))); + } Either flip(); @@ -88,7 +101,7 @@ public sealed interface Either extends Monad>, BiFunctor R collectThrow(Function left) throws T { - return mapLeft(left).collect(l -> FunctionUtils.sneakyThrow(l), Function.identity()); + return mapLeft(left).collect(l -> sneakyThrow(l), identity()); } @NotNull @@ -122,29 +135,9 @@ public sealed interface Either extends Monad>, BiFunctor) this; } - @Override - public Maybe getLeft() { - return Maybe.just(value); - } - - @Override - public Maybe getRight() { - return Maybe.nothing(); - } - - @Override - public boolean isLeft() { - return true; - } - - @Override - public boolean isRight() { - return false; - } - @Override public Either flip() { - return right(value); + return Either.right(value); } @Override @@ -171,29 +164,9 @@ public sealed interface Either extends Monad>, BiFunctor(f.apply(value)); } - @Override - public Maybe getLeft() { - return Maybe.nothing(); - } - - @Override - public Maybe getRight() { - return Maybe.just(value); - } - - @Override - public boolean isLeft() { - return false; - } - - @Override - public boolean isRight() { - return true; - } - @Override public Either flip() { - return left(value); + return Either.left(value); } @Override