从迭代器调用迭代器,绑定参数

时间:2019-12-10 09:55:15

标签: ruby

为简单起见,让我们假设以下方法:

def inner(p)
  %w(a b c d).each {|x| yield("#{p} inner #{x}")}
end

我想要一个函数outer,它与inner相同,但是参数p绑定到某个值,例如

def outer
  inner('haha') // This is NOT correct. It's just to give you an idea.
end

这不起作用:如果我做了

outer {|q| puts q}

我得到一个 LocalJumpError:产量超出范围

一种解决方法显然是:

def outer
  inner('haha') { |x| yield(x) }
end

不是很优雅,因为一个 yield 仅产生下一个 yield 。一种更简洁的方法是显式地传递该块:

def inner(p, &block)
  %w(a b c d).each {|x| block.yield("#{p} inner #{x}")}
end

def outer(&block)
  inner('haha', &block)
end

尽管有人可能认为无论如何都要明确地编写block参数是更好的解决方案,因为我们可以从方法签名中看到已经预料到了一个块,但我仍然想知道是否存在一种干净的方法来实现我的目标而不用&block参数。

更新:修复代码中缺少&的情况。

1 个答案:

答案 0 :(得分:1)

这很好

def inner(p)
  %w(a b c d).each {|x| yield("#{p} inner #{x}")}
end

def outer(&block)
  inner('haha', &block)
end

def outer(&block)
  inner('haha', &block)
end

outer {|haha_and_item| puts haha_and_item}
# haha inner a
# haha inner b
# haha inner c
# haha inner d

outer似乎只是包装方法,其唯一目的是存储字符串haha。然后,它接受将根据Proc方法定义相应执行的块或inner

如果您想使用一种方法,那么您的示例就是我所知道的唯一可用语法。但是看来您正在寻找closurecarried one

这里是一个例子:

def inner(parameter)
  inner_closure = -> (runable) do
     %w(a b c d).each { |x| runable.("#{parameter} inner #{x}") }
  end
  inner_closure.curry
end

parameter = 'ahah'
runable = proc {|haha_and_item| puts haha_and_item}
outer = inner(parameter)
outer[runable] 

outer = inner('closure')
outer[runable]
# ahah inner a
# ahah inner b
# ahah inner c
# ahah inner d
# closure inner a
# closure inner b
# closure inner c
# closure inner d