2011-04-30 238 views
5

返回一個懶惰的VAL我有一個看起來像這樣的功能:在斯卡拉

package org.thimblr.io 
import java.io._ 
object Local { 
    def streamer(path: String) =() => new FileReader(path) 
} 

這基本上管理是我想做的事,這是返回打開從文件流功能,當它被稱爲。因此,客戶端代碼可以做到這一點:

val planStreamSource = Local.streamer("/home/someuser/.plan") 
//...passes the function on to somewhere else 
val planStream = planStreamSource() 
val firstByte = planStream.read 
//can now read from planStream 

但我真的很想是返回一個懶惰的VAL一旦它引用了從文件流,像這樣:

val planStream = Local.streamer("/home/someuser/.plan") 
//...passes the val on to somewhere else, without opening the file for reading yet 
val firstByte=planStream.read 
//...such that planStream was only just opened to allow the read 

是否有可能做這樣的事情,返回一個懶惰的val,以便客戶端代碼可以將它視爲一個值而不是一個函數?

+1

爲什麼你不只是做'高清流光(路徑:字符串)=新的FileReader(路徑)'和'懶惰VAL planStream = Local.streamer( 「/家/ SomeUser的/。計劃」)'? – 2011-04-30 17:26:33

+0

,因爲我想提供這個val到代碼中的其他地方,與不是來自文件的流交換,而是來自套接字或其他東西。如果我將planStream作爲參數傳遞給另一個函數,那麼我不希望該文件在此時打開。我希望在客戶端代碼實際準備好開始使用流時(在try finally塊中)打開它。 – traffichazard 2011-04-30 19:20:16

+0

試圖把斯卡拉當作懶惰評估的語言來對待它的穀物。您可以使用lazy'val'和by-name參數來創建延遲評估值容器,但我不推薦將其作爲系統範圍的編程風格。 – 2011-05-01 16:32:10

回答

15

你不能「返回一個懶惰VAL」 - 客戶端代碼必須聲明爲懶惰。如果你不希望強制客戶端來聲明一個懶惰的VAL,你可以返回的包裝來代替:

class LazyWrapper[T](wrp: => T) { 
    lazy val wrapped: T = wrp 
} 

object LazyWrapper { 
    implicit def unboxLazy[T](wrapper: LazyWrapper[T]): T = wrapper.wrapped 
} 

然後:

def streamer(path: String) = new LazyWrapper(new FileReader(path)) 

,你可以進一步向前equalshashCode等。如果您需要這些,請聯繫LazyWrapper中的包裝對象。

+0

我喜歡這個。我是新來的Scala,爲了實驗的緣故,我試圖堅持一種功能風格,所以我試圖在沒有類包裝的情況下做。但是你的建議可能是這樣做的最簡單的方法。 – traffichazard 2011-04-30 19:26:54