在块/lambda 内产生问题

发布于 2024-10-17 13:05:46 字数 645 浏览 7 评论 0原文

我有以下 Ruby 代码:

# func1 generates a sequence of items derived from x
# func2 does something with the items generated by func1
def test(x, func1, func2)
    func1.call(x) do | y |
        func2.call(y)
    end
end

func1 = lambda do | x |
    for i in 1 .. 5
        yield x * i
    end
end

func2 = lambda do | y |
    puts y
end


test(2, func1, func2) # Should print '2', '4', '6', '8', and '10'

当然,这是行不通的。

test.rb:11: no block given (LocalJumpError)
    from test.rb:10:in `each'
    from test.rb:10
    from test.rb:4:in `call'
    from test.rb:4:in `test'
    from test.rb:20

I have the following Ruby code:

# func1 generates a sequence of items derived from x
# func2 does something with the items generated by func1
def test(x, func1, func2)
    func1.call(x) do | y |
        func2.call(y)
    end
end

func1 = lambda do | x |
    for i in 1 .. 5
        yield x * i
    end
end

func2 = lambda do | y |
    puts y
end


test(2, func1, func2) # Should print '2', '4', '6', '8', and '10'

This does not work, of course.

test.rb:11: no block given (LocalJumpError)
    from test.rb:10:in `each'
    from test.rb:10
    from test.rb:4:in `call'
    from test.rb:4:in `test'
    from test.rb:20

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

静赏你的温柔 2024-10-24 13:05:46

Lambda 不像常规方法那样隐式接受块,因此您的 func1 无法产生。这样做:

func1 = lambda do |x, &blk|
  for i in 1 .. 5
    blk.call(x * i)
  end
end

具体来说,我相信这是因为yield 会将控制发送回调用者的块,其中不包括 lambda 调用。所以下面的代码就像你“期望的”一样工作:

def foo
  (lambda { |n| yield(n) }).call(5)
end
foo { |f| puts f }  # prints 5

Lambdas don't implicitly accept blocks like regular methods do, so your func1 can't yield. Do this instead:

func1 = lambda do |x, &blk|
  for i in 1 .. 5
    blk.call(x * i)
  end
end

Specifically, I believe this is because yield would send control back to the caller's block, which would not include lambda invocations. So the following code works like you "expect":

def foo
  (lambda { |n| yield(n) }).call(5)
end
foo { |f| puts f }  # prints 5
东走西顾 2024-10-24 13:05:46

仅在 Ruby 1.9 中:

func1 = lambda do |x, &blk|
  for i in 1..5
    blk.call(x*i)
  end
end

In Ruby 1.9 only:

func1 = lambda do |x, &blk|
  for i in 1..5
    blk.call(x*i)
  end
end
‖放下 2024-10-24 13:05:46
def test(x, func1, func2)
    func1.call(x) do | y |
        func2.call(y)
    end
end

#change func1 to a method
def func1 x
    for i in 1 .. 5
        yield x * i
    end
end

#func2 may be either a method or a lambda
#I changed it for consistency, but you don't have to
def func2 y
    puts y
end


test(2, method(:func1), method(:func2))
def test(x, func1, func2)
    func1.call(x) do | y |
        func2.call(y)
    end
end

#change func1 to a method
def func1 x
    for i in 1 .. 5
        yield x * i
    end
end

#func2 may be either a method or a lambda
#I changed it for consistency, but you don't have to
def func2 y
    puts y
end


test(2, method(:func1), method(:func2))
别闹i 2024-10-24 13:05:46

根据 Nikita Misharin 的回答:[https://stackoverflow.com/a/45571976/2165560],我喜欢这:

def iterator(x)
  for i in 1 .. 5
    yield x * i
  end
end


iteratorWrapper = -> (m,&block) { iterator(m) {|n| block.call n}  }
iteratorWrapper.call(2) { |y| puts y }

它在这里回答了我的问题 [在 Ruby 中,可以使用 lambda 或 Proc 调用方法来调用迭代器吗?

通过包装迭代器,它可以任意传递给其他方法并迭代它们的块。

Based upon Nikita Misharin's answer here:[https://stackoverflow.com/a/45571976/2165560], I like this:

def iterator(x)
  for i in 1 .. 5
    yield x * i
  end
end


iteratorWrapper = -> (m,&block) { iterator(m) {|n| block.call n}  }
iteratorWrapper.call(2) { |y| puts y }

It answers my question here [In Ruby, can you use the lambda or or Proc call method to invoke an iterator?.

By wrapping the iterator it can be arbitrarily passed to other methods and iterate on their blocks.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文