Ruby挑战 – 方法链和懒惰评估

阅读文章http://jeffkreeftmeijer.com/2011/method-chaining-and-lazy-evaluation-in-ruby/后 ,我开始寻找方法链和懒惰评估的更好解决方案。

我想我已经用下面的五个规范封装了核心问题; 谁能让他们全部通过?

一切顺利:子类化,委托,元编程,但后者不鼓励。

将依赖关系保持在最低限度是有利的:

require 'rspec' class Foo # Epic code here end describe Foo do it 'should return an array corresponding to the reverse of the method chain' do # Why the reverse? So that we're forced to evaluate something Foo.bar.baz.should == ['baz', 'bar'] Foo.baz.bar.should == ['bar', 'baz'] end it 'should be able to chain a new method after initial evaluation' do foobar = Foo.bar foobar.baz.should == ['baz', 'bar'] foobaz = Foo.baz foobaz.bar.should == ['bar', 'baz'] end it 'should not mutate instance data on method calls' do foobar = Foo.bar foobar.baz foobar.baz.should == ['baz', 'bar'] end it 'should behave as an array as much as possible' do Foo.bar.baz.map(&:upcase).should == ['BAZ', 'BAR'] Foo.baz.bar.join.should == 'barbaz' Foo.bar.baz.inject do |acc, str| acc << acc << str end.should == 'bazbazbar' # === There will be cake! === # Foo.ancestors.should include Array # Foo.new.should == [] # Foo.new.methods.should_not include 'method_missing' end it "should be a general solution to the problem I'm hoping to solve" do Foo.bar.baz.quux.rab.zab.xuuq.should == ['xuuq', 'zab', 'rab', 'quux', 'baz', 'bar'] Foo.xuuq.zab.rab.quux.baz.bar.should == ['bar', 'baz', 'quux', 'rab', 'zab', 'xuuq'] foobarbaz = Foo.bar.baz foobarbazquux = foobarbaz.quux foobarbazquuxxuuq = foobarbazquux.xuuq foobarbazquuxzab = foobarbazquux.zab foobarbaz.should == ['baz', 'bar'] foobarbazquux.should == ['quux', 'baz', 'bar'] foobarbazquuxxuuq.should == ['xuuq', 'quux', 'baz', 'bar'] foobarbazquuxzab.should == ['zab', 'quux', 'baz', 'bar'] end end 

琐碎,不是吗?

 class Foo < Array def self.bar other = new other << 'bar' other end def self.baz other = new other << 'baz' other end def bar other = clone other.unshift 'bar' other end def baz other = clone other.unshift 'baz' other end end 

to_s标准失败,因为1.9改变了Array#to_s工作方式。 更改为兼容性:

 Foo.baz.bar.to_s.should == ['bar', 'baz'].to_s 

我要蛋糕。

BTW - 这里的元编程会大大减少代码大小并极大地提高灵活性:

 class Foo < Array def self.method_missing(message, *args) other = new other << message.to_s other end def method_missing(message, *args) other = clone other.unshift message.to_s other end end 

这是受到Amadan答案的启发,但使用的代码更少:

 class Foo < Array def self.method_missing(message, *args) new 1, message.to_s end def method_missing(message, *args) dup.unshift message.to_s end end