ruby - 如何创建自定义 while block

标签 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 的第一次求值。

任何帮助将不胜感激!

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

最佳答案

你几乎成功了。那么,您的问题是条件只被评估一次?好吧,我们知道我们可以根据需要经常评估的构造是什么?没错:函数!因此,让我们将 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 有一个特殊的句法和语义轻量级结构,即 block 。但是,一旦你有多个,你就倒霉了。

将此与具有适当 block 文字的语言进行比较,例如 Smalltalk。在 Smalltalk 中,您可以编写一个方法 while:do:,然后这样调用它:

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

事实上,在 Smalltalk 中, block 的语法非常轻量级,语言中根本没有控制结构。 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 代码不做任何保证,我没有测试它。

关于ruby - 如何创建自定义 while block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39642752/

相关文章:

javascript - @import 不适用于 Rails 项目中的 "application.css.scss"文件,仅适用于 "application.css"

ruby-on-rails - 重命名模型并更改对模型的所有引用后,对先前名称的引用仍然存在

Ruby:递增类型字符串的数量

ruby-on-rails - 用 capybara 填充隐藏区域

ruby - 递归例程中的 "stack level too deep"错误是否有解决方法?

ruby - 为什么我使用 Ruby 注入(inject)的斐波那契数列不起作用?

ruby-on-rails - 运行 Heckle 时出错? `current_code' : undefined method `translate' for Ruby2Ruby

ruby-on-rails - Rails 部署到 Amazon EC2 - 设备上没有剩余空间

ruby - 确认选择后下拉菜单中的值更改为默认值

android - 如何从 Ruby 的控制台输出中读取第 3 行?