2012-09-17 10 views
5

मेरे पास कई स्लॉट वाले क्लास हैं। मेरे पास उस वर्ग की ऑब्जेक्ट्स बनाने के लिए एक बिल्डर फ़ंक्शन भी है जो कि निम्न कार्य '(:id "john" :name "John Doe" :age 42) को उस फ़ंक्शन में पास करने से उन स्लॉट मानों के साथ एक नई ऑब्जेक्ट का निर्माण करेगा। सूचियों की सूची का उपयोग करके, मैं एक से अधिक ऑब्जेक्ट उत्पन्न करने के लिए उस फ़ंक्शन का उपयोग करूंगा।मैं किसी कीवर्ड को स्लॉट तक पहुंचने के लिए उपयुक्त प्रतीक में कैसे परिवर्तित कर सकता हूं?

मैं :id जैसे किसी स्लॉट नाम से SLOT-VALUE पर किसी कीवर्ड से कैसे परिवर्तित कर सकता हूं?

धन्यवाद।

उत्तर

3

find-symbol और symbol-name फ़ंक्शंस आपके लिए सहायक होंगे। यदि defclass और slot-value एक ही पैकेज में होती हैं, तो आप उन कार्यों के रूप में इस का उपयोग कर सकते हैं:

(defclass person() 
    ((id :initarg :id) 
    (name :initarg :name) 
    (age :initarg :age))) 

(slot-value (make-instance 'person :id "john" :name "John Doe" :age 42) 
      (find-symbol (symbol-name :id))) 

हैं defclass और slot-value दो अलग संकुल में होती हैं, तो आप find-symbol पैकेज का नाम देने के लिए जहां defclass होता है की जरूरत है:

(in-package #:common-lisp-user) 

(defpackage #:foo 
    (:use #:common-lisp) 
    (:export #:person)) 

(defpackage #:bar 
    (:use #:common-lisp #:foo)) 

(in-package #:foo) 

(defclass person() 
    ((id :initarg :id) 
    (name :initarg :name) 
    (age :initarg :age))) 

(in-package #:bar) 

(slot-value (make-instance 'person :id "john" :name "John Doe" :age 42) 
      (find-symbol (symbol-name :id) 'foo)) 

(find-symbol name &optional (package (sane-package)))

फ़ंक्शन: पैकेज में STRING नामक प्रतीक को वापस करें। यदि ऐसा प्रतीक पाया जाता है तो दूसरा मान है: आंतरिक,: बाहरी या: इंगित करने के लिए कि प्रतीक कैसे सुलभ है। यदि कोई प्रतीक नहीं मिला है तो दोनों मान शून्य हैं।

(symbol-name symbol)

फंक्शन: एक स्ट्रिंग के रूप वापसी प्रतीक का नाम।

+0

ग्रेट उत्तर। धन्यवाद। – sbenitezb

10

कीवर्ड, वर्ग के लिए initargs रहे हैं तो आप बस फोन कर सकते हैं के माध्यम से MAKE-INSTANCEAPPLY:

(defclass person() 
    ((id :initarg :id ) 
    (name :initarg :name) 
    (age :initarg :age))) 


CL-USER > (mapcar 
      (lambda (initargs) 
      (apply #'make-instance 'person initargs)) 
      '((:id "john" :name "John Doe" :age 42) 
      (:id "mary" :name "Mary Doe" :age 42))) 

(#<PERSON 402027AB7B> #<PERSON 402027AC33>) 
+0

मुझे आपके "अधिक कार्यात्मक" दृष्टिकोण पसंद हैं। – sbenitezb

+3

@WhiteCat उन सूचियों के साथ 'मेक-इंस्टेंस' को कॉल करने के बारे में आपका प्रश्न था? मैं आपके प्रश्न को अलग-अलग समझ गया क्योंकि प्रश्न का शीर्षक और शरीर कहता है, "मैं एक कीवर्ड को स्लॉट तक पहुंचने के लिए उपयुक्त प्रतीक में कैसे परिवर्तित कर सकता हूं?" और "मैं एक कीवर्ड से कैसे परिवर्तित कर सकता हूं जैसे आईडी: स्लॉट नाम से 'SLOT-VALUE' उपयोग कर सकता है?"। यदि आपका असली लक्ष्य केवल 'मेक-इंस्टेंस' को कॉल करने के लिए है, न कि 'स्लॉट-वैल्यू', रेनर जोसविग का समाधान जाने का एक तरीका है। – dkim

+2

@dkim: मेरा प्रश्न बिल्कुल लिखा गया था, जिसे आपने सही ढंग से उत्तर दिया था। मैंने पहले (खोज-प्रतीक ...) 'के साथ प्रयास किया था लेकिन पैकेज के रूप में KEYWORD का उपयोग किया था, इसलिए यह काम नहीं किया। रेनर के जवाब ने मुझे एक और परिप्रेक्ष्य दिया, जिस पर मैंने विचार नहीं किया और यह सही समाधान कौन सा है। धन्यवाद दोनों। – sbenitezb

-1

सीएल के इस मूर्खता मेरे समाधान किया गया था:

(defun locate-symbol 
     (inst kw) 
    (let* ((slot-name (symbol-name kw)) 
     (slot-def (find slot-name 
         (clos:compute-slots (class-of inst)) 
         :test #'(lambda (name sd) 
            (string= name 
              (symbol-name (clos:slot-definition-name sd))))))) 
    (if slot-def 
     (clos:slot-definition-name slot-def) 
     (error "Can't find a slot definition named ~s." slot-name)))) 

(defun gets 
     (self slot-name) 
    "Get a value of a slot by its name (keyword)" 
    (slot-value self (locate-symbol self slot-name))) 

(defun sets! 
     (self slot-name value) 
    "Set a value of a slot by its name (keyword)" 
    (setf (slot-value self (locate-symbol self slot-name)) 
     value)) 

तो अब आप कर सकते हैं:

(defvar obj (make-instance '<some-class>)) 
(sets! obj :some-slot "some value") 
(format t "-> ~a~%" (gets obj :some-slot)) 
1

मुझे लगता है कि यह काफी पुराना है, लेकिन मुझे लगता है कि सबसे महत्वपूर्ण बात यहाँ किए जाने के लिए है:

slot-value उस तरह का प्रयोग न करें!

आदेश एक्सेसर पाने के लिए, :accessor या :reader स्लॉट विकल्पों का उपयोग, और निर्माता के लिए मान पास करने के लिए, का उपयोग :initarg:

(defclass foo() 
    ((bar :accessor foo-bar :initarg :bar))) 

इसका मतलब यह है: एक गेटर विधि और एक setf विस्तारक नामित बनाने foo-bar, और इस स्लॉट के मान को आरंभ करने के लिए :bar से make-instance नामक एक कीवर्ड तर्क का उपयोग करें।

(make-instance 'foo :bar "quux") 

या, यदि आप initargs की संपत्ति की सूची प्राप्त (के रूप में रेनर पहले से ही पता चला था):

अब आप इस तरह इस तरह के एक वस्तु का दृष्टांत कर सकते हैं

(let ((initargs (list :bar "quux"))) ; getting this from somewhere 
    (apply #'make-instance 'foo initargs)) 

फिर आप प्राप्त कर सकते हैं इस तरह मूल्य:

(foo-bar some-foo) 

और setf हमेशा की तरह के साथ सेट:

(setf (foo-bar some-foo) "wobble") 

आप :reader बजाय :accessor उपयोग करते हैं, की स्थापना की अनुमति नहीं है। यह अपरिवर्तनीयता के इरादे को संवाद करने के लिए अक्सर उपयोगी होता है।

Slot-value वास्तव में किसी ऑब्जेक्ट के जीवनकाल में विशेष स्थितियों के लिए है, जैसे initialize-instance के तरीकों के साथ खेलते समय। यह एक उन्नत विषय है।

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

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