ऐसे कई कारण हैं, जिनका उपयोग नहीं करना चाहिए EVAL
।
शुरुआती लोगों का मुख्य कारण है: आपको इसकी आवश्यकता नहीं है।
उदाहरण (सामान्य लिस्प मानते हुए):
विभिन्न ऑपरेटरों के साथ एक अभिव्यक्ति का मूल्यांकन करें:
(let ((ops '(+ *)))
(dolist (op ops)
(print (eval (list op 1 2 3)))))
यह बेहतर लिखा है:
(let ((ops '(+ *)))
(dolist (op ops)
(print (funcall op 1 2 3))))
ऐसे बहुत से उदाहरण हैं जहां शुरुआती सीखने वाले लिस्प को लगता है कि उन्हें ज़रूरत है EVAL
, लेकिन उन्हें इसकी ज़रूरत नहीं है - चूंकि अभिव्यक्तियों का मूल्यांकन किया जाता है और कोई फ़ंक्शन भाग का मूल्यांकन भी कर सकता है। अधिकांश समय EVAL
मूल्यांकनकर्ता की समझ की कमी दर्शाता है।
मैक्रों के साथ भी यही समस्या है। अक्सर शुरुआती मैक्रोज़ लिखते हैं, जहां उन्हें फ़ंक्शंस लिखना चाहिए - यह नहीं समझना कि मैक्रोज़ वास्तव में क्या हैं और यह नहीं समझना कि एक फ़ंक्शन पहले से ही काम करता है।
यह नौकरी का उपयोग करने के लिए अक्सर गलत उपकरण है EVAL
और यह अक्सर इंगित करता है कि शुरुआती सामान्य लिस्प मूल्यांकन नियमों को नहीं समझता है।
यदि आपको लगता है कि आपको जरूरत है EVAL
, तो जांचें कि क्या कुछ पसंद है FUNCALL
, REDUCE
या APPLY
इसके बजाय इसका उपयोग किया जा सकता है।
FUNCALL
- तर्कों के साथ एक फ़ंक्शन को कॉल करें: (funcall '+ 1 2 3)
REDUCE
- मानों की सूची पर एक फ़ंक्शन को कॉल करें और परिणाम गठबंधन करें: (reduce '+ '(1 2 3))
APPLY
- एक फ़ंक्शन को एक सूची के साथ तर्कों के रूप में कॉल करें (apply '+ '(1 2 3))
:।
प्रश्न: क्या मुझे वास्तव में eval की आवश्यकता है या क्या संकलक / मूल्यांकनकर्ता पहले से ही मैं वास्तव में क्या चाहता हूं?
EVAL
थोड़ा और अधिक उन्नत उपयोगकर्ताओं से बचने के मुख्य कारण :
आप यह सुनिश्चित करना चाहते हैं कि आपका कोड संकलित किया गया है, क्योंकि कंपाइलर कई समस्याओं के लिए कोड की जांच कर सकता है और तेजी से कोड उत्पन्न करता है, कभी-कभी बहुत अधिक (यह कारक 1000; ;-)) से तेज कोड होता है।
कोड जो निर्माण किया गया है और मूल्यांकन करने की आवश्यकता है, उसे जल्द से जल्द संकलित नहीं किया जा सकता है।
उपयोगकर्ता इनपुट का मनमाना उपयोग सुरक्षा समस्याओं को खोलता है
मूल्यांकन के कुछ उपयोग EVAL
गलत समय पर हो सकते हैं और बिल्ड समस्याएं पैदा कर सकते हैं
सरलीकृत उदाहरण के साथ अंतिम बिंदु समझाने के लिए:
(defmacro foo (a b)
(list (if (eql a 3) 'sin 'cos) b))
इसलिए, मैं एक मैक्रो लिखना चाहता हूं जो पहले पैरामीटर के आधार पर SIN
या तो उपयोग करता है या COS
।
(foo 3 4)
करता है (sin 4)
और(foo 1 4)
करता है (cos 4)
।
अब हमारे पास हो सकता है:
(foo (+ 2 1) 4)
यह वांछित परिणाम नहीं देता है।
एक तो FOO
चर को चिह्नित करके मैक्रो की मरम्मत करना चाहता है :
(defmacro foo (a b)
(list (if (eql (eval a) 3) 'sin 'cos) b))
(foo (+ 2 1) 4)
लेकिन फिर भी यह काम नहीं करता है:
(defun bar (a b)
(foo a b))
चर का मान अभी संकलन समय पर ज्ञात नहीं है।
बचने का एक सामान्य महत्वपूर्ण कारण EVAL
: इसका उपयोग अक्सर बदसूरत हैक्स के लिए किया जाता है।