字符串上的Splat(星号)运算符

时间:2013-01-15 16:23:48

标签: ruby monkeypatching

要编写splat运算符的自定义结果,必须实现to_a方法。 String类的示例:

class String
  def to_a
    self.split //
  end
end

irb> res = *'text'
=> ["t", "e", "x", "t"]

但是如果没有上面的monkeypatch,String类对to_a方法一无所知:

irb> String.respond_to? :to_a
=> false

所以问题是,在标准的“未修补”的String对象上应用splat运算符时会调用什么方法?

irb> res = *'text'
=> ['text']

3 个答案:

答案 0 :(得分:5)

首先关闭:调用String.respond_to?(:to_a)告诉您字符串 instance 是否响应to_a,它会告诉您String是否to_a 1}} class 回复to_a。如果您想知道字符串是否响应'text'.respond_to?(:to_a) # => false ,您必须询问字符串:

String

或者您可以询问to_a类是否有公共实例方法String.public_instance_methods.include?(:to_a) # => false

String

现在,原因为什么to_a不响应a = *'text'.chars # => ['a', 'b', 'c'] a = *'text'.codepoints # => [116, 101, 120, 116] a = *'text'.bytes # => [116, 101, 120, 116] a = *'text'.lines # => ['text'] 是因为它不清楚你想要什么:你想要一个字符数组吗?字形?线?代码点?字节?

{{1}}

至于为什么splat运算符的行为与你看到的一样,这似乎是语言规范中的一个极端情况。我甚至不能100%确定这是预期的行为。多个赋值的规范大约有4页,详见Ruby语言规范的第11.4.2.4节。

答案 1 :(得分:3)

Splat, by definition, returns the value in an array if the object doesn't respond to to_a:

it "assigns the splatted object contained into an array when the splatted object doesn't respond to to_a" do
  a = *1; a.should == [1]
end
警告:有点非官方,但相对有用。

答案 2 :(得分:1)

我不确定这是否足以满足您的需求,但您可以这样做:

1.9.3-p0 :008 > res = *'text'.chars
 => ["t", "e", "x", "t"]