没有将 Enumerator 隐式转换为 Array

No implicit conversion of Enumerator into Array

我有:

qs = ["all=true", "limit=-1"]
value = ["agent", "service", "token"]

此代码:

qs.concat value.map do |val|
  "#{field}=#{val}"
end

最终出现以下错误:

`concat': no implicit conversion of Enumerator into Array (TypeError)`

而这段代码:

values = value.map do |val|
  "field=#{val}"
end
qs.concat values

没有。

它们有什么区别?

您的问题是由为链式方法调用提供块时的不同优先级引起的。在您的情况下,您使用以下代码:

qs.concat value.map do |val|
  "#{field}=#{val}"
end

Ruby 假定您的意思如下:

qs.concat(value.map) do |val|
  "#{field}=#{val}"
end

也就是说,Ruby 将块传递给忽略块的第一个方法(即 qs.concat)。因为 Array#map returns an Enumerator 如果你没有通过一个块,你就会得到你看到的错误。

为了解决这个问题,可以使用大括号形式传递块,即:

qs.concat value.map { |val|
  "#{field}=#{val}"
}

在这种形式下,块总是传递给 "last" 方法,u.e。你的 map.

无论如何,如果对运算符的优先级有任何疑问,最好使用显式括号或中间变量来向人类读者和 Ruby 解释器说明如何您的代码应该可以工作。

当你说qs.concat value.map do |val|时,do属于什么? (提示:不是 value.map!)

不确定时使用括号。

qs=["all=true", "limit=-1"]
value=["agent", "service", "token"]
qs.concat(value.map do |val|
  "field=#{val}"
end)

{...}do...end 更典型,而且优先级可以计算出来,因此您实际上不需要括号,因为 {...} 会转到 value.map 而不是比 qs.concat。这也有效:

qs=["all=true", "limit=-1"]
value=["agent", "service", "token"]
qs.concat value.map { |val|
  "field=#{val}"
}