2011-04-30 20 views
5

Tengo una función que tiene este aspecto:devolver un val perezoso en Scala

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

Esto logra básicamente lo que quiero hacer, que es devolver una función que abre un flujo de un archivo cuando se llama . Así código de cliente puede hacer esto:

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 

Pero lo que realmente me gustaría es devolver un val perezoso que fluye desde un archivo una vez que se hace referencia, así:

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 

¿Es posible Haga algo como esto, devuelva un valor perezoso, para que el código del cliente pueda tratarlo como un valor en lugar de una función.

+1

¿Por qué no acaba de hacer 'def streamer (path: String) = nueva FileReader (ruta)' y 'vago val = planStream Local.streamer ("/ home/someuser/.plan")'? –

+0

porque quiero suministrar este val a otro lugar en el código, intercambiable con una corriente que viene no desde un archivo, pero a partir de una toma de corriente o alguna otra cosa. Si paso planStream como argumento para otra función, no quiero que el archivo se abra todavía en ese punto. Quiero que se abra cuando el código del cliente esté realmente listo para comenzar a usar la transmisión (dentro de un bloque try finally). – traffichazard

+0

Tratar de tratar a Scala como si fuera un lenguaje perezosamente evaluado va en contra de su grano. Puede usar los parámetros 'val's' y '' by'' perezosos para crear contenedores con valor de evaluación diferida, pero no puedo recomendarlos como un estilo de programación de todo el sistema. –

Respuesta

15

no se puede “devolver un val perezoso” - código de cliente debe declarar como perezoso. Si no quiere forzar al cliente a declarar un val perezoso, se puede devolver un envoltorio en su lugar:

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

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

Y luego:

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

Usted podría más adelante equals, hashCode, etc. al objeto envuelto en LazyWrapper si los necesita.

+0

Me gusta esto. Soy nuevo en Scala y estoy intentando, más por gusto que nada, adherirme a un estilo funcional, así que estaba tratando de prescindir de un contenedor de clases. Pero su sugerencia es probablemente sobre la forma más delgada de hacer esto. – traffichazard

Cuestiones relacionadas