2012-07-25 14 views
8

किसी भी गलत शब्दावली के लिए क्षमा चाहते हैं - मैं कंप्यूटर विज्ञान के लिए काफी नया हूं, और मुझे बहुत अधिक क्लोजर पता है (लेकिन मुझे लगता है कि मैं कहूंगा कि मैं इसे जानता हूं बहुत बढ़िया)।अज्ञात "स्वयं संदर्भित" डेटा संरचनाओं पर सलाह/चर्चा

इसलिए, मैंने इस पर शोध का एक टन नहीं किया है, लेकिन क्लोजर कोड लिखते समय मुझे कभी-कभी यह उपयोगी लगता है कि कुछ "इंटरमीडिएट संस्करण जो मैं डेटा संरचना में हूं" से संदर्भित करने में सक्षम हूं उस डेटा संरचना के भीतर (let में बहुत कुछ)। त्वरित उदाहरण:

=> (self-ish {:a 10 
       :b (inc (this :a)) 
       :c (count (vals this))}) 
=> {:a 10, :b 11, :c 3} 
=> (self-ish ["a" "b" (reduce str this)]) 
=> ["a" "b" "ab"] 
//Works in any nested bits too 
=> (self-ish [1 2 3 [4 5 (first this)] 6 [7 [8 (cons (second this) (nth this 3))]]]) 
=> [1 2 3 [4 5 1] 6 [7 [8 (2 4 5 1)]]] 

विचार है कि संरचना ही बनाता है संवर्द्धित, और किसी भी स्तर पर this के रूप में वर्तमान मध्यवर्ती संरचना का उल्लेख करने की क्षमता है है। यहाँ मेरे वर्तमान कार्यान्वयन के लिए कोड है:

//Random straightforward but helpful definitions 
(defn map-entry? [obj] 
    (instance? clojure.lang.AMapEntry obj)) 
(def Map clojure.lang.IPersistentMap) 
(def Vector clojure.lang.IPersistentVector) 
(def List clojure.lang.IPersistentList) 
(def Set clojure.lang.IPersistentSet) 

(defn append 
    [x coll] 
    (if-not coll x 
    (condp instance? coll 
     Map (if (empty? x) coll 
      (assoc coll (first x) (second x))) 
     Vector (conj coll x) 
     Set (conj coll x) 
     List (apply list (concat coll [x])) 
     (concat coll [x])))) 

(defn build-this 
    [acc-stack acc] 
    (->> (cons acc acc-stack) 
     (drop-while list?) 
     (drop-while (every-pred empty? identity)) 
     (reduce append))) 

(defn self-indulge 
    [acc-stack acc form] 
    ;//Un-comment the following to see it print intermediate stages of processing 
    #_(println "this:" (build-this acc-stack acc) "\n at:" form) 
    (append (cond 
      (coll? form) (reduce (partial self-indulge (cons acc acc-stack)) 
           (if (map-entry? form) [] 
            (empty form)) 
           form) 
      (= (quote this) form) (build-this acc-stack acc) 
      :else form) 
      acc)) 

(defmacro self-ish 
    [form] 
    (self-indulge() nil form)) 

append समारोह एक संग्रह पर एक आइटम जोड़ देती है और संग्रह के एक ही प्रकार देता है। self-indulge फ़ंक्शन में मानक कम-जैसे संचयक होता है, जो केवल फ़ॉर्म के तत्व बनाता है। इसमें एक संचयक स्टैक भी होता है, जो हर बार self-indulge खुद पर रिकर्स करता है। इसका मुद्दा अन्य "उच्च अप" संचयकों का ट्रैक रखना है, ताकि this संपूर्ण संरचना न हो, न केवल स्थानीय टुकड़ा। self-ish मैक्रो बस अच्छी तरह से self-indulge को लपेटता है (जो खुद को partial का उपयोग करके कॉल करता है, इसलिए यह मैक्रो पैंट नहीं पहन सकता है)।

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

=> (self-ish {:favorite-books (list "Crime and Punishment" "Mrs. Dalloway") 
       :favorite-things (list* "Ice Cream" "Hammocks" (this :favorite-books)}) 
=> {:favorite-things ("Ice Cream" "Hammocks" "Crime and Punishment" "Mrs. Dalloway"), 
    :favorite-books ("Crime and Punishment" "Mrs. Dalloway")} 

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

मेरा मुख्य सवाल:

  1. यह वास्तव में उपयोगी है, या अस्पष्टता/जटिलता किए गए हैं बहुत ज्यादा हो सकता है? मुझे कल्पना है कि मैं इस प्रकार के मैक्रो का उपयोग/उपयोग करने में अकेला नहीं हूं। यहां दूसरों के अनुभव क्या हैं? क्या आप इस तरह कुछ उपयोग करते हैं? क्या आपको बेहतर कामकाज मिल गया है? क्या इस तरह के कुछ कारण क्लोजर पुस्तकालयों में नहीं हैं? या क्या ऐसा कुछ है जिसे मैंने अभी तक नहीं देखा है?
  2. क्या बेहतर नामकरण सम्मेलन मैं उपयोग कर सकता हूं - self-ish और this के विपरीत? उदाहरण के लिए, शायद this ओओपी अर्थ से बहुत भरा हुआ है, मुझे यकीन नहीं है, मैं मूल रूप से केवल क्लोजर से परिचित हूं।
  3. मैं कंप्यूटर विज्ञान के लिए काफी नया हूं, इस तरह की चीज़ से संबंधित सुलभ और सूचनात्मक संसाधन हैं - मुझे लगता है कि मैं इसे अज्ञात स्वयं रेफरेंसियल कह सकता हूं (शायद रिफ्लेक्सिव एक बेहतर शब्द है?) डेटा संरचनाएं? मुझे अभी तक कुछ भी सुलभ और जानकारीपूर्ण नहीं मिला है।
  4. self-ish मैक्रो लिखने का कोई बेहतर तरीका है?ऊपर, मैंने इसके वर्तमान संस्करण को शामिल किया है, लेकिन मैं महसूस नहीं कर सकता कि एक आसान तरीका हो सकता है।
  5. मेरे पास "बुद्धिमान" कार्यान्वयन विवरण क्या हो सकता है इसके बारे में विभिन्न प्रश्न हैं।

    • Traversal: क्या यह पहले चौड़ाई या गहराई होनी चाहिए? अगर गहराई पहले, preorder, postorder, या inorder? अभी, मेरा मानना ​​है कि यह गहराई पहले प्रीऑर्डर है, जो मुझे समझ में आता है, लेकिन हो सकता है कि इसमें कुछ कमीएं हैं जिन्हें मैंने नहीं देखा है।
    • आदेश समस्याओं: (See here for a related previous question of mine) {} को उचित 8 नक्शा प्रविष्टियों के ऊपर array-map या sorted-map दूसरे शब्दों --in का उपयोग किए बिना (8 ऊपर नक्शा प्रविष्टियों) बनाए रखने के लिए, असंभव है (यानी हाथ से लिखा नक्शे), {} के भीतर उपयोग असुरक्षित है। हो सकता है कि हाथ से लिखे गए आदेश के बजाय, मैक्रो कुछ "आदर्श" क्रम में वस्तुओं को संसाधित करने के लिए कुछ फैंसी जादू कर सकता है? या शायद के बजाय (array-map ...) के भीतर सभी मानचित्रों को लपेटना बेहतर होगा?

      //Showing maps with 9 entries failing 
      => (self-ish {:a 1 
             :b (inc (this :a)) 
             :c (inc (this :b)) 
             :d (inc (this :c)) 
             :e (inc (this :d)) 
             :f (inc (this :e)) 
             :g (inc (this :f)) 
             :h (inc (this :g)) 
             :i (inc (this :h))}) 
      => NullPointerException clojure.lang.Numbers.ops (Numbers.java:942) 
      //8 works fine 
      => (self-ish {:a 1 
             :b (inc (this :a)) 
             :c (inc (this :b)) 
             :d (inc (this :c)) 
             :e (inc (this :d)) 
             :f (inc (this :e)) 
             :g (inc (this :f)) 
             :h (inc (this :g))}) 
      => {:h 8, :g 7, :f 6, :e 5, :d 4, :c 3, :b 2, :a 1} 
      
    • सीरियल: मैं यह लिखा है के रूप में, मैक्रो अनंत प्रत्यावर्तन क्रमानुसार उसके तत्वों, let के लिए इसी तरह के साथ काम से बचा जाता है, लेकिन है कि संभावित अजीब व्यवहार का उत्पादन करता है। उदाहरण के लिए, मेरे उपरोक्त त्वरित उदाहरण में, (reduce str this)"ab" लौटाता है क्योंकि this["a" "b"] उस चरण में है। शायद यह कभी-कभी असीमित आलसी अनुक्रम बनाने के लिए उपयोगी होगा? यदि हां, तो इसे कैसे लागू किया जा सकता है?

    • मानचित्र प्रविष्टियों: अभी, नक्शा प्रविष्टियों वैक्टर की तरह व्यवहार कर रहे हैं, लेकिन क्योंकि कैसे this किसी भी मध्यवर्ती कदम पर लागू किया जा सकता है, यह "अभी तक नहीं" है कि एक कुंजी से एक nil मूल्य प्राप्त करने के लिए पूरी तरह से संभव है एक मूल्य असाइन किया गया है। यही कारण है कि मेरे पहले त्वरित उदाहरण में, :c समाप्त हो गया 3 से मैप किया गया - क्योंकि मध्यवर्ती nil:c से संबंधित था, और यह भी गिना गया। क्या आपको लगता है कि यह वारंट फिक्सिंग कर रहा है?
    • गैर-मैक्रो उपयोगिता: मैक्रो संदर्भ के बाहर केवल self-indulge का उपयोग करना मुश्किल होगा, लेकिन क्या यह कभी उपयोगी हो सकता है?

पढ़ने के लिए धन्यवाद, किसी भी मदद की सराहना की है :)

+0

दिलचस्प लग रहा है करने के लिए सार्थक नाम देने के लिए आमतौर पर है, लेकिन आप चीजों को जटिल और अस्पष्ट बनाने के अलावा अन्य तरह के बात के लिए किसी भी उपयोगी उपयोग के मामले का उल्लेख कर सकते हैं। – Ankur

+0

दार्शनिक दिखता है, शायद यह पूछने के लिए गलत स्टैक एक्सचेंज साइट है। – sortega

+0

@ अंकुर अच्छा विचार, मैं एक उपयोग केस शामिल करने के लिए संपादित कर दूंगा। ऐसा नहीं है कि यह किसी भी क्षमताओं का विस्तार करता है, यह संभावित रूप से लेखन कोड को अधिक सरल/मॉड्यूलर बनाता है। ईमानदारी से हालांकि, मुझे यकीन नहीं है कि यह वास्तव में अतिरिक्त अस्पष्टता/जटिलता के लायक है, जैसा कि आप इंगित करते हैं। यही वह था जो मैं अपने पहले प्रश्न के साथ आने की कोशिश कर रहा था, मुझे इसे भी संपादित करना चाहिए। –

उत्तर

2

यह दृष्टिकोण मुझे थोड़ा गलत लगता है, हालांकि मुझे पूरा यकीन नहीं है कि क्यों।शायद मैं नक्शा निर्माण आदेश पर निर्भर होने का विचार पसंद नहीं है ....

कहा करने के बाद कि यह एक बहुत आसान मैक्रो लिखने के लिए है, तो आप को प्रभावी ढंग से कुछ है कि के लिए विस्तारित हैं:

(let [this {} 
     this (assoc this :a 1) 
     this (assoc this :b (+ (this :a) 3))] 
    this) 

इसलिए

(defmacro self-ish [bindings] 
    `(let [~'this {} 
     [email protected](mapcat 
      #(do `(~'this (assoc ~'this [email protected]%)))  
      (partition 2 bindings))] 
    ~'this)) 

(self-ish [:a 1 
      :b (+ (this :a) 3)]) 
=> {:b 4, :a 1} 

ध्यान दें कि मैं बंधन फार्म के रूप में एक नक्शा बाध्यकारी रूप अव्यवस्थित है एक सदिश बना रही है: एक उचित मैक्रो की तरह (मानचित्र मामले के लिए) कुछ होगा।

अभी भी यह सुनिश्चित नहीं है कि मुझे यह मुहावरे कितना पसंद है। मेरे पसंदीदा तरीका एक लेट फार्म के साथ एक संरचना को परिभाषित करने और अंतरिम गणना उदा .:

(let [meaningful-foo (something) 
     meaningful-bar (something-else)] 
    {:foo meaningful-foo 
    :bar meaningful-bar 
    :baz (some-calculation meaningful-foo meaningful-bar)}) 
+1

शानदार! नीचे 'चलो' पूरी तरह से एक अच्छा विचार है, और वास्तव में सरल - मैंने कभी किसी कारण से कभी नहीं सोचा! कुछ मामलों में यह अधिक verbose होगा, लेकिन शायद लगभग हमेशा यह मेरे 'आत्म-आश' दृष्टिकोण से अधिक सरल और स्पष्ट होगा। 'स्वयं-ईश' मैक्रो के आपके संस्करण के लिए, जैसा कि वर्तमान में यह है, केवल नक्शे पर काम करने के अलावा, यह नेस्टेड डेटा पर भी काम नहीं करता है। आखिरकार, आप * मैक्रो को इंटरमीडिएट 'के साथ एक चलो के रूप में विस्तारित कर सकते हैं, जहां उन मध्यवर्ती शायद' आत्म-उलझन 'पर कुछ' कटौती 'कॉल होंगे, लेकिन मुझे लाभ नहीं दिख रहा है। –

2

योजना में इस (letrec ...) जो आप संरचना के अंदर ही डेटा संरचना के नाम का उल्लेख करने देता है के साथ किया जाता है। इसलिए यदि आप ऐसा करने के अपने तरीके को परिभाषित करना चाहते हैं तो इसे लागू करने के लिए और अधिक समझ हो सकती है। आप इसे Is it possible to create circular references in Clojure?

लेट्रेक का एक लाभ यह है कि इसमें उपयोगकर्ता द्वारा निर्दिष्ट नाम है (यदि आपका मैक्रो घोंसला है तो this छायांकित है) के उत्तर में वर्णित संदर्भों के साथ यह कर सकता है।

[प्रकार पर टिप्पणी को हटाने के लिए के रूप में मैं अपने मैक्रो समझ में नहीं आता संपादित।]

[अद्यतन] भी, आप clojure अनुभाग की खुशी में Anaphora की चर्चा में दिलचस्पी हो सकती है 8.5.1

+0

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

+0

अगर मुझे लगता है कि परमाणु अंत में त्याग दिया गया है। तो उस लिंक में दूसरे उदाहरण में, आप अंततः '@ ए' का उपयोग करेंगे। मैं आपके मैक्रो टीबी को समझ नहीं पा रहा हूं। –

+0

ओह, यह उन पाठकों के कारण है जो पाठक बना रहा है मुझे लगता है? ठीक। उस मामले में आपको भी सेट करना चाहिए था। हममम। नहीं, अभी भी यह नहीं मिलता है। माफ़ कीजिये। –

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