2012-01-21 11 views
6

मैं अपनी नई भाषा के रूप में लिस्प लेने की कोशिश कर रहा हूं, और मुझे कुछ मुद्दों के बारे में पता चल रहा है कि इस कार्य के प्रत्येक तत्व पर फ़ंक्शन के कुछ हिस्सों को कैसे काम किया जाए।तर्क के रूप में एक सूची के साथ defun

इस के आसपास पाने के लिए सीखने के प्रयोजन के लिए, मैं डिवीजन के एक काफी बुनियादी रूप में लिखने के लिए croak नहीं है जब सूची के तत्वों में से एक 0 कर रहे हैं कोशिश कर रहा हूँ (लेकिन इसके बजाय सिर्फ रिटर्न 0)

(defun divtest (elements) 
    (dolist (x elements) 
    (if (zerop x) 0()) 
    (/ elements))))) 

(divtest '(20 2 5)) 

कौन सा पैदावार:

मैं के रूप में इस चलाने का प्रयास

*** - /: (20 2 5) is not a number 

असफलता का बिंदु इस तथ्य में निहित है कि मैं उन्हें कार्य में पास करने से पहले सूची में तत्वों को निकालने वाला नहीं हूं (इस मामले में, न तो/न ही डॉलीस्ट कार्य के रूप में कार्य करता है, क्योंकि x कभी 0 का मूल्यांकन नहीं करता है)। यदि मैं सही हूं, तो क्या कोई मुझे बता सकता है कि यह "निष्कर्षण" कैसे करें?


ध्यान दें: यह सवाल one that I've asked earlier से संबंधित है, लेकिन जैसा कि मैंने स्पष्ट नहीं है जिसके बारे में पिछले जवाब का हिस्सा वास्तव में यह काम करने की अनुमति के रूप में इस विशिष्ट समस्या के साथ इरादा कर रहा हूँ मैं मूल बातें में आगे जाने का फैसला किया

उत्तर

5

/ एक या अधिक संख्याओं के तर्क के रूप में लेता है, लेकिन आपके कोड में आप इसे एक सूची पास कर रहे हैं - स्पष्ट रूप से यह काम नहीं करेगा। फ़ंक्शन apply आपका मित्र यहां है - (apply #'foo a b (list c d e))(foo a b c d e) के बराबर है। फ़ंक्शन का उपयोग करने के लिए apply पर तर्कों को नोट करें और अंतिम सूची वैकल्पिक हैं, इसलिए (apply #'/ '(20 2 5))(/ 20 2 5) के बराबर है।

इसके अलावा, शून्य को हटाने का आपका प्रयास काम नहीं करेगा। dolist तर्क सूची elements में प्रत्येक आइटम के लिए अपने शरीर का मूल्यांकन कर रहा है, लेकिन आप वास्तव में elements की सामग्री को बदलने के लिए कुछ भी नहीं कर रहे हैं (dolist के मूल्यांकन का नतीजा स्रोत तत्व को पुन: असाइन नहीं किया गया है जैसा कि आप उम्मीद करते हैं)।

फ़ंक्शन remove-if (और इसके विनाशकारी समकक्ष, delete-if) जो आप ढूंढ रहे हैं। निम्नलिखित दिखाता है कि इसका उपयोग कैसे करें (इसमें कई वैकल्पिक तर्क होते हैं, जिन्हें आपको इस उद्देश्य के बारे में चिंता करने की आवश्यकता नहीं है)।

(defun divtest (elements) 
    (apply #'/ (remove-if #'zerop elements))) 

भी ध्यान रखें कि यह ठीक से व्यवहार नहीं होगा अगर elements सूची अपनी पहली तत्व के रूप में शून्य है (यह मानते हुए मैं समझता हूँ कि समारोह के कर का मतलब क्या)। तो आप इसके बजाय कुछ

(defun divtest (elements) 
    (apply #'/ (first elements) (remove-if #'zerop (rest elements)))) 

अधिक जानकारी के लिए हाइपरपेक देखें।

+2

लागू –

+0

के बजाय RedUCE का उपयोग करें बस उत्सुक: उस की उपयोगिता क्या होगी? – Hugh

+0

इस तरह आप मनमाने ढंग से लंबी सूचियों को संसाधित कर सकते हैं न कि केवल कॉल-एर्ग्यूमेंट-लिमेंट (मानक सीएल स्थिरांक) अधिकतम लंबाई। सामान्य लिस्प में एक कार्यान्वयन निर्भर अधिकतम संख्या तर्क है। यह संख्या 50 या बड़ी होनी चाहिए। इसका मतलब है कि एक कार्यान्वयन केवल 50 तर्क (या अधिक) का समर्थन करने की आवश्यकता है। इस प्रकार आपका उपरोक्त फ़ंक्शन कुछ कार्यान्वयन में विफल हो सकता है जहां संख्याओं की सूची फ़ंक्शन/अनुमतियों को बुलाए गए तर्कों की संख्या से अधिक लंबी है। –

0

(/ elements) के स्थान पर आजमाएं। मुझे लगता है (?) जो लिस्प की अधिकांश बोलीभाषाओं में काम करना चाहिए।

+0

आप उद्धृत करने के लिए की आवश्यकता होगी की तरह लिख सकते हैं कि '/' जब तक आप '/' के डेटा सेल में फ़ंक्शन सौंपा है। – Hugh

1

या आप इसे इस

(defun divtest (elements) 
    (if (member 0 elements) 
     0 
     (apply #'/ elements))) 
1
(block exit 
    (reduce #'/ '(1 2 3 0 5) 
      :key (lambda (x) 
       (if (zerop x) 
        (return-from exit 0) 
        x))))