我对在 Ruby 中使用动态(而不是词法)范围变量感兴趣。
似乎没有直接的内置方式,就像let
在 Lisp 中一样。Christian Neukirchen提出了一种执行动态范围变量的可能方法。他在Dynamic
课堂上创建了一个“线程本地哈希”。我对此并不太疯狂。
然后我记得 Ruby 1.9 有一个tap
方法。我看到很多人用tap
命令链打印调试值。我认为它可以用来很好地模仿动态范围的变量。
下面是一个需要使用动态范围变量的情况示例,以及使用tap
.
如果我有一个博客可以发布这个并获得一些反馈,我会在那里做。相反,我来 S/O 批评这个想法。发表您的评论,我会给点赞最多的那个人提供正确答案。
情况
你有一个 ActiveRecord 对象,它代表一个Account
,每个 account has_many
Transaction
。ATransaction
有两个属性:
description
amount
你想在 上找到所有的总和,transactions
记住account
它amount
可以是nil
或者 a Float
(不,你不能批评)。
你的第一个想法是:
def account_value
transactions.inject(0){|acum, t| acum += t.amount}
end
这会在您第一次拥有 nil 数量时爆炸:
TypeError: nil can't be coerced into Fixnum
清洁解决方案
用于tap
临时定义amount = 0
。我们只希望这是临时的,以防我们忘记将其重新设置并保存transaction
0 值仍然存在。
def account_value
transactions.inject(0){|acm, t| t.amount.tap{|amount| amount ||=0; acm+=amount}; acm}
end
由于赋值为零,如果为零amount
是在tap
块内,我们不必担心忘记将其设置回nil
.
你怎么认为?