我想知道为什么以下标记方法会产生不同的结果:
方法1:
def tag(html)
print "<#{html}>#{yield}</#{html}>"
end
方法2:
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>
第二个是我正在寻找的输出。
第一种方法如何打印&#39;产生&#39;在它打印之前发生的事情&#39; yield&#39;在字符串?
答案 0 :(得分:1)
主要问题是操作顺序。当您致电print
时,它会立即打印 ,没有延迟,这可能会导致问题。
在Ruby中,处理返回字符串的代码通常更容易,而不是导致打印等副作用的代码。如果它们返回字符串,则可以控制输出的位置。如果他们立即打印出来,你需要非常小心你打电话给他们的订单。
您使用tag(:ul)
调用在最终程序集中调用该代码的方式实际上会遇到麻烦。你的方法的第二个版本巧合地订购了正确的东西。
解决这个问题并不一定容易。如果返回一个字符串,则只会使用三个tag
调用中的最后一个字符串。如果你打印,你必须确保你使用第二种方法使它工作。
在Rails系统中,有一种方法可以捕获这些东西的输出以用于缓冲目的,但这是一个非常麻烦的尝试和做法,当你尝试处理所有情况时它会变得非常混乱。
在可能的情况下创建某些缓冲区,这些东西可以写入,然后当所有内容都用print
或其他任何内容写出来时。
答案 1 :(得分:1)
回应@ tadman的回答:评估的顺序和api的不一致。您的块有时会返回字符串,有时会将字符串作为副作用打印出来。
print "<#{html}>"
print yield
print "</#{html}>"
在这里打印,然后屈服。如果块返回一个字符串(:li
块之一),那么它就打印在这里。如果它是:ul
块,那么会产生副作用(打印li块),之后会打印出nil。
在另一种情况下
print "<#{html}>#{yield}</#{html}>"
Ruby必须组装一个字符串才能打印。这意味着在任何印刷之前屈服。这意味着在打印开头<ul>
之前,会发生副作用。由于ul块返回nil,这就是为什么它在字符串末尾打印为空(<ul></ul>
)。
有意义吗?