gpt4 book ai didi

ruby - 声明一个带有 yield 的 Ruby lambda

转载 作者:太空宇宙 更新时间:2023-11-03 18:13:03 27 4
gpt4 key购买 nike

我正在编写一种方法,将一个结构数组拆分为几个不同的数组,同时消除具有 nil 值的元素。

我想写的是:

def my_func(some_data)
f = lambda{|data| data.select{|m| yield(m).present? }.map { |m| [m.date, yield(m)]}}

x = f.call(some_data) {|m| m.first_var}
y = f.call(some_data) {|m| m.second_var}

return x, y
end

这似乎行不通,因为 Ruby 没有按照我预期的方式处理 lambda 内部的 yield 。

LocalJumpError: no block given(yield)

有没有办法定义 f 以便 x 和 y 给出我正在寻找的结果?

最佳答案

您不能像现在这样从 lambda yield 直接传递给传递给它的非显式 block (有关@cremno 提供的源代码,请参阅下面的注释,显示 yield 只能在方法和单例类定义中使用)

源提取:

if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) {
rb_vm_localjump_error("no block given (yield)", Qnil, 0);
}

主要解决方案:

你可以像这样用显式 block 来做到这一点

f = lambda do |data,&block| 
data.select do |m|
block.call(m)
end.map do |m|
[m, block.call(m)]
end
end
d = ["string",1,2,3,4,"string2"]
f.call(d) { |n| n.is_a?(String) }
#=>[["string", true], ["string2", true]]

次要解决方案:

但是,如果 block 被传递给方法,您也可以在 lambdayield,例如

def some_method(data)
#extended syntax for readability but works fine as
#f = lambda{|data,&block| data.select{|m| block.call(m) }.map { |m| [m, block.call(m)]}}
f = lambda do |data|
data.select do |m|
yield(m)
end.map do |m|
[m, yield(m)]
end
end
f.call(data)
end
some_method(["string",1,2,3,4,"string2"]) { |s| s.is_a?(String) }
#=> [["string", true], ["string2", true]]

Tertiary Soultion:(更接近您的问题的次要解决方案的产物)

定义一个辅助方法

def some_method(some_data)
x = filter(some_data) {|m| m.is_a?(String)}
y = filter(some_data) {|m| m.is_a?(Fixnum)}
[x, y]
end
def filter(data)
data.select do |m|
yield(m)
end.map do |m|
[m, yield(m)]
end
end
some_method(["string",1,2,3,4,"string2"])
#=>[
[["string", true], ["string2", true]],
[[1, true], [2, true], [3, true], [4, true]]
]

四元溶液:

技术上还有第四个选项,我发布它只是为了您的利益,因为它尽可能地代表您的原始代码。这是迄今为止 4 中最奇怪的模式(几乎和四元这个词一样奇怪),但我想说得更透彻:

def some_method(some_data)
f = lambda{|data| data.select{|m| yield(m) }.map { |m| [m, yield(m)]}}
if block_given?
f.call(some_data)
else
x = some_method(some_data) {|m| m.is_a?(String)}
y = some_method(some_data) {|m| m.is_a?(Fixnum)}
[x,y]
end
end
some_method(["string",1,2,3,4,"string2"])
#=>[
[["string", true], ["string2", true]],
[[1, true], [2, true], [3, true], [4, true]]
]

关于ruby - 声明一个带有 yield 的 Ruby lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30649742/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com