मेटा-प्रोग्रामिंग रूबी - रूबी, मेटाप्रोग्रामिंग

मैं हर वर्ग चर को ट्रैक करने की कोशिश कर रहा हूंमेटाप्रोग्रामिंग द्वारा इतिहास। मैं इस तरह के प्रश्न पूछने के प्रशंसक नहीं हूं लेकिन मुझे इन्हें लिखने में सक्षम होने में 5 घंटे लग गए और अब मुझे नहीं पता कि कैसे आगे बढ़ना है (मैं "रूबी के लिए नया हूं, और यह पहली बार है" मेटाप्रोग्रामिंग के साथ खेल रहा है)।

मेरी समझ में; कब attr_accessor_with_history कक्षा में शुरू होता है, इसे निष्पादित करना चाहिएकोड युक्त है। इस प्रकार, जब भी यह विधि शुरू होती है, मेटाप्रोग्रामिंग की योग्यता के अनुसार प्रत्येक वर्ग में वर्णित समस्या के लिए अपनी विधि होगी।

मेरे द्वारा सबमिट किए गए कोड में, पाठकों को ठीक से प्रारंभ किया जाता है लेकिन मैं कोड के बारे में ऐसा नहीं कह सकता class_eval अंश। मुझे स्पष्टीकरण की आवश्यकता है कि कोड क्यों काम नहीं कर रहा है, और सामान्य रूप से मेटाप्रोग्रामिंग क्यों है।

class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s
attr_reader attr_name
attr_reader attr_name + "_history"

class_eval "%Q{
@#{attr_name}_history=[nil]
def #{attr_name}=(value)
#{attr_name}=value
#{attr_name}_history.push(value)
end
}
"
end
end

class Klass
attr_accessor_with_history :kamil
def initialize(value)
kamil = value
end
end

a = Klass.new(5)
a.kamil = 1
puts "#{a.kamil_history}"

उत्तर:

जवाब के लिए 0 № 1

स्वयं पर एक सेटर विधि को कॉल करने के लिए, आपको लिखना होगा self.foo = bar। अगर आप बस लिखते हैं foo = bar यह सिर्फ स्थानीय चर नामित बार बनाएगा और किसी भी विधि को कॉल नहीं करेगा। तो आपको तदनुसार लाइन 11 और 23 को बदलने की आवश्यकता होगी।

उद्धरण के अंदर% Q {} का उपयोग करके, आपका पूरा evalवास्तव में सिर्फ एक स्ट्रिंग का मूल्यांकन करेंगे। आपको% Q {} या उद्धरण का उपयोग करना चाहिए - दोनों नहीं। वास्तव में आपको शायद एक स्ट्रिंग का उपयोग नहीं करना चाहिए, लेकिन ब्लॉक और उपयोग के साथ class_eval को कॉल करना चाहिए define_method ब्लॉक के अंदर।


जवाब के लिए 4 № 2

सास कोर्स, हुह? आपको पता होना चाहिए कि इंस्टेंस वैरिएबल @ साइन के साथ शुरू होना चाहिए। तो उदाहरण के लिए अपनी प्रारंभिक विधि में क्या है kamil? यदि यह एक आवृत्ति चर है तो यह होना चाहिए @kamil। मैं यह भी सुझाव दूंगा कि आप अपना संशोधन करें class_eval इस विचार के संबंध में तर्क।

संपादित करें:

@#{attr_name}_history=[nil]

मैं इस कोड को कुछ विधि में भी डालूंगा क्योंकि किसी भी विधि से आपके इंस्टेंस वैरिएबल को प्रारंभ करना बहुत अच्छा नहीं है।


उत्तर № 3 के लिए 1

आपकी विधि के अंदर कोड "डीफ़attr_accessor_with_history (attr_name) "हर बार जब आप इस विधि को कॉल करते हैं तो उसे बुलाया जाता है। जब आप इसे लिखते हैं तो इसे अपनी कक्षा में बुलाते हैं कक्षा Klass attr_accessor_with_history: कामिल ..

जब रूबी इस लाइन को संसाधित करता है"attr_accessor_with_history: kamil" यह वास्तव में विधि class.attr_accessor_with_history विधि से कोड चलाएगा। Class_eval के अंदर एक स्ट्रिंग को कोड के रूप में व्याख्या किया गया है क्योंकि यह आपके द्वारा सीधे लिखा गया था।

अंत में, आपका व्याख्या कोड इस तरह होगा:

कक्षा Klass ..

@ Kamil_history = [शून्य]

def kamil=(value)
kamil=value
kamil_history.push(value)
end

समस्या देखें? यह @ kamil = value होना चाहिए, अन्यथा यह विधि "kamil =" को फिर से कॉल करेगा, उदाहरण आवृत्ति @ kamil तक नहीं पहुंच रहा है।

इसी तरह, यह "@ kamil_history.push (..)" होना चाहिए।

आप यहां कामकाजी कोड पा सकते हैं: http://maxivak.com/ruby-metaprogramming-and-own-attr_accessor/


संबंधित सवाल
सबसे लोकप्रिय