2012-02-20 10 views
8

मैं विभिन्न तत्वों के लिए HTML को उत्सर्जित करने के लिए कुछ विधियां लिख रहा हूं। प्रत्येक विधि में एक ही आउटपुट होता है, लेकिन आवश्यक रूप से एक ही इनपुट की आवश्यकता नहीं होती है।defgeneric में वैकल्पिक तर्क?

एक game-board जरूरतों गूंज के साथ-साथ एक player लेने के लिए (क्योंकि प्रत्येक खिलाड़ी केवल अपने स्वयं के टुकड़े को देखता है)

(defmethod echo ((board game-board) (p player)) ...) 

एक बोर्ड अंतरिक्ष गूंज खिलाड़ी प्रति बदल रहा है (कि प्रेषण वास्तव में है की आवश्यकता नहीं है के लिए विधि game-board विधि में किया गया, जो बाद में किसी स्थान पर echo पर कॉल करता है)। आदर्श रूप में, मैं

(defmethod echo ((space board-space)) ...) 
(defmethod echo ((space empty-space)) ...) 

यह भी बोधगम्य है कि मैं बाद में एक वस्तु है कि आदेश में ही ठीक से प्रदर्शित करने में सिर्फ खिलाड़ी से अधिक जानने की आवश्यकता होगी में चलाने ऐसा करने में सक्षम होगा। चूंकि पहले से ही कर रहे हैं, हालांकि, एक ही सामान्य पर विशेषज्ञता के तरीकों, कि त्रुटि

The generic function #<STANDARD-GENERIC-FUNCTION ECHO (4)> takes 2 required arguments; 

देना होगा यह आदर्श से कम वापस जाएँ और इन तरीकों echo-space, echo-board और इतने पर नाम के लिए लगता है।

क्या विशिष्ट वस्तु के आधार पर अन्य तर्कों का एक कैननिक तरीका है? मैं

(defgeneric echo (thing &key player ...) ...) 

या

(defgeneric echo (thing &rest other-args) ...) 

की तरह कुछ करना चाहिए? अधिक आम तौर पर, क्या कोई मुझे defgeneric पर विशेष रूप से एक सभ्य ट्यूटोरियल पर इंगित कर सकता है? (मैंने प्रासंगिक पीसीएल अध्याय और some CLOS tutorials पढ़ा है, लेकिन वे उस स्थिति को कवर नहीं करते हैं जो मैं यहां पूछ रहा हूं)।

उत्तर

5

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

Keene's book, मुझे विश्वास है, CLOS के लिए सबसे व्यापक मार्गदर्शिका है। दुर्भाग्य से यह केवल पुस्तक रूप में उपलब्ध प्रतीत होता है।

+0

एक सामान्य पर फ़ंक्शन प्रेषण होने से संतोषजनक से कम लगता है (जो मुझे 'इको-बोर्ड'/'इको-स्पेस'/आदि क्षेत्र में वापस ले जाएगा)। मुझे लगता है कि आप इस मामले में सही हैं; मैं 'echo' (निष्क्रिय रूप से एकल आइटम को निष्क्रिय करने के लिए) और एक अलग' गूंज-अनुरूप 'या समान (जो अतिरिक्त पैरामीटर के आधार पर अपना आउटपुट बदल देगा) को परिभाषित करने से बेहतर हो सकता है। – Inaimathi

+0

गैर-जेनेरिक फ़ंक्शन प्रेषण नहीं करता है, यह तर्कों को केवल अनुरूप बनाता है। यह स्पष्ट रूप से सभी संभावित तर्क लेने के लिए जेनेरिक (और इसलिए विधियों) की आवश्यकता है, यही कारण है कि यह केवल तब उपयोगी होता है जब इंटरफ़ेस वास्तव में समान होता है। – Ramarren

+0

यहां केन की पुस्तक का एक पीडीएफ है (मुझे नहीं पता कि यह कितना कानूनी है, कृपया सलाह दें): https://doc.lagout.org/programmation/Lisp/Object-Oriented%20Programming%20in%20Common%20Lisp_% 20A% 20Programmer% 27s% 20Guide% 20to% 20CLOS% 20% 5BKeene% 201989-01-11% 5D.pdf –

0

ऑब्जेक्ट्स/कक्षाओं के पुनर्गठन के बारे में क्या है ताकि प्रत्येक ऑब्जेक्ट जिसे आप गूंजना चाहते हैं, उसके पास सभी आवश्यक गुण हैं (और विरासत में) स्लॉट?

इस तरह आपको ऑब्जेक्ट पर गूंजते समय तर्क के रूप में उन्हें पास करने की आवश्यकता नहीं है, क्योंकि आपको जो वस्तु चाहिए वह पहले से ही ऑब्जेक्ट में संग्रहीत है।

3

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

कुछ इस तरह (नाटक हम पहले से ही है कक्षाएं वर्ग एक और वर्ग-बी) का प्रयास करें:

(defgeneric foo (object &key &allow-other-keys) 
    (:documentation "The generic function. Here is where the docstring is defined.")) 

(defmethod foo ((object class-a) &key &allow-other-keys) 
    (print "Code goes here. We dispatched based on type Class A.")) 

(defmethod foo ((object class-b) &key (x 1) (y 2) &allow-other-keys) 
    (print "Code goes here. We dispatched based on type Class B. We have args X and Y.")) 

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

अस्वीकरण: मैं एक आम लिस्प नौसिखिया हूं, इसलिए नमक के अनाज के साथ इसे ले लो!