如何创建自定义块

时间:2016-09-22 15:10:32

标签: ruby

我知道在ruby中我们可以使用while循环,但我想知道我是否可以创建一个自定义循环,所以我可以做这样的事情:

custom_while i < 5 do
    puts i
    i += 1
end

我目前有这段代码:

def custom_while(condition)
    loop do
        break if not condition
        yield
    end
end

i = 0
custom_while i < 5 do
    puts i
    i += 1
end

但是,在评估condition时,它始终为真(因为它只考虑i < 5 = true的第一次评估。

任何帮助将不胜感激!

注意:这仅用于教育目的。

2 个答案:

答案 0 :(得分:3)

你几乎拥有它。那么,你的问题是条件只评估一次?那么,我们知道我们可以根据需要经常评估哪种结构?那是对的:功能!所以,让我们将condition作为一个函数(或Ruby语言中的Proc):

def custom_while(condition)
  loop do
    break unless condition.()
    yield
  end
end

i = 0
custom_while -> { i < 5 } do
  puts i
  i += 1
end
# 0
# 1
# 2
# 3
# 4

遗憾的是,这并不像其他语言那样漂亮。 Ruby的语法和语义针对以1“函数”作为参数的方法进行了积极优化。 Ruby有一个特殊的语法和语义轻量级构造,即块。但是,只要你有一个以上,你就不幸了。

将此与具有适当块文字的语言(例如Smalltalk)进行比较。在Smalltalk中,您可以编写方法while:do:,并将其称为:

i := 0.
while: [i < 5] do: [Transcript write: i. i := i + 1].

事实上,在Smalltalk中,块的语法非常轻巧,因此语言中根本没有控制结构。 if / then / else只是Boolean的实例方法,例如:

i % 2 == 0 ifTrue: [Transcript write: "even"] ifFalse: [Transcript write: "odd"].

while实际上是Block的实例方法,所以实际上,您的示例如下所示:

i := 0.
[i < 5] whileTrue: [Transcript write: i. i := i + 1]

注意:我不保证Smalltalk代码,我没有测试它。

答案 1 :(得分:1)

问题是,条件在传入之前正在评估,因此它永远不会改变。

使条件成为您在循环内评估的函数,或使用宏使其更清晰。