2009-02-16 19 views
6

क्या क्लोजर में संरचना के भीतर घनिष्ठ संरचना हो सकती है? निम्नलिखित कोड पर विचार करें:क्लोजर संरचना एक और संरचना के भीतर नेस्टेड

(defstruct rect :height :width) 
(defstruct color-rect :color (struct rect)) 

(defn 
#^{:doc "Echoes the details of the rect passed to it"} 
echo-rect 
[r] 
    (println (:color r)) 
    (println (:height r)) 
    (println (:width r))) 

(def first-rect (struct rect 1 2)) 
;(def c-rect1 (struct color-rect 249 first-rect)) ;form 1 
;output "249 nil nil" 
(def c-rect1 (struct color-rect 249 1 2)) ;form 2 
;output "Too many arguments to struct constructor 

(echo-rect c-rect1) 
बेशक

यह एक काल्पनिक उदाहरण है, लेकिन ऐसे मामलों में जहां मैं कोड आसान बनाए रखने के लिए बनाने के लिए छोटे substructures में एक बड़े डेटा संरचना को तोड़ने के लिए चाहते हैं। जैसा कि टिप्पणियां इंगित करती हैं कि यदि मैं फॉर्म 1 करता हूं तो मुझे "24 9 शून्य शून्य" मिलता है लेकिन यदि मैं फॉर्म 2 करता हूं तो मुझे "स्ट्रक्चर कन्स्ट्रक्टर के लिए बहुत सारे तर्क मिलते हैं"।

यदि मैं गलत तरीके से इस मुद्दे पर आ रहा हूं, तो कृपया मुझे बताएं कि मुझे क्या करना चाहिए। क्लोजर Google समूह को खोजना मेरे लिए कुछ भी नहीं बदला।


संपादित करें:

मुझे लगता है कि मैं अपने प्रश्न के बयान में के रूप में स्पष्ट रूप में मैंने सोचा कि मैं था नहीं था:

1.) उस में एक और भीतर घोंसला एक struct करना संभव है Clojure? (नीचे से यह एक हां है।)

2.) यदि हां, तो सही वाक्यविन्यास क्या होगा? (फिर से, नीचे से निर्णय लेना ऐसा लगता है कि कोई ऐसा कर सकता है।)

3.) जब आप किसी अन्य संरचना के भीतर घोंसला वाली संरचना प्राप्त करते हैं तो आप एक निर्दिष्ट कुंजी द्वारा मूल्य कैसे प्राप्त करते हैं?

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

उत्तर

7

मुझे लगता है कि struct नक्शे में अन्य पोस्टर के साथ सहमत होगा वास्तव में विरासत का समर्थन नहीं करते। हालांकि, अगर आप बस एक नया struct एक और की कुंजी का उपयोग करता है बनाना चाहते हैं, तो यह काम करेगा:

; Create the rect struct 
(defstruct rect :height :width) 

; Create the color-rect using all the keys from rect, with color added on 
(def color-rect (apply create-struct (cons :color (keys (struct rect))))) 

(defn create-color-rect 
    "A constructor function that takes a color and a rect, or a color height and width" 
    ([c r] (apply struct (concat [color-rect c] (vals r)))) 
    ([c h w] (struct color-rect c h w))) 

आप echo-rect समारोह की जरूरत नहीं है, तो आप बस struct नक्शे उदाहरण मूल्यांकन कर सकते हैं क्या में है देखने के लिए यह:

user=> (def first-rect (struct rect 1 2)) 
#'user/first-rect 
user=> first-rect 
{:height 1, :width 2} 
user=> (create-color-rect 249 first-rect) 
{:color 249, :height 1, :width 2} 
user=> (create-color-rect 249 1 2) 
{:color 249, :height 1, :width 2} 
+0

धन्यवाद पॉल - यह वही है जो मैं जानना चाहता था। –

1

मैं क्लोजर के लिए वास्तव में नया हूं, इसलिए मैं गलत हो सकता हूं। लेकिन मुझे लगता है, आप

(defstruct color-rect :color (struct rect)) 

की तरह कुछ नहीं कर सकते जहां तक ​​मेरा clojure-structs समझते हैं, यह एक struct (मूल रूप से जाना जाता है कुंजी के साथ एक नक्शा), किसी भी तरह के रूप में struct 'रेक्ट' है कि पैदा करेगा इसकी चाबियाँ में से एक

मेरे धारणा अवलोकन है कि (struct रेक्ट) का एक सरल मूल्यांकन पैदावार

{:height nil, :width nil} 

(struct रंग-रेक्ट) पैदावार का मूल्यांकन जबकि द्वारा समर्थित है:

{:color nil, {:height nil, :width nil} nil} 

संपादित करें: क्या यह तथ्य आपकी मदद कर सकता है, कि structs कुंजी तक ही सीमित नहीं हैं, इन्हें परिभाषित किया गया है। ऐसा लगता है कि आप को पूरा कर सकते हैं, तो आप कुछ इस तरह से क्या कोशिश कर रहे हैं:

(def c-rect1 (struct-map color-rect :color 249 :height 1 :width 1)) ;form 3 
+0

यह सही है:: या यहां तक ​​कि आप चाबियों का नाम, जो स्वचालित रूप से इस तरह के एक struct द्वारा उत्पादित कुंजी में विस्तार कर रहे हैं के रूप में अन्य struct परिभाषाओं का उपयोग करने की अनुमति आप एक के लिए कुंजी के रूप में एक खाली रेक्ट struct का उपयोग कर रहे रंग-रेक्ट के मूल्यों का। यह कुछ ऐसा करने के लिए और अधिक समझ में आता है जैसे: rect। –

6

नेस्टिंग संरचनाओं संभव है और कभी कभी वांछनीय है। हालांकि, ऐसा लगता है कि आप कुछ अलग करने की कोशिश कर रहे हैं: ऐसा लगता है कि आप रचना के बजाय संरचना प्रकारों की विरासत का उपयोग करने की कोशिश कर रहे हैं। यही है, फॉर्म 2 में आप एक रंग-रेक्ट बना रहे हैं जो में एक रेक्ट है लेकिन आप एक उदाहरण बनाने की कोशिश कर रहे हैं जैसे कि एक आयत था। फॉर्म 1 काम करता है क्योंकि आप पूर्व-मौजूदा रेक्ट से सी-रेक्ट 1 बना रहे हैं, जो संरचना का उपयोग करने का सही तरीका है।

क्लोजर समूह या केवल वेब पर एक त्वरित खोज आपको रचना और विरासत के बीच भेद के अच्छे वर्णन के लिए ले जाना चाहिए। क्लोजर में, रचना या बतख-टाइपिंग (Google को फिर से देखें) लगभग हमेशा विरासत को प्राथमिकता दी जाती है।


संपादित करें:

जवाब में अपने प्रश्न # 3: का उपयोग कर के लिए एक वैकल्पिक -> नेस्टेड संरचनाओं में डेटा निकालने के लिए, के रूप में ब्रायन छिद्रान्वेषी अपने जवाब में बताया गया है, मिल-इन, के साथ साथ अपनी भाई बहन Assoc-इन और अद्यतन-इन:

उदाहरण के लिए:

(def cr {:rect {:height 1, :width 2}, :color :blue}) 
(get-in cr [:rect :width]) 
;; => 2 

(assoc-in cr [:rect :height] 7) 
;; => {:rect {:height 7, :width 2}, :color :blue} 

(update-in cr [:rect :width] * 2) 
;; => {:rect {:height 1, :width 4}, :color :blue} 

(assoc-in cr [:a :new :deeply :nested :field] 123) 
;; => {:a {:new {:deeply {:nested {:field 123}}}}, 
;;  :rect {:height 1, :width 2}, :color :blue} 
6

यदि आप इसे जोड़ने के लिए एक कुंजी देते हैं तो आप एक संरचना को अन्य संरचना का मूल्य बना सकते हैं। आप इसे नीचे के रूप में कर सकते हैं।

(आप आसानी से मनमाने ढंग से नेस्ट हैश/structs की हिम्मत -> के माध्यम से देख सकते हैं, वाक्य रचना चीनी का एक सा है।)

(defstruct rect :height :width) 
(defstruct color-rect :rect :color) 

(def cr (struct color-rect (struct rect 1 2) :blue)) 
;; => {:rect {:height 1, :width 2}, :color :blue} 

(:color cr)   ;; => :blue 
(:width (:rect cr)) ;; => 2 
(-> cr :color)  ;; => :blue 
(-> cr :rect :width) ;; => 2 
1

मुझे पता है यह अब एक पुराने सवाल है, लेकिन मैं के साथ आया था निम्नलिखित मैक्रो:

(defmacro extendstruct [n b & k] 
    `(def ~n 
    (apply create-struct 
     (clojure.set/union 
     (keys (struct ~b)) 
     #{[email protected]})))) 

कौन सा आप इस बारे में करने की अनुमति होगी:

(defstruct rect :width :height) 
(extendstruct color-rect rect :color) 

परीक्षण:

(struct rect)  ; {:width nil, :height nil} 
(struct color-rect) ; {:color nil, :width nil, :height nil} 

क्या यह वही होगा जो आप चाहते थे?

इसे भी संशोधित किया जा सकता है ताकि संरचनाओं का संग्रह उपयोग किया जा सके।

(defstructx one :a :b) 
(defstructx two :c one :d) 
(defstructx three :e two :f :g) 
; three 
(keys (struct three)) ; #{:e :c :a :b :d :f :g} 
संबंधित मुद्दे