dav*_*k01 14 design-patterns scala lazy-loading lazy-evaluation lazy-initialization
我一直在学习scala,我得说它是一种非常酷的语言.我特别喜欢它的模式匹配功能和函数文字,但我来自javascript,ruby背景,这些语言中我最喜欢的模式之一是惰性函数和方法定义模式.javascript中的一个例子是
var foo = function() {
var t = new Date();
foo = function() {
return t;
};
return foo();
};
Run Code Online (Sandbox Code Playgroud)
带有小调整的相同代码在ruby中工作,您只需使用单例对象在执行计算后重新定义该方法.当涉及昂贵的计算时,这种事情非常方便,如果您需要结果,则提前不知道.我知道在scala中我可以使用缓存来模拟相同类型的结果,但我正在尝试避免条件检查,到目前为止,我的实验已经返回了负面结果.有没有人知道scala中是否存在惰性函数或方法定义模式?
注意:javascript代码来自Peter Michaux的网站.
Rex*_*err 30
JavaScript中所有复杂的代码似乎只是尝试缓存日期的值.在Scala中,您可以轻松地实现同样的目标:
lazy val foo = new Date
Run Code Online (Sandbox Code Playgroud)
并且,如果甚至不想制作val,但想要调用只在需要时才执行昂贵代码的函数,则可以
def maybeExpensive(doIt: Boolean, expensive: => String) {
if (doIt) println(expensive)
}
maybeExpensive(false, (0 to 1000000).toString) // (0 to 1000000).toString is never called!
maybeExpensive(true, (0 to 10).toString) // It is called and used this time
Run Code Online (Sandbox Code Playgroud)
模式expensive: => String被称为名称参数,您可以将其视为"给我一些将根据请求生成字符串的东西".请注意,如果您使用它两次,它将每次重新生成,这是Randall Schultz的便利模式所在:
def maybeExpensiveTwice(doIt: Boolean, expensive: => String) {
lazy val e = expensive
if (doIt) {
println(e)
println("Wow, that was " + e.length + " characters long!")
}
}
Run Code Online (Sandbox Code Playgroud)
现在只有在需要时才会生成(通过by-name参数)并存储它并在需要时重新使用它(通过lazy val).
所以这样做,而不是JavaScript方式,即使你可以让Scala看起来很像JavaScript.
Ran*_*ulz 19
Scala有lazy vals,除非使用val,否则不对其初始化程序进行求值.延迟val可以用作方法局部变量.
Scala还具有按名称方法参数,其实际参数表达式包含在thunk中,并且每次在方法体中引用形式参数时都会评估thunk.
这些可以用来实现惰性评估语义,例如Haskell中的默认语义(至少在我对Haskell的非常有限的理解中).
def meth(i: => Int): Something = {
// ^^^^^^ by-name parameter syntax
lazy val ii = i
// Rest of method uses ii, not i
}
Run Code Online (Sandbox Code Playgroud)
在此方法中,用作实际参数的表达式将被评估为零次(如果方法体的动态执行路径从不使用ii)或一次(如果它使用ii一次或多次).
Mr_*_*Qqn 10
你可以定义一个lazy val这是一个函数:
lazy val foo = {
val d = new Date
() => { d }
}
println(foo())
Run Code Online (Sandbox Code Playgroud)
foo() 现在将每次返回相同的Date对象,第一次调用foo时将初始化的对象.
为了解释一下代码,第一次调用foo()时{ val d = new Date; () => { d } },d被赋值给一个新的日期值,然后它计算最后一个表达式() => { d }并将其赋值给foo值.然后foo是一个没有参数返回d的函数.
我认为一些响应者对你提出这个问题的方式感到有些困惑.你想要的Scala构造是一个简单的惰性定义:
lazy val foo = new java.util.Date
Run Code Online (Sandbox Code Playgroud)
Date对象的构造最多只发生一次,并推迟到第一次引用foo.
| 归档时间: |
|
| 查看次数: |
18043 次 |
| 最近记录: |