我有一个接受块的方法,让我们在外面调用它。它又调用一个接受另一个块的方法,将其称为内部。
我想要发生的是外部调用内部,传递一个调用第一个块的新块。
这是一个具体的例子:
class Array
def delete_if_index
self.each_with_index { |element, i| ** A function that removes the element from the array if the block passed to delete_if_index is true }
end
end
['a','b','c','d'].delete_if_index { |i| i.even? }
=> ['b','d']
传递给delete_if_index的块由传递给each_with_index的块调用。
这在Ruby中是否可行,更广泛地说,我们对接收它的函数中的块有多少访问权限?
答案 0 :(得分:4)
您可以将块包装在另一个块中:
def outer(&block)
if some_condition_is_true
wrapper = lambda {
p 'Do something crazy in this wrapper'
block.call # original block
}
inner(&wrapper)
else
inner(&passed_block)
end
end
def inner(&block)
p 'inner called'
yield
end
outer do
p 'inside block'
sleep 1
end
我会说打开一个现有的块并更改其内容是做错了 TM ,也许继续传递会有帮助吗?我也要警惕路过有副作用的街区;我尝试保持lambdas确定性,并采取行动,如删除方法体中的东西。在复杂的应用程序中,这可能会使调试变得更加容易。
答案 1 :(得分:1)
也许这个例子选择不当,但你的具体例子与:
相同[1,2,3,4].reject &:even?
打开并修改一个块会让我感觉到代码味道。以一种使副作用明显的方式编写它是很困难的。
考虑到你的例子,我认为高阶函数的组合将做你想要解决的问题。
更新:正如评论中所指出的那样,它们不一样。 [1,2,3,4].reject(&:even?)
查看内容,而不是索引(并返回[1,3],而不是问题中的[2,4])。下面的内容与原始示例相同,但不会有很大变化。
[1,2,3,4].each_with_index.reject {|element, index| index.even? }.map(&:first)
答案 2 :(得分:0)
所以这是我自己问题的解决方案。传入的块被隐式转换为proc,可以通过&参数语法。然后proc存在于任何嵌套块的闭包内,因为它被分配给作用域中的局部变量,并且可以被它调用:
class Array
def delete_if_index(&proc)
ary = []
self.each_with_index { |a, i| ary << self[i] unless proc.call(i) }
ary
end
end
[0,1,2,3,4,5,6,7,8,9,10].delete_if_index {|index| index.even?}
=> [1, 3, 5, 7, 9]
这里将块转换为proc,并分配给变量proc,然后在传递给each_with_index的块中可用。