जैसे java.util.Optional<T>जावा 8, स्काला के Option[T]प्रकार के बराबर (कुछ) है , क्या स्काला के समकक्ष है Either[L, R]?
java.lang.Object ... दुखी।
जैसे java.util.Optional<T>जावा 8, स्काला के Option[T]प्रकार के बराबर (कुछ) है , क्या स्काला के समकक्ष है Either[L, R]?
java.lang.Object ... दुखी।
जवाबों:
कोई भी Eitherप्रकार जावा 8 नहीं है, इसलिए आपको खुद को बनाने या किसी तीसरे पक्ष के पुस्तकालय का उपयोग करने की आवश्यकता है।
आप नए Optionalप्रकार का उपयोग करके ऐसी सुविधा का निर्माण कर सकते हैं (लेकिन इस उत्तर के अंत में पढ़ें):
final class Either<L,R>
{
public static <L,R> Either<L,R> left(L value) {
return new Either<>(Optional.of(value), Optional.empty());
}
public static <L,R> Either<L,R> right(R value) {
return new Either<>(Optional.empty(), Optional.of(value));
}
private final Optional<L> left;
private final Optional<R> right;
private Either(Optional<L> l, Optional<R> r) {
left=l;
right=r;
}
public <T> T map(
Function<? super L, ? extends T> lFunc,
Function<? super R, ? extends T> rFunc)
{
return left.<T>map(lFunc).orElseGet(()->right.map(rFunc).get());
}
public <T> Either<T,R> mapLeft(Function<? super L, ? extends T> lFunc)
{
return new Either<>(left.map(lFunc),right);
}
public <T> Either<L,T> mapRight(Function<? super R, ? extends T> rFunc)
{
return new Either<>(left, right.map(rFunc));
}
public void apply(Consumer<? super L> lFunc, Consumer<? super R> rFunc)
{
left.ifPresent(lFunc);
right.ifPresent(rFunc);
}
}
उदाहरण उपयोग मामला:
new Random().ints(20, 0, 2).mapToObj(i -> (Either<String,Integer>)(i==0?
Either.left("left value (String)"):
Either.right(42)))
.forEach(either->either.apply(
left ->{ System.out.println("received left value: "+left.substring(11));},
right->{ System.out.println("received right value: 0x"+Integer.toHexString(right));}
));
पूर्वव्यापी में, Optionalआधारित समाधान एक शैक्षणिक उदाहरण की तरह है, लेकिन अनुशंसित दृष्टिकोण नहीं है। एक समस्या null"खाली" के रूप में है जो "या तो" के अर्थ का विरोध करती है।
निम्न कोड दिखाता है Eitherकि nullएक संभावित मूल्य पर विचार करता है, इसलिए यह कड़ाई से "या तो", बाएं या दाएं, भले ही मूल्य है null:
abstract class Either<L,R>
{
public static <L,R> Either<L,R> left(L value) {
return new Either<L,R>() {
@Override public <T> T map(Function<? super L, ? extends T> lFunc,
Function<? super R, ? extends T> rFunc) {
return lFunc.apply(value);
}
};
}
public static <L,R> Either<L,R> right(R value) {
return new Either<L,R>() {
@Override public <T> T map(Function<? super L, ? extends T> lFunc,
Function<? super R, ? extends T> rFunc) {
return rFunc.apply(value);
}
};
}
private Either() {}
public abstract <T> T map(
Function<? super L, ? extends T> lFunc, Function<? super R, ? extends T> rFunc);
public <T> Either<T,R> mapLeft(Function<? super L, ? extends T> lFunc) {
return this.<Either<T,R>>map(t -> left(lFunc.apply(t)), t -> (Either<T,R>)this);
}
public <T> Either<L,T> mapRight(Function<? super R, ? extends T> lFunc) {
return this.<Either<L,T>>map(t -> (Either<L,T>)this, t -> right(lFunc.apply(t)));
}
public void apply(Consumer<? super L> lFunc, Consumer<? super R> rFunc) {
map(consume(lFunc), consume(rFunc));
}
private <T> Function<T,Void> consume(Consumer<T> c) {
return t -> { c.accept(t); return null; };
}
}
दोनों फैक्ट्री के तरीकों की शुरुआत में nullकेवल एक सख्त अस्वीकृति के साथ इसे बदलना आसान है Objects.requireNonNull(value)। इसी तरह, खाली के लिए समर्थन जोड़ना या तो कल्पना करना उचित होगा।
Either, तो टाइप कुछ अर्थ में "बहुत बड़ा" है, क्योंकि आपके leftऔर rightक्षेत्र दोनों सिद्धांत में खाली हो सकते हैं या दोनों को परिभाषित किया जा सकता है। आपने उन कंस्ट्रक्टरों को छिपा दिया है जो ऐसा संभव कर सकते हैं, लेकिन दृष्टिकोण अभी भी आपके कार्यान्वयन में बग के लिए संभावित है। सरल प्रकार के अंकगणितीय शब्दों में, आप a + bबाहर निकलने की कोशिश कर रहे हैं (1 + a) * (1 + b)। ज़रूर, a + bउस अभिव्यक्ति के परिणाम में होता है, लेकिन ऐसा है 1और a * b।
intसंपूर्ण मान श्रेणी का intउपयोग करते हुए लगभग हर उपयोग के मामले के लिए एक नई "मान्य श्रेणी" प्रकार का आविष्कार करना होगा int। आखिरकार, Optionalएक ही करता है, वस्तु निर्माण के दौरान आक्रमणकारियों को लागू करना।
Either.left(42).map(left -> null, right -> right)फेंकता है । इसके अलावा, एक व्यक्ति प्रवर्तन प्रवर्तन को दरकिनार कर सकता है और उत्पादन कर सकता है । या जब एक साथ रखा जाता है, तो फिर से असफल हो जाता है । NoSuchElementExceptionthis.right.get()Either<empty, empty>Either.left(42).mapLeft(left -> null)Either.left(42).mapLeft(left -> null).map(left -> left, right -> right)
Optional.mapफ़ंक्शन को वापस लौटने की अनुमति देता है null, इसे खाली कर देता है Optional। हालांकि, इसका पता लगाने और तुरंत फेंकने के अवसर के अलावा, मुझे कोई भी वैकल्पिक समाधान नहीं दिखता है जो "अधिक सही" हो। अफाक, कोई संदर्भ व्यवहार नहीं है, जैसा कि स्काला में है, आप उसका नक्शा नहीं बना सकते null...
Rightकोड पथ को एक Leftउदाहरण के लिए निष्पादित किया जाए , भले ही त्रुटि समान हो। और हाँ, मैं अभी प्राप्त करने <empty, empty>और बाद में विफल होने के बजाय तुरंत विफल होना पसंद करूंगा । लेकिन फिर, यह सब सिर्फ एक स्वाद / शैली की बात है।
एटलसियन फुगे देखें । वहां का अच्छा कार्यान्वयन है Either।
जावा मानक पुस्तकालय में कोई भी नहीं है। लेकिन वहाँ के एक कार्यान्वयन है या तो में FunctionalJava , कई अन्य अच्छा कक्षाओं के साथ।
साइक्लोप्स-रिएक्शन में एक 'सही' पक्षपाती या तो कार्यान्वयन है जिसे एक्सोर कहा जाता है ।
Xor.primary("hello")
.map(s->s+" world")
//Primary["hello world"]
Xor.secondary("hello")
.map(s->s+" world")
//Secondary["hello"]
Xor.secondary("hello")
.swap()
.map(s->s+" world")
//Primary["hello world"]
Xor.accumulateSecondary(ListX.of(Xor.secondary("failed1"),
Xor.secondary("failed2"),
Xor.primary("success")),
Semigroups.stringConcat)
//failed1failed2
एक संबंधित प्रकार Ior भी है जो या तो tuple2 के रूप में कार्य कर सकता है।
Xorथा नाम दिया करने के लिए Either: साइक्लोप्स एक्स में static.javadoc.io/com.oath.cyclops/cyclops/10.0.0-FINAL/cyclops/...
नहीं, कोई नहीं है।
जावा भाषा डेवलपर्स स्पष्ट रूप से बताते हैं कि जैसे प्रकार का Option<T>उपयोग केवल अस्थायी मूल्यों के रूप में किया जाता है (उदाहरण के लिए स्ट्रीम संचालन परिणाम), इसलिए जब वे अन्य भाषाओं की तरह ही होते हैं, तो उनका उपयोग नहीं किया जाता है क्योंकि वे अन्य में उपयोग किए जाते हैं भाषाएँ। इसलिए यह आश्चर्य की बात नहीं है कि ऐसा कुछ भी नहीं है Eitherक्योंकि यह स्वाभाविक रूप से उत्पन्न नहीं होता है (जैसे धारा संचालन से) Optional।
Eitherस्वाभाविक रूप से पैदा होता है। शायद मैं गलत कर रहा हूं। जब कोई विधि दो अलग-अलग चीजों को वापस कर सकती है तो आप क्या करते हैं? की तरह Either<List<String>, SomeOtherClass>?
Eitherएक छोटे से पुस्तकालय में एक अकेला कार्यान्वयन है , "महत्वाकांक्षा": http://github.com/poetix/ambivalence
आप इसे मावेन केंद्रीय से प्राप्त कर सकते हैं:
<dependency>
<groupId>com.codepoetics</groupId>
<artifactId>ambivalence</artifactId>
<version>0.2</version>
</dependency>
लैम्ब्डा-साथी का एक Eitherप्रकार है (और कुछ अन्य कार्यात्मक प्रकार जैसे Try)
<dependency>
<groupId>no.finn.lambda</groupId>
<artifactId>lambda-companion</artifactId>
<version>0.25</version>
</dependency>
इसका उपयोग करना आसान है:
final String myValue = Either.right("example").fold(failure -> handleFailure(failure), Function.identity())