2011-11-13 9 views
5

मैं एक लिस्प फ़ंक्शन लिखने की कोशिश कर रहा हूं जो वैकल्पिक और कीवर्ड तर्क ले सकता है। समारोहमेरे पास एक ही फ़ंक्शन में वैकल्पिक तर्क और कीवर्ड तर्क कैसे हो सकते हैं?

(defun max-min (v &optional max min &keyword (start 0) (end nil)) 

जब मैं कीवर्ड तर्कों का उपयोग करके फ़ंक्शन को कॉल करने का प्रयास करता हूं लेकिन वैकल्पिक नहीं, तो मुझे एक त्रुटि मिलती है। मुझे क्या करना कोशिश कर रहा हूँ

(max-min #(1 2 3 4) :start 1 :end 2) 

मैं त्रुटि Error: :START' is not of the expected type REAL'

हो रही है मुझे लगता है कि इस वजह से यह max को :start बाध्य करने के लिए कोशिश कर रही है। में इससे कैसे चला सकता हूँ? धन्यवाद।

उत्तर

8

आपको उस फ़ंक्शन को आवश्यक पैरामीटर, वैकल्पिक पैरामीटर और फिर कीवर्ड पैरामीटर के साथ कॉल करने की आवश्यकता है। यह अन्यथा कैसे काम करना चाहिए? आपके कॉल में वैकल्पिक पैरामीटर की कमी है। यदि आप कॉल में कीवर्ड पैरामीटर निर्दिष्ट करना चाहते हैं, तो वैकल्पिक अब वैकल्पिक नहीं हैं।

(max-min #(1 2 3 4) 0 100 :start 1 :end 2) 

बुनियादी शैली नियम:

एक समारोह में कीवर्ड मानकों के साथ वैकल्पिक मिश्रण मत करो। उदाहरण के लिए सामान्य लिस्प इसे किसी स्थान पर उपयोग करता है और यह बग का स्रोत है।

CL:READ-FROM-STRING ऐसा उदाहरण है।

read-from-string string 
       &optional eof-error-p eof-value 
       &key start end preserve-whitespace 

http://www.lispworks.com/documentation/HyperSpec/Body/f_rd_fro.htm

यह काम करता है:

(read-from-string " 1 3 5" t nil :start 2) 

यह भी काम कर सकते हैं:

(read-from-string " 1 3 5" :start 2) 

लेकिन उपयोगकर्ता EOF-त्रुटि-पी निर्दिष्ट करना भूल गए और EOF-मूल्य । लिस्प संकलक शिकायत नहीं कर सकता है और उपयोगकर्ता क्यों यह 2.

5

पूर्णता 'खातिर पर शुरू नहीं होगी, तो आप तकनीकी रूप से यह आपूर्ति की तर्कों की सूची को पार्स द्वारा काम करने के लिए प्राप्त कर सकते हैं अपने आप को:

(defun max-min (v &rest args) 
    (flet ((consume-arg-unless-keyword (default) 
      (if (keywordp (first args)) 
       default 
       (pop args)))) 
    (let ((max (consume-arg-unless-keyword nil)) 
      (min (consume-arg-unless-keyword nil))) 
     (destructuring-bind (&key (start 0) (end nil)) args 
     ;; ... 
     )))) 

सामान्य रूप से, हालांकि, रेनर को सुनना अच्छा विचार है। यह एक जादुई डिजाइन की तरह दिखता है। यह विकास पर्यावरण दोनों (उदाहरण के लिए स्वचालित arglist डिस्प्ले को तोड़कर) और उपयोगकर्ता (टाइप त्रुटियों को खोजने के लिए कठिन बनाकर) को भ्रमित करता है: क्या होता है जब आप गलती से एक कीवर्ड पास करते हैं जहां आप किसी संख्या को पास करना चाहते हैं?)।