了解一些Ruby代码

时间:2015-08-13 23:56:38

标签: ruby

我正在查看一些粗略的代码:

foo = true
while foo
  foo = newfoo() do
    thing1()
  end
end

这里发生了什么? do作业后面的end ... foo块有什么作用?

2 个答案:

答案 0 :(得分:2)

这是一个街区。在Ruby中存在块,proc和lambdas。请查看此链接以更好地了解它。

http://www.reactive.io/tips/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/

答案 1 :(得分:2)

你看到的是...在进行赋值之前将结束块传递给函数。 记住代码:

    [1,2].each do puts "xd" end

? 块“do puts”xd“end”在这里传递给“each”方法。

代码相同。 使用块调用newfoo()函数,在newfoo()中可以产生块,然后将newfoo()的返回值赋给foo。

但是你应该避免这种语法,如果块是短使用{}而不是do..end,如果不是 - 请考虑使用Proc.new。

两个代码示例,两者都有相同的结果:

def newfoo()
    yield()
    return false
end
foo = true
while(foo)
    foo = newfoo() do
        puts "JP2GMD"
    end
end

带存储过程的版本

truth_to_be_spoken = Proc.new { puts "JP2GMD" }

def newfoo()
    yield()
    return false
end
foo = true
while(foo)
    foo = newfoo() {truth_to_be_spoken.call()}
end

编辑以回复评论

“{}”在任何其他情况下肯定不比“do ... end”更好,而不是传递真正的短proc(在例子中就是这种情况)。

为什么你要在实际情况下使用proc而不是传递 result 参数(注意这只是显示语法的例子,而不是现实世界的使用!):原因很多,现在我能想到至少两个简单的例子:
1.只有在需要时,您才可以使用它来懒散地评估函数内部:

magic_number = Proc.new do
    x = # some really complicated code
    # it posts question on stackoverflow
    # to ask users, what number they would like to divide
    # waits an hour for answers 
    # and picks the one with most votes
    return x
end

def divide_numbers(divisor)
    if divisor == 0
        puts "Cannot into"
    else
        dividend = yield
        puts (dividend / divisor)
end
  1. 您可以使用函数内部已知的值并将它们作为参数传递(实际上,您使用迭代方法的方式!)。下面是两次使用的代码 - 参数与块“{}”一起传递,而在“{}”中将参数传递给声明的proc:

    second_power_double_printer = Proc.new do | param |     把帕拉姆     把帕拉姆 端

    [1,2,3,4] .each {| number | double_printer.call(number * number)}

  2. 为什么使用do..end / {}语法而不是传递阻止作为参数。 可能有更多的理由我无法想到正确的知识,但

    1. 内置方法以这种方式实现,因此坚持这一点更加清晰。
    2. Do ... end / {}将隐式为您创建匿名块。您不能使用参数执行此操作,例如:

      def f(proc)     proc.call() 端

      f(确实说“很难过:(”结束)

    3. 如果您使用匿名阻止,您至少可以犯一个错误 - 忘记传递阻止。 如果你使用函数参数,你至少可以犯两个错误 - 忘记传递任何东西(尽管 - 如果你使用IDE它会在这种情况下帮助你)并传递一些东西,这不是一个块 - 导致“未定义的方法调用“错误。