2012-03-23 10 views
11

Como se discutió en la publicación de blog de Eric Lippert Closing over the loop variable considered harmful, el cierre de la variable de bucle en C# puede tener consecuencias inesperadas. Estaba tratando de entender si el mismo "gotcha" aplicado a Scala.Cerrando la variable de bucle en Scala

En primer lugar, ya que esta es una pregunta Scala, voy a tratar de explicar C# ejemplo de Eric Lippert añadir algunos comentarios a su código

// Create a list of integers 
var values = new List<int>() { 100, 110, 120 }; 

// Create a mutable, empty list of functions that take no input and return an int 
var funcs = new List<Func<int>>(); 

// For each integer in the list of integers we're trying 
// to add a function to the list of functions 
// that takes no input and returns that integer 
// (actually that's not what we're doing and there's the gotcha). 
foreach(var v in values) 
    funcs.Add(()=>v); 

// Apply the functions in the list and print the returned integers. 
foreach(var f in funcs) 
    Console.WriteLine(f()); 

La mayoría de la gente espera que este programa para imprimir 100, 110, 120 . en realidad, imprime 120, 120, 120. la cuestión es que la función () => v añadimos a la lista funcs se cierra sobre la variable de v , no el valor de v. A medida que v cambia el valor, en el primer ciclo, los tres cierres que agregamos a la lista funcs "ven" la misma variable v, que (cuando los aplicamos en el segundo ciclo) tiene un valor 120 para todos.

he tratado de traducir el código de ejemplo para Scala:

import collection.mutable.Buffer 
val values = List(100, 110, 120) 
val funcs = Buffer[() => Int]() 

for(v <- values) funcs += (() => v) 
funcs foreach (f => println(f())) 
// prints 100 110 120 
// so Scala can close on the loop variable with no issue, or can it? 

¿Se Scala de hecho no sufren el mismo problema o han acabo traducida código de Eric Lippert mal y no han podido reproducirlo?

Este comportamiento ha tropezado a muchos desarrolladores de C# valientes, por lo que quería asegurarme de que no haya problemas similares extraños con Scala. Pero también, una vez que comprendes por qué C# se comporta de la manera en que lo hace, el resultado del código de ejemplo de Eric Lippert tiene sentido (es básicamente la forma en que funcionan los cierres): entonces, ¿qué está haciendo Scala de forma diferente?

+2

'v' no es una variable mutable en el código de Scala. Tenga en cuenta que las comprensiones 'for' no son' 'for' loops. El código Scala realmente se traduce a algo mucho más funcional en la naturaleza que un bucle 'for' estándar, entonces, donde tenía una' v' con muchos valores en el código C#, tiene múltiples 'v's que cada uno obtiene su propio valor en el código de Scala. – Destin

+0

@Destin: gracias, deberías haber publicado eso como una respuesta. Al menos lo habría votado a favor. (Todavía puede hacerlo, en realidad) –

Respuesta

Cuestiones relacionadas