2013-02-10 13 views
5

मेरे पास "आईपी", "डेट", "यूआरएल" नामक फ़ंक्शंस का एक सेट है।प्रोग्रामेटिक फ़ंक्शन परिभाषा: यहां "eval" से छुटकारा पाने के लिए कैसे?

इनके साथ, मैं "आईपी-आई", "डेट-इज़" इत्यादि का एक और सेट जेनरेट करना चाहता हूं।

अंततः मेरे पास निम्न समाधान है, जो ठीक काम कर रहा है, लेकिन यह "eval" का उपयोग करता है।

(loop for name in '(ip date url code bytes referer user-agent) do 
    (let ((c-name (intern (concatenate 'string (symbol-name name) "-IS")))) 
    (eval `(defun ,c-name (c) 
      #'(lambda (l) (equal (,name l) c)))))) 

क्या कोई मेरी मदद कर सकता है, "बुराई eval" से छुटकारा पाने के लिए कैसे? मेरे कार्यक्रम के लिए यह आवश्यक है कि फ़ंक्शन नाम सूची के रूप में प्रदान किए जाएं। तो कुछ marcro

(define-predicate ip) 
    (define-predicate date) 
    (define-predicate url) 

आदि के लिए एक कॉल

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

अग्रिम में धन्यवाद!

उत्तर

7

आपको यहां एक मैक्रो का उपयोग करना चाहिए। मैक्रोज का मूल्यांकन संकलन (या लोड) के दौरान किया जाता है और प्रोग्रामेटिक रूप से फ़ंक्शन परिभाषा उत्पन्न करने के लिए उपयोग किया जा सकता है। आपका कोड कुछ इस तरह लिखा जा सकता है:

(defmacro define-predicates (&rest names) 
    `(progn 
    ,@(loop 
      for name in names 
      collect (let ((c-sym (gensym)) 
         (l-sym (gensym))) 
        `(defun ,(intern (concatenate 'string (symbol-name name) "-IS")) (,c-sym) 
         #'(lambda (,l-sym) (equal (,name ,l-sym) ,c-sym))))))) 


(define-predicates ip date url) 

ध्यान दें कि प्रतीकों कार्यों में GENSYM का उपयोग कर उत्पन्न कर रहे हैं। इस विशेष मामले में, यह सख्ती से जरूरी नहीं है, लेकिन मैं आमतौर पर इसे इस तरह से करना पसंद करता हूं ताकि अगर मैं बाद के चरण में कोड को दोबारा जोड़ूं तो कोई लीक होने का कोई मौका नहीं है।

+0

निश्चित रूप से मैक्रो के लिए सही मामला। सही विकल्प के रूप में 'eval' का उपयोग करना एक बहुत ही दुर्लभ मामला है। –

+0

@ एलियास, आपने जो लिखा है उसके बारे में सिर्फ एक प्रश्न: ऐसा लगता है कि मैक्रोज़ को लोड समय पर मूल्यांकन नहीं किया जा सकता है क्योंकि उनका उपयोग कोड उत्पन्न करने के लिए संकलन समय पर किया जाता है। – tuscland

5

आप एक समारोह (एक मैक्रो के बजाय अन्य जवाब के रूप में) का उपयोग करना चाहते हैं, तो आप (setf fdefinition) का उपयोग करना चाहिए:

(loop for name in '(ip date url code bytes referer user-agent) do 
    (let ((c-name (intern (concatenate 'string (symbol-name name) "-IS")))) 
    (setf (fdefinition c-name) 
      (lambda (c) (lambda (l) (equal (funcall name l) c)))))) 
+0

हाय, यह वही है, जो मैं खोज रहा हूं, लेकिन किसी कारण से, यह मेरे लिए काम नहीं करता है। मैं समाधान समझता हूं लेकिन मुझे पता नहीं चला कि यह क्यों काम नहीं कर रहा है। मैं एसबीसीएल 1.0.58 – Patrick

+0

@ पैट्रिक का उपयोग कर रहा हूं: यह कैसे विफल हो जाता है? – sds

+0

यह संकलित करता है और यदि मैं कॉल करता हूं (कोड-"200" है) यह मुझे एक अनुमानित बंद देता है। इतनी देर तक सबकुछ ठीक है। लेकिन अगर मैं इसे अपने फ़िल्टर दिनचर्या के साथ बुलाता हूं, तो यह "केस" फ़ंक्शन "200" प्रदान करता है, तो यह सही ढंग से केस से मेल नहीं खाता है। अगर मैं इसे निर्देशित करता हूं, उदाहरण के लिए। (कोड को परिभाषित करें (जेड) "200"), फिर अपनी परिभाषा चलाएं, फिर (funcall (कोड-"200") "200") यह "INVALID-ARRAY-INDEX-ERROR" के साथ टूट जाता है। बल्कि अजीब बात है, क्योंकि हम यहाँ सरणी से निपट नहीं रहे हैं। – Patrick

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

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