鉴于Ruby的表现力如何,我想知道是否有人试图创建一个模仿JS对象语法的类或模块。例如,在JS中,我当然可以这样做:
[1] var obj = {a: 'b'};
[2] obj.c = 'd';
[3] obj.a = 123
[4] obj['e'] = 'f';
[5] obj.e = obj['a']
在Ruby中,我现在可以拥有允许我这样做的代码:
[1] obj = {'a' => 'b'}.to_js
[2] # obj.c = 'd' << This is what I can't solve, 'c' is first defined here.
[3] obj.a = 123;
[4] obj['e'] = 'f'
[5] obj.e = obj['a']
只要我通过方括号或初始化获得符号,我就可以轻松存储K / V对并为设置者和getter创建instance methods
。
然而,我还没有弄清楚如何创建一个会响应'c'的对象,如果它没有定义,那么就做一些魔术。例如,
[]=(k, v)
作为括号表示法并执行相同的操作。有一个非常具体的Object#respond_to_missing?
,可以在其中加上特定的符号;但在一般情况下无法回应。
有三种可能的方法可以解决注释掉的第二种调用方式:
class A def b; puts 'c'; end end def always A.new end c = always c.b
鉴于此,可能有一种方法可以执行某种错误捕获,然后相应地挂钩对象。
利用我从未听说过的一些奇妙的红宝石功能。 Ruby是如此丰富的语言,这可能已经相当容易了。
以某种方式覆盖错误处理机制。我不知道有人会在大型的一般情况下如何做到这一点,但基本上你会告诉ruby,如果某个类的任何实例未能响应某个方法,你就会有一些通用的处理程序来处理的东西。
无论如何,如果有人在这里有任何想法,我认为这将是一个非常有趣的练习。谢谢!
答案 0 :(得分:2)
可能更好的方法:
class Hash
def method_missing(symbol, opts = nil)
string = symbol.to_s
self[string[0..-2].to_sym] = opts if string[-1..-1] == '=' and opts
self[symbol]
end
end
如果你想要进行子类化,那么你可以这样做:
class JSHash < Hash
def method_missing(symbol, opts = nil)
string = symbol.to_s
self[string[0..-2].to_sym] = opts if string[-1..-1] == '=' and opts
self[symbol]
end
end
class Hash
def to_js
JSHash.new.merge! self
end
end
我会暂时保持这种状态,以防其他人想到更好的方法。
答案 1 :(得分:1)
Hashie::Mash gem提供了这种行为。
require 'hashie/mash'
obj = Hashie::Mash.new ({'a' => 'b'})
obj.c = 'd'
obj.a = 123
obj['e'] = 'f'
obj.e = obj['a']
p obj # #<Hashie::Mash a=123 c="d" e=123>
p obj.to_hash # {"a"=>123, "c"=>"d", "e"=>123}
在分配嵌套哈希并将它们转换为蒙版时,它也具有魔力:
require 'hashie/mash'
obj = Hashie::Mash.new ({'a' => 'b'})
obj.c = 3
obj.d = { e: { f: {g: { h: 5 } } } }
puts obj.d.e.f.g.h # 5
puts obj.to_hash # {"a"=>"b", "c"=>3, "d"=>{"e"=>{"f"=>{"g"={"h"=>5}}}}}
这里的价格是性能。在简单的测量中,Hashie :: Mash是app。比Hash慢10倍:
require 'benchmark'
require 'hashie/mash'
n = 1000000
time = Benchmark.measure do
hash = {}
(0..n).each do |key|
hash[key] = key.to_s
end
end
puts 'Standard Hash'
puts time
n = 1000000
time = Benchmark.measure do
hash = Hashie::Mash.new
(0..n).each do |key|
hash[key] = key.to_s
end
end
puts 'Hashie::Mash'
puts time
在我的机器上,结果是:
Standard Hash
0.330000 0.030000 0.360000 ( 0.367405)
Hashie::Mash
3.350000 0.040000 3.390000 ( 3.394001)