没有将 Struct 隐式转换为 Array

No implicit conversion of Struct into Array

我遇到了一个问题,我正在处理一个结构数组并想 transpose 它们,但遇到了一个错误:

TypeError (no implicit conversion of Struct into Array)

我认为(错误地)这种隐式转换只是在每个对象上调用 to_a(如果可用),尽管结构确实有一个 to_a method.

所以我的问题分为两部分:

这是一个产生错误的最小示例:

S = Struct.new(:a, :b)

a = S.new(1, 2)
# => #<struct S a=1, b=2>
b = S.new(3, 4)
# => #<struct S a=3, b=4>

[a, b].transpose
# TypeError (no implicit conversion of S into Array)

[a, b].map(&:to_a)
# => [[1, 2], [3, 4]]

# Therefore, the extra step I'd have to take to transpose:
[a, b].map(&:to_a).transpose
# => [[1, 3], [2, 4]]

在此先感谢您的帮助。

我在研究这个问题时实际上已经找到了这个问题的答案,所以将弹出答案,因为我之前搜索时找不到任何类似的东西。

Ruby 使用不同的强制方法进行显式与隐式转换:

| Explicit | Implicit |
|----------|----------|
| to_i     | to_int   |
| to_s     | to_str   |
| to_a     | to_ary   | 
| to_h     | to_hash  |
|----------|----------|

所以这里的问题是结构没有 to_ary 方法:

a.to_ary
# NoMethodError (undefined method `to_ary' for #<struct S a=1, b=2>)

因此,如果我们在有问题的结构上定义这个方法,我们可以隐式转换:

S.define_method(:to_ary) do
  self.to_a
end

[a, b].transpose
# => [[1, 3], [2, 4]]

瞧:)

if I can, how do I implement this implicit conversion?

您可以将块传递给 Struct.new,然后在那里定义您的方法:

S = Struct.new(:a, :b) do
  alias_method :to_ary, :to_a
end

secondly, why is this the case? Why can't structs be implicitly converted to arrays, yet can be explicitly converted?

这有点哲理,但是to_aryto_int等表示那些对象真的分别表示数组、整数等;他们只是不完全正确的类型。

to_ato_i的单字母变体不同,表示对象可能属于数组、整数等,但它们的底层结构完全不同,或者仅代表其真实语义的一部分。