15

ठीक है, अब धोखा नहीं है।कार्यात्मक क्लोजर या अनिवार्य ग्रोवी अधिक पठनीय है?

नहीं, वास्तव में, एक या दो मिनट लें और इसे आजमाएं।

"पदों" क्या करता है?

संपादित करें: cgrand के सुझाव के अनुसार सरलीकृत।

(defn redux [[current next] flag] [(if flag current next) (inc next)]) 

(defn positions [coll] 
    (map first (reductions redux [1 2] (map = coll (rest coll))))) 

अब, इस संस्करण के बारे में कैसे?

def positions(coll) { 
    def (current, next) = [1, 1] 
    def previous = coll[0] 
    coll.collect { 
    current = (it == previous) ? current : next 
    next++ 
    previous = it 
    current 
    } 
} 

मैं Clojure सीख रहा हूँ और मैं इसे प्यार कर रहा हूँ, क्योंकि मैं हमेशा कार्यात्मक प्रोग्रामिंग का आनंद लिया। मुझे क्लोजर समाधान के साथ आने में लंबा समय लगा, लेकिन मुझे को एक सुरुचिपूर्ण समाधान के पर विचार करना पड़ा। ग्रोवी समाधान ठीक है, लेकिन मैं उस बिंदु पर हूं जहां मुझे इस प्रकार के अनिवार्य प्रोग्रामिंग उबाऊ और मैकेनिकल मिलते हैं। जावा के 12 साल बाद, मुझे क्लोजर के साथ एक रट और कार्यात्मक प्रोग्रामिंग में महसूस होता है जो मुझे चाहिए।

ठीक है, बिंदु पर जाएं। खैर, मुझे ईमानदार होना है और कहना है कि मुझे आश्चर्य है कि अगर मैं क्लोजर कोड को समझूंगा तो मैं महीनों बाद वापस जाऊंगा। निश्चित रूप से मैं इसे बिल्ली से बाहर टिप्पणी कर सकता हूं, लेकिन मुझे इसे समझने के लिए अपने जावा कोड पर टिप्पणी करने की आवश्यकता नहीं है।

तो मेरा सवाल यह है: क्या यह कार्यात्मक प्रोग्रामिंग पैटर्न के लिए और अधिक उपयोग करने का सवाल है? क्या कार्यात्मक प्रोग्रामिंग गुरु इस कोड को पढ़ रहे हैं और इसे समझने के लिए हवा ढूंढ रहे हैं? कौन सा संस्करण आपको समझने में आसान लगता है?

संपादित करें: यह कोड क्या करता है खिलाड़ियों की स्थिति की गणना उनके बिंदुओं के अनुसार करते हैं, जबकि बंधे लोगों का ट्रैक रखें। उदाहरण के लिए:


Pos Points 
1. 36 
1. 36 
1. 36 
4. 34 
5. 32 
5. 32 
5. 32 
8. 30 

उत्तर

23

मुझे नहीं लगता कि आंतरिक पठनीयता जैसी कोई चीज है। वहां आप का उपयोग किया जाता है, और जिसका उपयोग आप नहीं करते हैं। मैं आपके कोड के दोनों संस्करणों को ठीक से पढ़ने में सक्षम था। मैं वास्तव में आपके ग्रोवी संस्करण को अधिक आसानी से पढ़ सकता हूं, भले ही मुझे ग्रोवी नहीं पता, क्योंकि मैंने सी और जावा को देखकर एक दशक बिताया और केवल एक वर्ष क्लोजर को देख रहा था। यह भाषाओं के बारे में कुछ भी नहीं कहता है, यह केवल मेरे बारे में कुछ कहता है।

इसी तरह मैं स्पेनिश से अधिक आसानी से अंग्रेजी पढ़ सकता हूं, लेकिन यह उन भाषाओं की अंतर्निहित पठनीयता के बारे में कुछ भी नहीं कहता है। (स्पेनिश वास्तव में सादगी और स्थिरता के मामले में दोनों की "अधिक पठनीय" भाषा है, लेकिन मैं अभी भी इसे पढ़ नहीं सकता)। मैं अभी जापानी सीख रहा हूं और कठिन समय की बिल्ली पकड़ रहा हूं, लेकिन मूल जापानी वक्ताओं अंग्रेजी के बारे में भी यही कहते हैं।

यदि आपने अपना अधिकांश जीवन जावा पढ़ने में बिताया है, तो निश्चित रूप से जावा जैसी चीजें जो चीजें नहीं पढ़तीं, उन्हें पढ़ने में आसान होगी। जब तक आप सी-जैसी भाषाओं को देखने के रूप में लिस्पी भाषाओं को देखने में उतना समय बिताते हैं, यह संभवतः सच रहेगा।

एक भाषा समझने के लिए, अन्य बातों के अलावा आप से परिचित होना जरूरी:

  • वाक्य रचना ([vector] बनाम (list), hyphens-in-names)
  • शब्दावली (reductions क्या मतलब है कैसे/जहां देख सकते हैं? यह ऊपर है?)
  • मूल्यांकन नियम (कार्यों का इलाज करता है के रूप में वस्तुओं काम करते हैं? यह सबसे भाषाओं में एक त्रुटि है।)
  • मुहावरों, जैसे (map first (some set of reductions with extra accumulated values))

इन सभी के समय और अभ्यास और पुनरावृत्ति जानने के लिए और भली ले। लेकिन अगर आप अगले 6 महीनों में क्लोजर को पढ़ने और लिखने में व्यतीत करते हैं, न केवल आप क्लोजर कोड को 6 महीने समझने में सक्षम होंगे, तो शायद आप इसे अब से बेहतर समझेंगे, और शायद सरल बनाने में भी सक्षम होंगे यह। कैसे इस बारे में:

(use 'clojure.contrib.seq-utils)          ;;' 
(defn positions [coll] 
    (mapcat #(repeat (count %) (inc (ffirst %))) 
      (partition-by second (indexed coll)))) 

Clojure कोड को देखते हुए मैं एक साल पहले लिखा था, मैं कितना बुरा यह है पर भयभीत हूँ, लेकिन मैं यह ठीक पढ़ सकते हैं। (यह नहीं कह रहा कि आपका क्लोजर कोड भयानक है; मुझे इसे पढ़ने में कोई परेशानी नहीं थी, और मैं कोई गुरु नहीं हूं।)

+0

उत्कृष्ट प्रतिक्रिया। मुझे आपके संस्करण से प्यार है। मैं स्वीकार करूंगा कि इसे पाने में मुझे कुछ समय लगेगा। यह काफी चालाक है! धन्यवाद। – foxdonut

8

संपादित करें: अब प्रासंगिक नहीं हो सकता है।

क्लोजर एक मेरे लिए घिरा हुआ है। इसमें अधिक अवशोषण शामिल हैं जिन्हें समझने की आवश्यकता है। यह उच्च आदेश कार्यों का उपयोग करने की कीमत है, आपको पता होना चाहिए कि उनका क्या मतलब है। तो एक अलग मामले में, अनिवार्य को कम ज्ञान की आवश्यकता होती है। लेकिन abstractions की शक्ति संयोजन के उनके साधनों में है। प्रत्येक अनिवार्य पाश को पढ़ और समझा जाना चाहिए, जबकि अनुक्रम abstractions आपको एक पाश की जटिलता को हटाने और शक्तिशाली opperations गठबंधन करने की अनुमति देता है।

मैं आगे तर्क दूंगा कि ग्रोवी संस्करण कम से कम आंशिक रूप से कार्यात्मक है क्योंकि यह संग्रह का उपयोग करता है, जो वास्तव में मानचित्र है, एक उच्च क्रम कार्य है। इसमें कुछ राज्य भी है।

यहाँ कैसे मैं Clojure संस्करण लिख देगी:

(defn positions2 [coll] 
    (let [current (atom 1) 
     if-same #(if (= %1 %2) @current (reset! current (inc %3)))] 
    (map if-same (cons (first coll) coll) coll (range (count coll))))) 

यह काफी है कि यह एक अस्थायी "वर्तमान" का उपयोग करता है में ग्रूवी संस्करण के लिए समान है, लेकिन में अलग है कि यह एक अगले नहीं है/prev variable - इसके बजाय उन लोगों के लिए अपरिवर्तनीय अनुक्रमों का उपयोग करना। जैसा कि ब्रायन ने इसे स्पष्ट रूप से रखा है, पठनीयता आंतरिक नहीं है। यह संस्करण इस विशेष मामले के लिए मेरी प्राथमिकता है, और लगता है कि बीच में कहीं भी बैठता है।

+0

मैंने कोड संपादित किया। मुझे नहीं लगता कि यह अब बहुत गड़बड़ है। – foxdonut

+0

कूल :) यह आपके कोड की आलोचना नहीं थी, मैं सिर्फ इस सवाल का जवाब दे रहा था कि किस शैली को समझना आसान था। अब लक्ष्य पद चले गए हैं! Hehehe। –

+1

वैसे मैंने इसे आलोचना के रूप में नहीं लिया, और इसके अलावा, आप सही थे, पहला संस्करण/था/गठित। :-) – foxdonut

8

मैं तीमुथियुस से सहमत हूं: आप बहुत अधिक अमूर्तताओं को पेश करते हैं। मैं अपने कोड पर फिर से काम और के साथ समाप्त हुआ:

(defn positions [coll] 
    (reductions (fn [[_ prev-score :as prev] [_ score :as curr]] 
       (if (= prev-score score) prev curr)) 
    (map vector (iterate inc 1) coll))) 

अपने कोड के बारे में,

(defn use-prev [[a b]] (= a b)) 
(defn pairs [coll] (partition 2 1 coll)) 
(map use-prev (pairs coll)) 

बस के रूप में पुनर्संशोधित जा सकता है: मैं भी Clojure सीख रहा हूँ और यह प्यार

(map = coll (rest coll)) 
+0

धन्यवाद, मैंने आपके रिफैक्टरिंग सुझाव के अनुसार उपरोक्त संपादित किया है। – foxdonut

3

। लेकिन मेरे विकास के इस चरण में, ग्रोवी संस्करण को समझना आसान था। क्लोजर के बारे में मुझे क्या पसंद है हालांकि कोड पढ़ रहा है और "आह!" अनुभव करें जब आप आखिरकार "प्राप्त करें" क्या हो रहा है। मैं वास्तव में आनंद लेता हूं, ऐसा कुछ अनुभव होता है जो कुछ मिनट बाद होता है जब आप कोड के किसी भी प्रकार के डेटा के साथ अन्य प्रकार के डेटा पर कोड लागू किए जा सकते हैं। मैंने क्लोजर में कुछ संख्यात्मक कोड के माध्यम से कई बार काम किया है और फिर, थोड़ी देर बाद, सोचा था कि उसी कोड को स्ट्रिंग्स, प्रतीकों, विजेट्स के साथ कैसे इस्तेमाल किया जा सकता है ...

मेरे द्वारा उपयोग किए जाने वाले समानता रंग सीखने के बारे में है। याद रखें जब आपको रंग लाल रंग में पेश किया गया था? आप इसे बहुत जल्दी समझ गए - दुनिया में यह सब लाल चीजें हैं।फिर आपने मैजेंटा शब्द सुना और थोड़ी देर के लिए खो गया। लेकिन फिर, थोड़ा अधिक जोखिम के बाद, आप अवधारणा को समझ गए और किसी विशेष रंग का वर्णन करने के लिए एक और अधिक विशिष्ट तरीका था। आपको अवधारणा को आंतरिक बनाना है, अपने सिर में थोड़ी अधिक जानकारी रखें, लेकिन आप कुछ अधिक शक्तिशाली और संक्षिप्त के साथ समाप्त हो जाते हैं।

4

क्लोजर एक पहली नज़र में अधिक घुलनशील है; हालांकि यह शायद अधिक सुरुचिपूर्ण है। ओओ उच्च स्तर पर भाषा को "संबंधित" बनाने के लिए परिणाम है। कार्यात्मक भाषाओं में अधिक "एल्गोरिदमिक" (आदिम/प्राथमिक) लगता है। यही वह क्षण है जो मुझे इस समय महसूस हुआ। हो सकता है कि जब मेरे पास क्लोजर के साथ काम करने का अधिक अनुभव हो तो वह बदल जाएगा।

मुझे डर है कि हम इस खेल में निर्णय ले रहे हैं कि कौन सी भाषा सबसे संक्षिप्त हो सकती है या कोड की कम से कम पंक्ति में समस्या का समाधान कर सकती है।

मुद्दा मेरे लिए 2 परतों हैं:

  1. पहली नजर में कितना आसान क्या कोड क्या कर रहा है की एक महसूस करने के लिए ?. कोड रखरखाव के लिए यह महत्वपूर्ण है।

  2. कोड के पीछे तर्क पर अनुमान लगाना कितना आसान है? बहुत verbose/लंबी हवादार ?. बहुत terse?

"संभव है, लेकिन आसान नहीं के रूप में सरल रूप में सब कुछ है।"

अल्बर्ट आइंस्टीन

+0

मुझे नहीं लगता कि यह कोड की कम से कम पंक्तियों के बारे में है। कम से कम यह मेरा इरादा नहीं है। मुद्दे वे हैं जिन्हें आपने सुंदरता से समझाया। उदाहरण के लिए, मैं इस स्क्रिप्ट में 'gnud' (विस्तारित टिप्पणियों में) के छोटे, लेकिन कम पठनीय (IMHO) संस्करण के बजाय कोड का अपना संस्करण पसंद करता हूं: http://stackoverflow.com/questions/188162/ क्या-है-सर्वाधिक उपयोगी स्क्रिप्ट-youve से लिखा के लिए हर रोज जीवन/245,724 # 245,724 – foxdonut

3

ग्रूवी इस समस्या को भी हल करने के विभिन्न शैलियों का समर्थन करता है:

coll.groupBy{it}.inject([]){ c, n -> c + [c.size() + 1] * n.value.size() } 

निश्चित रूप से सुंदर लेकिन बहुत समझना कठिन नहीं होना करने के लिए पुनर्संशोधित नहीं।

3

मैं जानता हूँ कि इस प्रश्न का उत्तर नहीं है, लेकिन मैं "समझ" कोड बहुत अगर वहाँ इस तरह के रूप परीक्षण, बेहतर में सक्षम हो जाएगा:

assert positions([1]) == [1] 
assert positions([2, 1]) == [1, 2] 
assert positions([2, 2, 1]) == [1, 1, 3] 
assert positions([3, 2, 1]) == [1, 2, 3] 
assert positions([2, 2, 2, 1]) == [1, 1, 1, 4] 

जो मुझे बता देगा, एक से साल अब, कोड क्या करने की उम्मीद है। मैंने यहां देखे गए कोड के किसी भी उत्कृष्ट संस्करण से काफी बेहतर है।

क्या मैं वास्तव में विषय से बाहर हूं?

दूसरी बात यह है कि, मुझे लगता है कि "पठनीयता" संदर्भ पर निर्भर करता है। यह निर्भर करता है कि कोड कौन बनाएगा। उदाहरण के लिए, ग्रोवी कोड (हालांकि शानदार) के "कार्यात्मक" संस्करण को बनाए रखने के लिए, यह न केवल ग्रोवी प्रोग्रामर लेगा, बल्कि कार्यात्मक ग्रोवी प्रोग्रामर ... दूसरा, अधिक प्रासंगिक, उदाहरण है: यदि कुछ पंक्तियां कोड के "शुरुआती" क्लोजर प्रोग्रामर के लिए समझना आसान हो जाता है, तो कोड समग्र रूप से अधिक पठनीय होगा क्योंकि इसे एक बड़े समुदाय द्वारा समझा जाएगा: कोड को समझने और बनाने में सक्षम होने के लिए क्लोजर का अध्ययन करने की आवश्यकता नहीं है इसे संपादित करें।

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