कॉमन लिस्प में "सेट", "सेटक" और "सेटफ" के बीच अंतर क्या है?
कॉमन लिस्प में "सेट", "सेटक" और "सेटफ" के बीच अंतर क्या है?
जवाबों:
मूल रूप से, लिस्प में, कोई शाब्दिक चर नहीं थे - केवल गतिशील वाले। और SETQ या SETF नहीं था, सिर्फ SET फ़ंक्शन था।
अब क्या लिखा है:
(setf (symbol-value '*foo*) 42)
के रूप में लिखा गया था:
(set (quote *foo*) 42)
जो अंततः SETQ (सेट उद्धरण) से अलग हो गया:
(setq *foo* 42)
तब शाब्दिक चर हुआ, और SETQ भी उन्हें काम के लिए इस्तेमाल किया जाने लगा - तो यह अब SET के आसपास एक साधारण आवरण नहीं था।
बाद में, किसी ने SETF (SET फील्ड) का आविष्कार डेटा संरचनाओं को मान देने के एक सामान्य तरीके के रूप में किया, अन्य भाषाओं के एल-मूल्यों को प्रतिबिंबित करने के लिए:
x.car := 42;
के रूप में लिखा जाएगा
(setf (car x) 42)
समरूपता और सामान्यता के लिए, SETF ने SETQ की कार्यक्षमता भी प्रदान की। इस बिंदु पर यह कहना सही होगा कि SETQ एक निम्न-स्तरीय आदिम था, और SETF एक उच्च-स्तरीय ऑपरेशन था।
फिर प्रतीक मैक्रों हुए। ताकि प्रतीक मैक्रों पारदर्शी रूप से काम कर सकें, यह महसूस किया गया कि SETQ को SETF की तरह कार्य करना होगा यदि "चर" को सौंपा जा रहा है तो वास्तव में एक प्रतीक मैक्रो था:
(defvar *hidden* (cons 42 42))
(define-symbol-macro foo (car *hidden*))
foo => 42
(setq foo 13)
foo => 13
*hidden* => (13 . 42)
इसलिए हम वर्तमान समय में आते हैं: SET और SETQ पुरानी बोलियों के एट्रोफाइड अवशेष हैं, और संभवतः कॉमन लिस्प के अंतिम उत्तराधिकारियों से बूट किए जाएंगे।
f
वास्तव में कार्य के लिए खड़ा है , न कि फ़ील्ड (या फॉर्म , उस मामले के लिए), और संदर्भ प्रदान करता है, इसलिए जबकि फ़ील्ड के लिए सेट कुछ समझ में आता है, ऐसा लगता है कि यह सही नहीं हो सकता है।
set
एक फ़ंक्शन है। इस प्रकार यह पर्यावरण को नहीं जानता है। set
शाब्दिक चर नहीं देख सकता। यह अपने तर्क का केवल प्रतीक-मूल्य निर्धारित कर सकता है। setq
किसी भी अधिक "सेट उद्धृत" नहीं है। तथ्य यह setq
है कि एक विशेष रूप है, न कि एक मैक्रो दिखाता है।
(set ls '(1 2 3 4)) => Error - ls has no value
(set 'ls '(1 2 3 4)) => OK
(setq ls '(1 2 3 4)) => OK - make ls to (quote ls) and then have the usual set
(setf ls '(1 2 3 4)) => OK - same as setq so far BUT
(setf (car ls) 10) => Makes ls '(10 2 3 4) - not duplicated by setq/set
(setq ls '(((1))))
, (setf (car (car (car ls))) 5)
अपरिभाषित व्यवहार है, क्योंकि मूल्य ls
स्थिर है (जैसे सी में एक स्ट्रिंग शाब्दिक संशोधन)। के बाद (setq ls (list (list (list 1))))
, सी। की (setf (car (car (car ls))) 5)
तरह काम करता हैls->val->val->val = 5
setq
सिर्फ set
एक उद्धृत पहले arg के साथ की तरह है - (set 'foo '(bar baz))
जैसा है (setq foo '(bar baz))
। setf
दूसरी ओर, वास्तव में सूक्ष्म है - यह एक "अप्रत्यक्ष" जैसा है। मेरा सुझाव है http://www.nano.com/lisp/cmucl-tutorials/LISP-tutorial-16.html एक बेहतर तरीका के रूप में किसी भी सवाल का जवाब की तुलना में यह समझने आरंभ करने के लिए यहाँ दे सकते हैं ... संक्षेप में, हालांकि, setf
ले जाता है एक "संदर्भ" के रूप में पहला तर्क, ताकि उदाहरण के (aref myarray 3)
लिए setf
एक सरणी के अंदर एक आइटम सेट करने के लिए काम करेगा (पहले arg के रूप में )।
आप इसके setf
स्थान पर उपयोग कर सकते हैं set
या setq
इसके विपरीत नहीं, क्योंकि setf
चर के अलग-अलग तत्वों का मान भी सेट कर सकते हैं यदि चर में अलग-अलग तत्व हैं। नीचे दिए गए निर्वासन देखें:
सभी चार उदाहरण foo नाम के वेरिएबल को सूची (1, 2, 3) सौंपेंगे।
(set (quote foo) (list 1 2 3)) ;foo => (1 2 3)
(1 2 3)
(set 'foo '(1 2 3)) ;foo => (1 2 3) same function, simpler expression
(1 2 3)
(setq foo '(1 2 3)) ;foo => (1 2 3) similar function, different syntax
(1 2 3)
(setf foo '(1 2 3)) ;foo => (1 2 3) more capable function
(1 2 3)
setf
foo
एक नए मूल्य के लिए सूची के एक सदस्य को स्थापित करने की अतिरिक्त क्षमता है ।
foo ;foo => (1 2 3) as defined above
(1 2 3)
(car foo) ;the first item in foo is 1
1
(setf (car foo) 4) ;set or setq will fail since (car foo) is not a symbol
4
foo ;the fist item in foo was set to 4 by setf
(4 2 3)
हालाँकि, आप एक प्रतीक मैक्रो को परिभाषित कर सकते हैं जो किसी एकल आइटम को पुन: प्रस्तुत करता है foo
(define-symbol-macro foo-car (car foo)) ; assumes FOO => (1 2 3)
FOO-CAR
foo-car ;foo-car is now a symbol for the 1st item in foo
1
(setq foo-car 4) ;set or setq can set the symbol foo-car
4
foo ;Lisp macros are so cool
(4 2 3)
आप उपयोग कर सकते हैं defvar
यदि आपने पहले से चर को परिभाषित नहीं किया है और अपने कोड में बाद तक इसे एक मूल्य नहीं देना चाहते हैं।
(defvar foo2)
(define-symbol-macro foo-car (car foo2))
एक के बारे में सोच सकते हैं SET
और SETQ
निम्न स्तर के निर्माणों जा रहा है।
SET
प्रतीकों का मूल्य निर्धारित कर सकते हैं।
SETQ
चर का मान सेट कर सकते हैं।
फिर SETF
एक मैक्रो है, जो चीजों को स्थापित करने के कई प्रकार प्रदान करता है: प्रतीक, चर, सरणी तत्व, उदाहरण स्लॉट, ...
प्रतीकों और चरों के लिए कोई सोच सकता है जैसे कि SETF
विस्तार SET
और SETQ
।
* (macroexpand '(setf (symbol-value 'a) 10))
(SET 'A 10)
* (macroexpand '(setf a 10))
(SETQ A 10)
तो SET
और SETQ
कुछ की कार्यक्षमता को लागू करने के लिए उपयोग किया जाता है SETF
, जो कि अधिक सामान्य निर्माण है। कुछ अन्य उत्तर आपको थोड़ा और जटिल कहानी बताते हैं, जब हम प्रतीक मैक्रोज़ को ध्यान में रखते हैं।
मैं पिछले उत्तरों में जोड़ना चाहूंगा कि सेटफ़ मैक्रो है जो विशिष्ट फ़ंक्शन को कॉल करता है जो उसके पहले तर्क के रूप में पारित किया गया था। विभिन्न प्रकार के तर्कों के साथ सेटफ के मैक्रो विस्तार के परिणामों की तुलना करें:
(macroexpand '(setf a 1))
(macroexpand '(setf (car (list 3 2 1)) 1))
(macroexpand '(setf (aref #(3 2 1) 0) 1))
कुछ प्रकार के तर्कों के लिए "सेटफ फ़ंक्शन" कहा जाएगा:
(defstruct strct field)
(macroexpand '(setf (strct-field (make-strct)) 1))