3

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

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

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

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

3 回答 3

5

首先:调用String.respond_to?(:to_a)不会告诉你字符串实例是否响应,它会告诉你是否响应。如果您想知道一个字符串是否响应,您必须询问该字符串:to_aString to_ato_a

'text'.respond_to?(:to_a) # => false

或者您可以询问String该类是否具有公共实例方法to_a

String.public_instance_methods.include?(:to_a) # => false

现在,s 不响应的原因是因为不清楚你想要什么:你想要一个字符数组吗?字形的?线的?代码点?字节数?Stringto_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']

至于为什么 splat 运算符的行为方式如您所见,这似乎是语言规范中的一个极端情况。我什至不能 100% 确定这是预期的行为。多重赋值规范运行了将近 4 页,有关详细信息,请参阅 Ruby 语言规范的第 11.4.2.4 节。

于 2013-01-15T16:38:37.180 回答
3

Splat,根据定义,如果对象没有响应,则返回数组中的值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

警告:有点非官方,但相对可用。

于 2013-01-15T16:41:56.587 回答
1

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

1.9.3-p0 :008 > res = *'text'.chars
 => ["t", "e", "x", "t"]
于 2013-01-15T16:27:17.360 回答