2011-08-31 7 views
5

Uso Scala y JDBC, ahora quiero reutilizar un PreparedStatement para hacer una inserción múltiple. Quiero usar un bucle foreach sobre una matriz, pero no puedo hacerlo bien con Scala.¿Cómo usar un bucle foreach en Scala que muta un objeto?

val stmt = conn.prepareStatement(insertStatement) 

// wrong Scala 
items.foreach(item : MyItem => 
    stmt.setInt(1, item.id) 
    stmt.setInt(2, item.value) 
    stmt.executeUpdate() 
    ) 

items es una matriz que contiene múltiples MyItem.

¿Cómo puedo escribir este foreach-loop en Scala y reutilizar el PreparedStatement?

+0

¿Podría ser que necesita usar llaves ('elementos foreach {...}') para que el bloque de varias líneas se ejecute correctamente? De lo contrario, explique ** por qué ** está equivocado (por ejemplo, proporcione el mensaje de error del compilador o el comportamiento incorrecto que resulta). –

+0

@Andrzej: He tratado de poner '{' y '}' en algunos lugares, pero no puedo hacer que se compile con ninguna combinación. El error en este caso es 'Error raised is: ')' expected but '(' found. * * At *' stmt.setInt ↓ (1, item.id) ' – Jonas

+0

@Jones parece que es un problema de llaves. ; He agregado una respuesta que demuestra esto. Si todavía está viendo problemas, probablemente se base en un error lógico en otro lugar, en lugar de en la forma en que Scala maneja los bucles foreach. –

Respuesta

19

Es necesario utilizar llaves para el argumento de foreach si desea que se interpreta como una instrucción múltiple bloque (que lo hace).

Aparte de eso, lo que estás haciendo se ve bien. Aquí está una sesión REPL donde estoy mutando un objeto en un bloque foreach de forma similar (utilizando un StringBuilder para simplificar):

scala> val sb = new java.lang.StringBuilder 
sb: java.lang.StringBuilder = 

scala> val items = List("tinker", "tailor", "soldier", "spy") 
items: List[java.lang.String] = List(tinker, tailor, soldier, spy) 

scala> items.foreach { item => 
    | sb.append(item) 
    | sb.append("; ") 
    | println(sb) 
    | } 
tinker; 
tinker; tailor; 
tinker; tailor; soldier; 
tinker; tailor; soldier; spy; 

(Y el uso de paréntesis para el bloque foreach conduce al error <console>:3: error: ')' expected but '.' found.)

+0

@biesczadka No estoy seguro de seguir: si quieres devolverlo desde una función, ¡solo asegúrate de que sea el valor de retorno de tu función! De cualquier manera, eso tiene ** nada ** que ver con esta pregunta o mi respuesta, por lo que si todavía tiene problemas, debe publicarlo como una pregunta separada. –

11

Un pequeño punto, pero la respuesta de Andrzej se puede limpiar mediante el uso de la notación infija más liberalmente:

val sb = new java.lang.StringBuilder 

val items = List("tinker", "tailor", "soldier", "spy") 

items foreach { item => 
    sb append item 
    sb append "; " 
    println(sb) 
} 

Generalmente, se considera más idiomática utilizar la forma infija para operaciones de recogida tal como map, flatMap, foreach y filter

+3

Este comentario me sorprende. Aquí está la discusión en la guía de estilo: http://davetron5000.github.com/scala-style/method_invocation/arity1/index.html y http://davetron5000.github.com/scala-style/method_invocation/arity1/higher_order_functions. html La regla parece ser que la notación infija debe * usarse * solo para funciones inmutables, y preferiblemente con métodos de orden superior como 'map'. Como 'append' es una mutación, la guía de estilo dice que no use infix. –

+1

La guía de estilo es solo eso, una * guía *. Contiene pautas (no reglas) y no es un evangelio absoluto.Encontrará diferencias de opinión sobre algunas de las sugerencias allí, incluida esta :) –

+1

Como un contraejemplo obvio para la regla, el método de asignación, '=', tiene efecto secundario, pero siempre se usa en la notación infija. –

Cuestiones relacionadas