2013-07-09 9 views
5

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

(defstruct (node (:type list)) label [other args here]) 

मैं एक समारोह में पता है कि तुम कर सकते हैं:

(defun foo (arg1 &rest args) ...) 

वहाँ defstruct के लिए बराबर &rest किसी प्रकार का है?

मैं बस सीख रहा हूं, इसलिए मुझे एहसास है कि मुझे कुछ याद आ रहा है। यदि &rest समतुल्य नहीं है, तो इस बारे में कोई विचार है कि मैं इसके बारे में कैसे जा सकता हूं? अग्रिम में धन्यवाद!

उत्तर

6

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

(defstruct node 
    label) 

आप node-label के साथ एक node के लेबल का उपयोग और तेजी देखने समय मिलता है (यह आम तौर पर एक स्मृति हिस्सा में सिर्फ एक सूचकांक है के बाद से) कर सकते हैं। अब, जैसा कि आप कर रहे हैं, आप संरचनाओं के कार्यान्वयन के रूप में सूचियों का उपयोग करने का विकल्प चुन सकते हैं, जिस स्थिति में node-labelcar या first के लिए केवल एक उपनाम है।

(defstruct (node (:type list)) 
    label) 

CL-USER> (make-node :label 'some-label) 
(SOME-LABEL) 
CL-USER> (node-label (make-node :label 'some-label)) 
SOME-LABEL 
CL-USER> (first (make-node :label 'some-label)) 
SOME-LABEL 
CL-USER> (car (make-node :label 'some-label)) 

आप मनमाने ढंग से सूची के आधार पर महत्वपूर्ण मूल्य जोड़े के लिए देख रहे हैं, तो आप शायद एक property list, जिसके लिए कॉमन लिस्प कुछ सुविधा कार्यों में शामिल करना चाहते हैं।

यदि आप एक ऐसी संरचना चाहते हैं जिसमें संपत्ति सूची भी शामिल है, तो आप उस विशेष निर्माता को उस सूची को पॉप्युलेट कर सकते हैं। उदाहरण के लिए,

(defstruct (node (:type list) 
       (:constructor make-node (label &rest plist))) 
    label 
    plist) 

CL-USER> (make-node 'some-label :one 1 :two 2) 
(SOME-LABEL (:ONE 1 :TWO 2)) 
CL-USER> (node-plist (make-node 'some-label :one 1 :two 2)) 
(:ONE 1 :TWO 2) 
+0

धन्यवाद, यह लगभग वही है जो मैं ढूंढ रहा हूं। लेकिन संपत्ति सूची रखने का कोई तरीका है, जैसा कि आपने इसे 'नोड' में बस अन्य स्लॉट के रूप में रखा है? दूसरे शब्दों में, '(मेक-नोड' कुछ लेबल करने के लिए कोई तरीका है: एक 1: दो 2) => (कुछ-लेबल: एक 1: दो 2) ', '(कुछ-लेबल (: एक 1: दो दो)) '? –

+1

संक्षेप में, नहीं। [रेनर का जवाब] (http://stackoverflow.com/a/17556349/1281433) सामान्य रूप से संरचनाओं के बारे में अधिक गहराई में जाता है, लेकिन बिंदु यह है कि संरचनाओं में स्लॉट की निश्चित संख्या होती है। भले ही आप '(: प्रकार सूची) 'विकल्प के साथ" खराब व्यक्ति के रिकॉर्ड "बनाने के लिए' defstruct' का उपयोग कर सकते हैं, फिर भी आप केवल स्लॉट की एक निश्चित संख्या प्राप्त करने जा रहे हैं (जिसका अर्थ है कि सूची में निश्चित संख्या है तत्व)। यह वास्तव में लगता है जैसे आप सिर्फ एक संपत्ति सूची चाहते हैं। –

+0

हाँ, रेनर के जवाब के माध्यम से पढ़ना, मुझे लगता है कि मैं जो कर रहा हूं उसके मुकाबले ज्यादा फ़ायरवॉवर है। सलाह के लिए धन्यवाद दोस्तों! –

7

सामान्य लिस्प में, संरचनाओं को कठोर और निम्न-स्तर के रिकॉर्ड के रूप में माना जाता है। उनके पास फैंसी गतिशील विशेषताएं नहीं हैं।

संरचनाओं के साथ आप क्या कर सकते हैं एक नई संरचना प्रकार को परिभाषित करना है जो किसी अन्य से प्राप्त होता है। एक विरासत उपलब्ध है।

गतिशील विस्तारशीलता को संभालने के लिए, संरचना का एक संपत्ति सूची स्लॉट जोड़ने का एक सामान्य तरीका है। यहोशू का जवाब देखें।

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

कॉमन लिस्प के लिए अन्य ऑब्जेक्ट सिस्टम हैं, जो आसानी से प्रति-आवृत्ति आधार पर स्लॉट जोड़ सकते हैं। लेकिन आमतौर पर इसका उपयोग करने के लिए बहुत अधिक होता है, क्योंकि वे काफी अधिक शक्तिशाली होते हैं।

CLOS और मेटा-ऑब्जेक्ट प्रोटोकॉल के साथ कोई इसे छिपाने का प्रयास कर सकता है।LispWorks यहाँ मैं उपयोग कर रहा हूँ: हमारी संपत्ति के नाम को स्वीकार SLOT-VALUE बनाने के लिए

(defmethod set-property ((object property-mixin) key value) 
    (setf (getf (slot-value object 'plist) key) value)) 

(defmethod get-property ((object property-mixin) key) 
    (getf (slot-value object 'plist) key)) 

अब हम तरीकों लिखें:

(defclass property-mixin() 
    ((plist :initform nil)) 
    #+lispworks 
    (:optimize-slot-access nil)) 

सेटिंग और गुण पढ़ने:

हम अपने गुणों के लिए एक mixin वर्ग को परिभाषित :

(defmethod (setf clos:slot-value-using-class) 
     (value (class standard-class) (object property-mixin) slot-name) 
    (declare (ignorable class)) 
    (if (slot-exists-p object slot-name) 
     (call-next-method) 
    (progn 
     (set-property object slot-name value) 
     value))) 

(defmethod clos:slot-value-using-class ((class standard-class) 
             (object property-mixin) 
             slot-name) 
    (declare (ignorable class)) 
    (if (slot-exists-p object slot-name) 
     (call-next-method) 
    (get-property object slot-name))) 

उदाहरण।

(defclass automobile (property-mixin) 
    ((company :initarg :company) 
    (motor :initarg :motor)) 
    #+lispworks 
    (:optimize-slot-access nil)) 

अब एक उदाहरण:: हम दो स्लॉट के साथ एक वाहन वर्ग को परिभाषित

CL-USER 45 > (setf a6 (make-instance 'automobile :company :audi :motor :v6)) 
#<AUTOMOBILE 402005B47B> 

हम एक सामान्य स्लॉट मूल्य प्राप्त कर सकते हैं:

CL-USER 46 > (slot-value c1 'motor) 
:V6 

के एक स्लॉट जो नहीं है के लिए लिखते हैं मौजूद है, लेकिन हमारी संपत्ति सूची में जोड़ा जाएगा:

CL-USER 47 > (setf (slot-value a6 'seats) 4) 
4 

हम मूल्य वापस प्राप्त कर सकते:

CL-USER 48 > (slot-value c1 'seats) 
4 
1

मुझे लगा कि यह एक अलग जबाब बल्कि तो एक टिप्पणी है, तो यहाँ जाता है के लायक हो जाएगा:

कभी-कभी, जब आपको लगता है कि आप एक संरचना या एक की जरूरत है ऑब्जेक्ट, लेकिन आपके पास कुछ विशेष आवश्यकताएं हैं जो इन इकाइयों को पूरा नहीं करती हैं, शायद ऐसा इसलिए है क्योंकि आपको वास्तव में जो कुछ चाहिए वह कुछ अलग डेटा संरचना है? ऑब्जेक्ट्स या स्ट्रक्चर अच्छे होते हैं जब कुछ शर्तों को पूरा किया जाता है, ऐसी एक शर्त यह है कि स्लॉट स्थिर रूप से ज्ञात हैं - यह संकलक को कोड के बारे में बेहतर कारण बताता है, जो अनुकूलन और त्रुटि रिपोर्टिंग दोनों के लिए अच्छा है।

दूसरी तरफ, डेटा संरचनाएं हैं। कुछ भाषा मानक पुस्तकालय के साथ प्रदान किए जाते हैं, अन्य इसके शीर्ष पर जोड़े जाते हैं। यहां एक लाइब्रेरी है जो उनमें से कई प्रदान करती है: http://cliki.net/cl-containers लेकिन विशेष मामलों के लिए और भी कुछ हैं।

अब, मैं तर्क दूंगा कि सूची, सरणी, किसी प्रकार के पेड़ इत्यादि जैसी संरचना का उपयोग करना बेहतर होता है, फिर स्लॉट गतिशील रूप से जोड़ने की अनुमति देने के लिए ऑब्जेक्ट्स या स्ट्रक्चर का विस्तार करने की कोशिश करना बेहतर होता है। ऐसा इसलिए होता है क्योंकि आम तौर पर हम उम्मीद करते हैं कि स्लॉट को नगण्य होने का समय मिलेगा। हम उम्मीद करते हैं कि यह ओ (1) हो। ऑब्जेक्ट की स्लॉट की संख्या के बावजूद यह सामान्य रूप से होता है। अब, जब आप नीचे एक सूची का उपयोग कर रहे हैं तो आप इसे ओ (एन) बना रहे हैं, जबकि आप वही अर्थशास्त्र रखते हैं! आप निश्चित रूप से ओ (1) बनाने के लिए हैश-टेबल का उपयोग कर सकते हैं (हालांकि यह अभी भी धीमी गति से स्लॉट एक्सेस होगा), लेकिन फिर आपके पास कुछ अन्य अप्रत्याशित व्यवहार होंगे, जैसे nil स्लॉट नहीं करता है नियमित त्रुटि इत्यादि के बजाय मौजूद हैं

मुझे नहीं लगता कि इस तरह से वस्तुओं को विस्तारित करना सीएल में एक आम प्रथा है, शायद यही कारण है कि अन्य प्रतिक्रियाएं आपको ऐसा करने से हतोत्साहित नहीं करती हैं। मुझे सीएल के बाद अन्य उत्तरदाताओं को पता है, लेकिन मुझे इस तरह की कुशलता के साथ एक और भाषा में दुःख का अच्छा सौदा हुआ है, जहां यह आम है और आमतौर पर निराश होता है।

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

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