如何为Scala传名函数的参数创建临时别名且保留原有执行逻辑
问题差异原因
两者行为不同是Scala不同求值策略的特性导致的:
f的入参x: => Int是传名参数,每次在f内部用到x都会重新计算一次传入的表达式test1直接将g()传入f,f执行x * x时会两次触发g()的计算,因此打印两次Hellotest2中用lazy val x = g(),lazy val惰性求值后会缓存结果,第一次用到x时执行g()打印一次,后续调用x直接返回缓存的42,因此只打印一次
解决方案
只需要把test2里的lazy val x改成无参def定义即可,这样每次调用x都会重新执行g(),完全匹配test1的原始行为,同时保留了给g()设置别名x的能力。
修改后的test2代码:
def test2() : Int = { def x = g() f(x) }
效果验证
修改后运行的输出和test1完全一致:
test1 Hello Hello 1764 test2 Hello Hello 1764
该改写方案是通用的:任何需要给传名参数的传入表达式设置别名、又不想改变原有多次求值语义的场景,都可以用def定义别名替代lazy val/普通val,不会改变原有代码逻辑。
内容的提问来源于stack exchange,提问作者Clinton
相关产品推荐
相关产品推荐

