2013-05-31 9 views
11

के साथ शून्य-सुरक्षित विधि श्रृंखला, गुवा का Optional पैटर्न बहुत अच्छा है, क्योंकि यह अस्पष्टता को शून्य के साथ हटाने में मदद करता है। transform विधि शून्य-सुरक्षित विधि श्रृंखला बनाने के लिए बहुत उपयोगी है जब श्रृंखला का पहला भाग अनुपस्थित हो सकता है, लेकिन उपयोगी नहीं है जब श्रृंखला के अन्य भाग अनुपस्थित हैं।वैकल्पिक

यह प्रश्न Guava Optional type, when transformation returns another Optional से संबंधित है, जो अनिवार्य रूप से एक ही प्रश्न पूछता है लेकिन एक अलग उपयोग मामले के लिए जो मुझे लगता है कि Optional (हैंडलिंग त्रुटियों) का इच्छित उपयोग नहीं हो सकता है।

एक विधि Optional<Book> findBook(String id) पर विचार करें। findBook(id).transform(Book.getName) अपेक्षित के रूप में काम करता है। यदि कोई पुस्तक नहीं मिली है तो हमें Absent<String> मिल जाएगा, यदि कोई पुस्तक मिली है तो हमें Present<String> मिल जाएगा।

सामान्य मामले में जहां इंटरमीडिएट विधियां null/absent() वापस आ सकती हैं, कॉल को श्रृंखलाबद्ध करने का एक शानदार तरीका प्रतीत नहीं होता है। उदाहरण के लिए, मान लें कि Book में एक विधि Optional<Publisher> getPublisher() है, और हम एक पुस्तक के प्रकाशक द्वारा प्रकाशित सभी पुस्तकें प्राप्त करना चाहते हैं। प्राकृतिक वाक्यविन्यास findBook(id).transform(Book.getPublisher).transform(Publisher.getPublishedBooks) प्रतीत होता है, हालांकि यह विफल हो जाएगा क्योंकि transform(Publisher.getPublishedBooks) कॉल वास्तव में Optional<Optional<Publisher>> लौटाएगा।

पर Optional पर विधि के समान उचित लगता है जो Optional पर एक फ़ंक्शन स्वीकार करेगा। यह वर्तमान कार्यान्वयन की तरह कार्य करेगा, सिवाय इसके कि यह केवल वैकल्पिक रूप से फ़ंक्शन के परिणाम को लपेट नहीं देगा। (Present के लिए) कार्यान्वयन पढ़ सकता है:

public abstract <V> Optional<V> optionalTransform(Function<? super T, Optional<V>> function) { 
    return function.apply(reference); 
} 

Absent के लिए कार्यान्वयन transform से अपरिवर्तित है:

public abstract <V> Optional<V> optionalTransform(Function<? super T, Optional<V>> function) { 
    checkNotNull(function); 
    return Optional.absent(); 
} 

यह भी अच्छा होगा यदि वहाँ एक रास्ता तरीकों कि वापसी null को संभालने के लिए के रूप में विरोध किया थीं या नहीं विरासत वस्तुओं के साथ काम करने के लिए Optional पर। इस तरह की एक विधि transform की तरह होगी लेकिन फ़ंक्शन के परिणामस्वरूप बस Optional.fromNullable पर कॉल करें।

मैं उत्सुक हूं कि किसी और ने इस त्रासदी में भाग लिया है और अच्छे कामकाज पाए हैं (जिसमें आपकी Optional कक्षा लिखना शामिल नहीं है)। मुझे गुवा टीम से भी सुनना अच्छा लगेगा या इस मुद्दे से संबंधित चर्चाओं की ओर इशारा किया जाएगा (मुझे मेरी खोज में कोई नहीं मिला)।

+0

क्या आपने [चर्चा समूह] (https://groups.google.com/forum/#!forum/guava-discuss) की कोशिश की है? यहां पोस्ट करने पर विचार करें, भले ही यह इस (अच्छी तरह से लिखित) प्रश्न को इंगित करें। इस प्रश्न के लिए –

उत्तर

0

आप शायद लगा कि बाहर है, लेकिन आप (.transform(Book.getPublisher के बाद अपने मामले में) हर परिवर्तन है कि Optional रिटर्न के बाद .or(Optional.absent) जोड़ सकता है कम करने Optional<Optional<T>>Optional<T> रहे हैं:

Optional<List<Book>> publishedBooks = findBook(id).transform(Book.getPublisher). 
     or(Optional.absent()).transform(Publisher.getPublishedBooks); 

दुर्भाग्य से, Optional.absent के प्रकार के यहाँ नहीं लगाया जा सकता , इसलिए कोड वास्तव में बन जाता है:

Optional<List<Book>> publishedBooks = book.transform(Book.getPublisher). 
     or(Optional.<Publisher> absent()).transform(Publisher.getPublishedBoooks); 

बहुत सुविधाजनक नहीं है लेकिन ऐसा कोई अन्य तरीका प्रतीत नहीं होता है।

10

आप कुछ मोनाड की तलाश में हैं, लेकिन अमरूद के वैकल्पिक (उदाहरण के लिए स्कैला के विकल्प के विपरीत) केवल एक फंक्टर है।

फ़ैक्टर क्या है ?!

फ़ैक्टर और मोनाड एक प्रकार का बॉक्स है, एक संदर्भ जो कुछ मूल्य लपेटता है। फ़ंक्शन जिसमें टाइप ए के कुछ मान होते हैं, जानता है कि फ़ंक्शन ए => बी कैसे लागू करें और परिणाम को फ़ंक्शन में वापस रखें। उदाहरण के लिए: वैकल्पिक, ट्रांसफॉर्म, और वैकल्पिक में वापस लपेटें। कार्यात्मक प्रोग्रामिंग भाषाओं में ऐसी विधि को अक्सर 'मानचित्र' नाम दिया जाता है।

मोना .. क्या?

मोनाड फंक्टर के समान ही है, सिवाय इसके कि यह मोनाड (ए => मोनाड, उदाहरण के लिए Int => वैकल्पिक) में लिपटे फ़ंक्शन रिटर्निंग मूल्य का उपभोग करता है। यह जादू मोनाड की विधि को अक्सर 'फ्लैटमैप' कहा जाता है।

यहाँ आप मौलिक एफपी शब्दों के लिए सचमुच कमाल स्पष्टीकरण प्राप्त कर सकते: http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html

functors & monads आ रहे हैं!

जावा 8 से वैकल्पिक दोनों फंक्टर (http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#map-java.util.function.Function-) और मोनाड (http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#flatMap-java.util.function.Function-) के रूप में वर्गीकृत किया जा सकता है।

अच्छा मोन (विज्ञापन) ओलॉग, मार्किन, लेकिन मैं अपनी विशेष समस्या को कैसे हल कर सकता हूं?

मैं वर्तमान में जावा 6 का उपयोग करने वाली एक परियोजना पर काम कर रहा हूं और कल मैं 'वैकल्पिक' नामक कुछ सहायक वर्ग लिखता हूं, जिसने मुझे बहुत समय बचाया।

यह कुछ सहायक विधि प्रदान करता है, जो मुझे वैकल्पिक रूप से मोनाड्स (फ्लैटमैप) में बदलने की अनुमति देता है।

यहाँ कोड है: https://gist.github.com/mkubala/046ae20946411f80ac52

क्योंकि अपने प्रोजेक्ट के codebase अभी भी एक वापसी मान के रूप में nulls का उपयोग करता है, मैं Optionals.lift (फंक्शन) है, जो वैकल्पिक में परिणाम लपेटकर करने के लिए इस्तेमाल किया जा सकता की शुरुआत की।

परिणाम को वैकल्पिक में क्यों उठाया जा रहा है? स्थिति से बचने के लिए जब परिवर्तन में पारित किया गया कार्य शून्य हो सकता है और पूरी अभिव्यक्ति इस पोस्टकंडिशन की वजह से "नल का वर्तमान" (जिस तरह से गुवा के वैकल्पिक के साथ संभव नहीं है,>>https://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/base/Present.java?r=0823847e96b1d082e94f06327cf218e418fe2228#71 की पंक्ति # 71 देखें)।

उदाहरण के युगल

मान लेते हैं कि findEntity() रिटर्न एक वैकल्पिक और Entity.getDecimalField (..) वापस आ सकते हैं BigDecimal या अशक्त करते हैं:

Optional<BigDecimal> maybeDecimalValue = Optionals.flatMap(
    findEntity(), 
    new Function<Entity, Optional<BigDecimal>>() { 
     @Override 
     public Optional<BigDecimal> apply(Entity input) { 
      return Optional.fromNullable(input.getDecimalField(..)); 
     } 
    } 
); 

फिर भी एक और उदाहरण है कि मैं यह सोचते हैं पहले से ही कुछ फ़ंक्शन है, जो इकाइयों से दशमलव मान निकालता है, और शून्य वापस कर सकता है:

Function<Entity, Decimal> extractDecimal = .. // extracts decimal value or null 
Optional<BigDecimal> maybeDecimalValue = Optionals.flatMap(
    findEntity(), 
    Optionals.lift(extractDecimal) 
); 

और लास टी, लेकिन कम से कम नहीं - उदाहरण के रूप में आपका उपयोग केस:

Optional<Publisher> maybePublisher = Optionals.flatMap(findBook(id), Optionals.lift(Book.getPublisher)); 

// Assuming that getPublishedBooks may return null.. 
Optional<List<Book>> maybePublishedBooks = Optionals.flatMap(maybePublisher, Optionals.lift(Publisher.getPublishedBooks)); 

// ..or simpler, in case when getPublishedBooks never returns null 
Optional<List<Book>> maybePublishedBooks2 = maybePublisher.transform(Publisher.getPublishedBooks); 

// as a one-liner: 
Optionals.flatMap(maybePublisher, Optionals.lift(Publisher.getPublishedBooks)).transform(Publisher.getPublishedBooks); 
+0

ओवरकिल, लेकिन अच्छी पढ़ाई! – orbfish

संबंधित मुद्दे