How to dynamically create a local variable?

后端 未结 4 2209
温柔的废话
温柔的废话 2020-11-22 03:46

I have a variable var = \"some_name\" and I would like to create a new object and assign it to some_name. How can I do it? E.g.

var         


        
4条回答
  •  深忆病人
    2020-11-22 04:38

    It is true what others wrote that you cannot dynamically declare true variable in a local context. However you can achieve similar functionality with object attributes and since in the Ruby world everything is an object (even main context) you can easily extend those objects with new attributes. Of corse, this operation can be done dynamically. Let's examine this approach.

    Firstly, let's look at the main scope with irb.

    > self
    => main
    > self.class
    => Object
    > self.class.ancestors
    => [Object, Kernel, BasicObject]
    

    As you can see now, main is truly an object. Objects can have attributes which have same indirection property as variables. Normally, when declaring new class we would use attr_accessor method but main is already an instantiated object thus we cannot declare new attributes directly. Here module mixins come for rescue.

    variable_name = 'foo'
    variable_value = 'bar'
    
    variable_module = Module.new do
      attr_accessor variable_name.to_sym
    end
    
    include variable_module
    
    instance_variable_set("@#{variable_name}", variable_value)
    
    p foo # "bar"
    
    self.foo = 'bad'
    
    p foo # "baz"
    
    self.class.ancestors
    # [Object, #, Kernel, BasicObject]
    

    Now you see that main object was tainted with new module that introduced new attribute foo. For further inspection you can run methods to see that main now have two more methods foo and foo=.

    To simplify this operation I wrote metaxa gem which I highly encourage you to check out. This is example of how to use it.

    require 'metaxa'
    
    include Metaxa
    
    introduce :foo, with_value: 'foo'
    
    puts foo == 'foo' # true
    puts foo === get(:foo) # true
    
    set :foo, 'foobar'
    
    puts foo == 'foobar' # true
    puts foo === get(:foo) # true
    
    self.foo = 'foobarbaz'
    
    puts foo == 'foobarbaz' # true
    puts foo === get(:foo) # true     
    

提交回复
热议问题