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
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)
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
return@structures [key]
end
def self. [ ](*key)
instance [*key]
end
end
class Number <StructFactory [:value]
# hereinafter abbreviated
© 2024 OneMinuteCode. All rights reserved.