If you load more than once with irb, it will fail.

Asked 3 months ago, Updated 3 months ago, 8 views

If you load ruby's code more than once on ruby's irb, it will fail.
Why is that?

Python is


import mymodule
import import lib

importlib.reload(mymodule)# Changes take effect

This will reflect changes to the module.

What would ruby do?


>>load"./big_step.rb"#2nd time
TypeError: superclass mismatch for class number

big_step.rb


class Number <Structure.new(:value)
    def to_s
        return value.to_s
    end

    default(environment)
        self
    end

    def inspect
        return "<#{self}>"
    end
end


class Multiple <Struct.new(:left,:right)
    def to_s
        return "#{left}*#{right}"
    end

    def inspect
        return "<#{self}>"
    end

    default(environment)
        Number.new (left.evaluate(environment).value*right.environment(environment).value)
    end
end

classAdd<Struct.new(:left,:right)
    def to_s
        return "#{left}+#{right}"
    end

    def inspect
        return "<#{self}>"
    end

    default(environment)
        Number.new (left.evaluate(environment).value + right.evaluate(environment).value)
    end
end

class Boolean<Struct.new(:value)
    def to_s
         value.to_s
    end

    def inspect
        "<<#{self}>>"
    end

    default(environment)
        self
    end
end

class LessThan<Struct.new(:left,:right)
    def to_s
        "#{left}<#{right}"
    end

    def inspect
        "<<#{self}>>"
    end

end

class Variable <Struct.new(:name)
    def to_s
        name.to_s
    end

    def inspect
        "<<#{self}>>"
    end

    default(environment)
        environment [name]
    end
end

class DoNothing
    def to_s
        "do-noting"
    end

    def inspect
        "<<#{self}>>"
    end

    def==(other_statement)
        other_statement.instance_of?(DoNothing)
    end
end


class Assign <Structure.new(:name,:expression)
    def to_s
        "#{name}=#{expression}"
    end

    def inspect
        "<<#{self}>>"
    end

    default(environment)
        environment.merge({name=>expression.value(environment)})
    end
end


class If <Struct.new(:condition,:true_exe,:false_exe)
    def to_s
        "if(#{condition}) {#{true_exe}} else {#{false_exe}}"
    end

    def inspect
        "<<#{self}>>"
    end

    default(environment)
        case condition.evaluate(environment)
        when Boolean.new(true)
            true_exe.validate(environment)
        when Boolean.new(false)
            false_exe.validate(environment)
        end
    end
end

class sequence <Struct.new(:first,:second)
    def to_s
        "#{first};#{second}"
    end

    def inspect
        "<<#{self}>>"
    end


    default(environment)
        second.evaluate(first.evaluate(environment))
    end
end


class While <Struct.new(:condition,:body)
    def to_s
        "while(#{condition}) {#{body}}"
    end

    def inspect
        "<<#{self}>>"
    end

    default(environment)
        case condition.evaluate(environment)
        when Boolean.new(true)
            validate(body.evaluate(environment))
        when Boolean.new(false)
            environment
        end
    end
end



ruby python irb

2022-09-30 11:32

2 Answers

After loading twice, class Number<Struct.new(:value) runs twice, but Struct.new(:value) generates and returns a new class, which results in an error specifying the wrong superclass when adding class definitions.

 irb(main): 001:0>Struct.new(:value)
=>#<Class:0x00000000aab338>
irb(main): 002:0>Struct.new(:value)
=>#<Class:0x00000000a9fb28>
irb(main): 003:0>Struct.new(:value)
=>#<Class:0x00000000a90790>
irb(main): 004:0>Struct.new(:value) ==Struct.new(:value)
=>false

http://docs.ruby-lang.org/ja/1.9.3/doc/spec=2fdef.html#class

If a class is already defined and you write the class definition with the same class name, you add the class definition.However, if you specify a superclass that is different from the original class, TypeError occurs.

class Foo<Array
  def foo
  end
end

# Add definition (even if superclass array is explicitly specified)
class Foo
  def bar
  end
end

# Invalid superclass specified error
class Foo<String
end
# =>superclass mismatch for class Foo (TypeError)


2022-09-30 11:32

I thought of some countermeasures.

Put the Strict.new subclass into a constant and create it only once.
Check with definde? to see if you have created a constant.

unless defined? Structure_value
  Structure_value = Structure.new(:value)
end
class Number <Struct_value
 # hereinafter abbreviated

If a class is defined, make it undefined before defining it.
Browse: https://stackoverflow.com/questions/11503558/how-to-undefine-class-in-ruby
Browse: http://www.iwazer.com/~iwazawa/diary/May 2013/ruby-remove-defined-class.html
Browse: http://qiita.com/ogawatti/items/0e69125ef4155241f598

if defined? Number
  Object.send(:remove_const,:Number)
end
class Number <Structure.new(:value)
 # hereinafter abbreviated

Create a single-ton structure factory.
The code is quite appropriate, so please refer to it only.

require'singleton'
classStructureFactory
  include Singleton
  def initialize
    @structures={}
  end
  def[](*key)
    [email protected]_key?(key)
      @structures[key]=Struct.new(*key)
    end
    [email protected] [key]
  end
  def self. [ ](*key)
    instance [*key]
  end
end
class Number <StructFactory [:value]
 # hereinafter abbreviated


2022-09-30 11:32

If you have any answers or tips


© 2023 OneMinuteCode. All rights reserved.