Ruby 迭代器产量
Ruby iterator yield
我想知道为什么以下标记方法会产生不同的结果:
方法一:
def tag(html)
print "<#{html}>#{yield}</#{html}>"
end
方法二:
def tag(html)
print "<#{html}>"
print yield
print "</#{html}>"
end
当我运行使用上述方法在终端中输入以下代码时:
tag(:ul) do
tag(:li) { "It sparkles!" }
tag(:li) { "It shines!" }
tag(:li) { "It mesmerizes!" }
end
第一个给了我:
<li>It sparkles!</li><li>It shines!</li><li>It mesmerizes!</li><ul></ul>
第二个给了我:
<ul><li>It sparkles!</li><li>It shines!</li><li>It mesmerizes!</li></ul>
第二个是我正在寻找的输出。
为什么第一个方法在打印字符串中 'yield' 之前的内容之前先打印 'yield'?
主要问题是操作顺序。当您调用 print
时,它会立即打印 ,没有延迟,这可能会导致问题。
在 Ruby 中,处理 return 字符串的代码通常比处理导致打印等副作用的代码更容易。如果它们 return 字符串,您可以控制输出的位置。如果他们立即打印东西,您需要非常注意调用它们的顺序。
您在最终汇编中使用 tag(:ul)
调用调用该代码的方式实际上会很麻烦。您的方法的第二个版本巧合地正确排序。
解决这个问题并不容易。如果您 return 一个字符串,则只会使用三个 tag
调用中的最后一个字符串。如果您打印,则必须确保您使用的是第二种方法才能使其正常工作。
在 Rails 系统中,有一种方法可以捕获这些东西的输出以用于缓冲目的,但这是一件非常麻烦的事情,当你尝试处理所有情况时,它会变得非常混乱.
尽可能创建一些缓冲区,这些东西可以写入,然后当一切都完成后,用 print
或其他什么写出来。
只是回应@tadman 的回答:api 的评估顺序和不一致。您的块有时会 returns 字符串,有时会打印字符串作为副作用。
print "<#{html}>"
print yield
print "</#{html}>"
这里打印,然后yield。如果块 returns 是一个字符串(:li
块之一),那么它就打印在这里。如果它是一个 :ul
块,那么 它的副作用 会发生(打印 li 块)并且之后打印 nil。
另一种情况
print "<#{html}>#{yield}</#{html}>"
Ruby 必须 assemble 一个字符串才能打印。这意味着在任何打印之前屈服。这意味着在 打印开头 <ul>
之前 会发生副作用。由于 ul 块 returns nil,这就是它在字符串末尾打印为空的原因 (<ul></ul>
).
有道理吗?
我想知道为什么以下标记方法会产生不同的结果:
方法一:
def tag(html)
print "<#{html}>#{yield}</#{html}>"
end
方法二:
def tag(html)
print "<#{html}>"
print yield
print "</#{html}>"
end
当我运行使用上述方法在终端中输入以下代码时:
tag(:ul) do
tag(:li) { "It sparkles!" }
tag(:li) { "It shines!" }
tag(:li) { "It mesmerizes!" }
end
第一个给了我:
<li>It sparkles!</li><li>It shines!</li><li>It mesmerizes!</li><ul></ul>
第二个给了我:
<ul><li>It sparkles!</li><li>It shines!</li><li>It mesmerizes!</li></ul>
第二个是我正在寻找的输出。
为什么第一个方法在打印字符串中 'yield' 之前的内容之前先打印 'yield'?
主要问题是操作顺序。当您调用 print
时,它会立即打印 ,没有延迟,这可能会导致问题。
在 Ruby 中,处理 return 字符串的代码通常比处理导致打印等副作用的代码更容易。如果它们 return 字符串,您可以控制输出的位置。如果他们立即打印东西,您需要非常注意调用它们的顺序。
您在最终汇编中使用 tag(:ul)
调用调用该代码的方式实际上会很麻烦。您的方法的第二个版本巧合地正确排序。
解决这个问题并不容易。如果您 return 一个字符串,则只会使用三个 tag
调用中的最后一个字符串。如果您打印,则必须确保您使用的是第二种方法才能使其正常工作。
在 Rails 系统中,有一种方法可以捕获这些东西的输出以用于缓冲目的,但这是一件非常麻烦的事情,当你尝试处理所有情况时,它会变得非常混乱.
尽可能创建一些缓冲区,这些东西可以写入,然后当一切都完成后,用 print
或其他什么写出来。
只是回应@tadman 的回答:api 的评估顺序和不一致。您的块有时会 returns 字符串,有时会打印字符串作为副作用。
print "<#{html}>"
print yield
print "</#{html}>"
这里打印,然后yield。如果块 returns 是一个字符串(:li
块之一),那么它就打印在这里。如果它是一个 :ul
块,那么 它的副作用 会发生(打印 li 块)并且之后打印 nil。
另一种情况
print "<#{html}>#{yield}</#{html}>"
Ruby 必须 assemble 一个字符串才能打印。这意味着在任何打印之前屈服。这意味着在 打印开头 <ul>
之前 会发生副作用。由于 ul 块 returns nil,这就是它在字符串末尾打印为空的原因 (<ul></ul>
).
有道理吗?