गतिशील निरंतर असाइनमेंट


139
class MyClass
  def mymethod
    MYCONSTANT = "blah"
  end
end

मुझे त्रुटि देता है:

SyntaxError: डायनेमिक निरंतर असाइनमेंट त्रुटि

इसे गतिशील स्थिरांक क्यों माना जाता है? मैं इसे एक स्ट्रिंग सौंप रहा हूँ।


34
डायनेमिक कॉन्स्टेंट कुछ ऐसा है जैसे ड्राई वाटर :)
fl00r

39
यह नहीं कहता कि स्थिर गतिशील है। यह कहता है कि असाइनमेंट गतिशील है।
sepp2k

जवाबों:


141

आपकी समस्या यह है कि हर बार जब आप विधि को चलाते हैं तो आप स्थिरांक को एक नया मान दे रहे हैं। यह अनुमति नहीं है, क्योंकि यह निरंतर गैर-स्थिर बनाता है; भले ही स्ट्रिंग की सामग्री समान हो (फिलहाल, किसी भी तरह), वास्तविक स्ट्रिंग ऑब्जेक्ट अपने आप में अलग-अलग होता है, जब विधि को बुलाया जाता है। उदाहरण के लिए:

def foo
  p "bar".object_id
end

foo #=> 15779172
foo #=> 15779112

शायद अगर आपने अपने उपयोग के मामले को समझाया — तो आप एक विधि में स्थिरांक का मूल्य क्यों बदलना चाहते हैं - हम आपको बेहतर क्रियान्वयन में मदद कर सकते हैं।

शायद आपके पास कक्षा पर एक उदाहरण चर होगा?

class MyClass
  class << self
    attr_accessor :my_constant
  end
  def my_method
    self.class.my_constant = "blah"
  end
end

p MyClass.my_constant #=> nil
MyClass.new.my_method

p MyClass.my_constant #=> "blah"

यदि आप वास्तव में किसी विधि में किसी स्थिरांक का मान बदलना चाहते हैं, और आपका स्थिरांक एक स्ट्रिंग या एक ऐरे है, तो आप #replaceवास्तव में वस्तु को बदले बिना वस्तु को नए मूल्य पर ले जाने के लिए विधि को 'धोखा' दे सकते हैं और उपयोग कर सकते हैं :

class MyClass
  BAR = "blah"

  def cheat(new_bar)
    BAR.replace new_bar
  end
end

p MyClass::BAR           #=> "blah"
MyClass.new.cheat "whee"
p MyClass::BAR           #=> "whee"

19
ओपी ने कभी नहीं कहा कि वह स्थिरांक के मूल्य को बदलना चाहता था , लेकिन सिर्फ एक मूल्य निर्दिष्ट करना चाहता था। इस रूबी त्रुटि के लिए लगातार उपयोग का मामला तब है जब आप अन्य रन-टाइम एसेट्स (चर, कमांड-लाइन तर्क, ईएनवी) से एक विधि में मूल्य का निर्माण करते हैं, आमतौर पर एक कंस्ट्रक्टर जैसे def initialize(db,user,password) DB=Sequel.connect("postgres://#{user}:#{password}@localhost/#{db}") end। यह उन मामलों में से एक है जहां रूबी के पास कोई सरल तरीका नहीं है।
अरनौद मीरुत

2
@ArnaudMeuret उस स्थिति के लिए आप एक उदाहरण चर (उदाहरण @variable) चाहते हैं, स्थिर नहीं। अन्यथा आप DBहर बार जब आप उस वर्ग के एक नए उदाहरण को फिर से असाइन करेंगे, तो आप फिर से असाइन हो जाएंगे ।
Ajedi32

2
@ Ajedi32 यह स्थिति आमतौर पर बाहरी बाधाओं से पैदा होती है, जैसे कि सीक्वल के साथ मेरे उदाहरण जैसे विकल्प नहीं। मेरा कहना है कि रूबी द्वारा कुछ स्कॉप्स में एक स्थिरांक को एक मान निर्दिष्ट करने की अनुमति है, अन्य नहीं। यह असाइनमेंट को निष्पादित करने के लिए बुद्धिमानी से चुनने के लिए डेवलपर तक हुआ करता था। इस पर रूबी बदल गई। सभी के भले के लिए नहीं।
अरनौद मीरूट

2
@ArnaudMeuret मैं स्वीकार करूँगा कि मैंने पहले कभी भी सीक्वल का उपयोग नहीं किया है, इसलिए मैं इसे 100% निश्चितता के साथ नहीं कह सकता, लेकिन सीक्वल के दस्तावेज़ीकरण पर नज़र रखने से मुझे ऐसा कुछ भी नहीं दिखाई देता है जो कहता है कि आपको Sequel.connectडीबी के साथ एक निरंतरता का परिणाम सौंपना है । वास्तव में, प्रलेखन स्पष्ट रूप से कहता है कि यह सिर्फ एक सिफारिश है। यह मेरे लिए एक बाहरी बाधा की तरह नहीं है।
अजेडी 32

@ Ajedi32 1) मैंने कभी नहीं लिखा कि (स्थिरांक का नाम या यहां तक ​​कि आपको इसे कहीं और रखना था) यह सिर्फ एक उदाहरण है 2) बाधा यह है कि आपके सॉफ़्टवेयर में आवश्यक जानकारी नहीं हो सकती है जब तक कि आप आम तौर पर एक गतिशील संदर्भ में नहीं होते हैं। ।
अरनौद मीरूट

69

क्योंकि रूबी में स्थिरांक को बदलने का मतलब नहीं है, रूबी आपको कोड के कुछ हिस्सों में उन्हें असाइन करने से हतोत्साहित करता है जो कि एक से अधिक बार निष्पादित हो सकते हैं, जैसे कि अंदर के तरीके।

सामान्य परिस्थितियों में, आपको कक्षा के अंदर निरंतर को परिभाषित करना चाहिए:

class MyClass
  MY_CONSTANT = "foo"
end

MyClass::MY_CONSTANT #=> "foo"

यदि किसी कारण से, हालांकि आपको वास्तव में एक विधि के अंदर एक स्थिरांक को परिभाषित करने की आवश्यकता है (शायद कुछ प्रकार के मेटाप्रोग्रामिंग के लिए), तो आप निम्न कार्य कर सकते हैं const_set:

class MyClass
  def my_method
    self.class.const_set(:MY_CONSTANT, "foo")
  end
end

MyClass::MY_CONSTANT
#=> NameError: uninitialized constant MyClass::MY_CONSTANT

MyClass.new.my_method
MyClass::MY_CONSTANT #=> "foo"

फिर भी, const_setकुछ ऐसा नहीं है जिसे आपको वास्तव में सामान्य परिस्थितियों में सहारा लेना चाहिए। यदि आप सुनिश्चित नहीं हैं कि आप वास्तव में इस तरह से स्थिरांक देना चाहते हैं, तो आप निम्नलिखित विकल्पों में से एक पर विचार करना चाह सकते हैं:

कक्षा चर

कक्षा चर कई मायनों में स्थिरांक की तरह व्यवहार करते हैं। वे एक वर्ग पर गुण हैं, और वे उस वर्ग के उपवर्गों में सुलभ हैं जिन्हें वे परिभाषित किया गया है।

अंतर यह है कि वर्ग चर को परिवर्तनीय माना जाता है, और इसलिए इसे बिना किसी समस्या के अंदर के तरीकों को सौंपा जा सकता है।

class MyClass
  def self.my_class_variable
    @@my_class_variable
  end
  def my_method
    @@my_class_variable = "foo"
  end
end
class SubClass < MyClass
end

MyClass.my_class_variable
#=> NameError: uninitialized class variable @@my_class_variable in MyClass
SubClass.my_class_variable
#=> NameError: uninitialized class variable @@my_class_variable in MyClass

MyClass.new.my_method
MyClass.my_class_variable #=> "foo"
SubClass.my_class_variable #=> "foo"

वर्ग गुण

वर्ग विशेषताएँ "एक वर्ग पर उदाहरण चर" का एक प्रकार हैं। वे वर्ग चर की तरह थोड़ा व्यवहार करते हैं, सिवाय इसके कि उनके मूल्यों को उपवर्गों के साथ साझा नहीं किया जाता है।

class MyClass
  class << self
    attr_accessor :my_class_attribute
  end
  def my_method
    self.class.my_class_attribute = "blah"
  end
end
class SubClass < MyClass
end

MyClass.my_class_attribute #=> nil
SubClass.my_class_attribute #=> nil

MyClass.new.my_method
MyClass.my_class_attribute #=> "blah"
SubClass.my_class_attribute #=> nil

SubClass.new.my_method
SubClass.my_class_attribute #=> "blah"

आवृत्ति के चर

और सिर्फ पूर्णता के लिए मुझे शायद उल्लेख करना चाहिए: यदि आपको एक मूल्य निर्दिष्ट करने की आवश्यकता है जो केवल आपकी कक्षा के तुरंत बाद निर्धारित की जा सकती है, तो एक अच्छा मौका है जो आप वास्तव में एक सादे पुराने उदाहरण चर के लिए देख सकते हैं।

class MyClass
  attr_accessor :instance_variable
  def my_method
    @instance_variable = "blah"
  end
end

my_object = MyClass.new
my_object.instance_variable #=> nil
my_object.my_method
my_object.instance_variable #=> "blah"

MyClass.new.instance_variable #=> nil

33

रूबी में, कोई भी चर जिसका नाम एक बड़े अक्षर से शुरू होता है, एक स्थिरांक है और आप इसे केवल एक बार असाइन कर सकते हैं। इनमें से कोई एक विकल्प चुनें:

class MyClass
  MYCONSTANT = "blah"

  def mymethod
    MYCONSTANT
  end
end

class MyClass
  def mymethod
    my_constant = "blah"
  end
end

2
धन्यवाद किसी ने उल्लेख किया है कि "कोई भी चर जिसका नाम बड़े अक्षर से शुरू होता है वह स्थिर है!"
ubienewbie


0

आप बड़े अक्षरों के साथ एक चर का नाम नहीं दे सकते हैं या रूबी एक स्थिर मान लेगा और यह चाहेगा कि यह मूल्य स्थिर बना रहे, जिस स्थिति में यह मूल्य बदल रहा है वह एक "गतिशील निरंतर असाइनमेंट त्रुटि" होगी। कम मामले के साथ ठीक होना चाहिए

class MyClass
  def mymethod
    myconstant = "blah"
  end
end

0

रूबी को यह पसंद नहीं है कि आप किसी विधि के अंदर निरंतर असाइन कर रहे हैं क्योंकि यह पुन: असाइनमेंट को जोखिम में डालता है। मेरे सामने कई एसओ जवाब एक विधि के बाहर इसे असाइन करने का विकल्प देते हैं - लेकिन कक्षा में, जो इसे असाइन करने के लिए एक बेहतर जगह है।


1
एसओ जॉन को अजीब। यो आप जो वर्णन कर रहे हैं उसका कुछ नमूना कोड जोड़कर इस उत्तर को बेहतर बनाने पर विचार कर सकते हैं।
क्लेप्टस

0

डोरियन और फ्रॉग्ज के लिए कई धन्यवाद मुझे सरणी (और हैश) विधि #replace के बारे में याद दिलाने के लिए, जो "किसी सरणी या हैश की सामग्री को प्रतिस्थापित कर सकता है।"

यह धारणा कि एक CONSTANT का मूल्य बदला जा सकता है, लेकिन एक कष्टप्रद चेतावनी के साथ, रूबी के कुछ वैचारिक गलत कदमों में से एक है - ये या तो पूरी तरह से अपरिवर्तनीय होना चाहिए, या स्थिर विचार को पूरी तरह से डुबो देना चाहिए। एक कोडर के दृष्टिकोण से, एक निरंतर घोषणात्मक और जानबूझकर है, अन्य के लिए एक संकेत है कि "यह मूल्य वास्तव में अपरिवर्तनीय है जो केवल घोषित या असाइन किया गया है।"

लेकिन कभी-कभी "स्पष्ट घोषणा" वास्तव में अन्य, भविष्य के उपयोगी अवसरों को प्रभावित करती है। उदाहरण के लिए...

वहाँ रहे हैं उदाहरण के लिए, एक आरईपीएल की तरह शीघ्र लूप से फिर से लोड हो रहा है ARGV, तो के माध्यम से अधिक (बाद) OptionParser.parse ARGV का पुनर्प्रसारण: वैधानिक उपयोग के मामले में जहां एक "निरंतर के" मूल्य वास्तव में परिवर्तित करने की आवश्यकता हो सकता है! कॉल - वॉइला! "कमांड लाइन आर्ग्स" एक पूरी नई गतिशील उपयोगिता देता है।

व्यावहारिक समस्या या तो अनुमान लगाने योग्य धारणा के साथ है कि "ARGV एक स्थिर होना चाहिए", या ऑप्टपर्स की अपनी इनिशियलाइज़ विधि में, जो ARGV के असाइनमेंट को बाद के प्रोसेसिंग के लिए var @default_arv पर हार्ड कोड को कोड करता है - वह सरणी (ARGV) वास्तव में एक पैरामीटर होना चाहिए, जहां पुन: पार्स और फिर से उपयोग को प्रोत्साहित करना, जहां उपयुक्त हो। एक उचित डिफ़ॉल्ट (कहते हैं, ARGV) के साथ उचित पैरामीटर, कभी भी "स्थिर" ARGV को बदलने की आवश्यकता से बचता है। बस कुछ 2 some-विचारों के गुण ...

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.