una texto programar programacion pasos paso para pagina encabezado empezar ejemplo desde cual con como cero aprender aprende scala syntax coding-style method-chaining

texto - ¿Cuál es la sintaxis aceptada/recomendada para el código Scala con muchos métodos de encadenamiento?



programacion html (6)

En Scala tiendo a favorecer la escritura de grandes expresiones encadenadas sobre muchas expresiones más pequeñas con asignaciones val . En mi empresa, hemos desarrollado un estilo para este tipo de código. Aquí hay un ejemplo totalmente inventado (la idea es mostrar una expresión con muchas llamadas encadenadas):

import scala.util.Random val table = (1 to 10) map { (Random.nextInt(100), _) } toMap def foo: List[Int] = (1 to 100) .view .map { _ + 3 } .filter { _ > 10 } .flatMap { table.get } .take(3) .toList

La Guía de estilo Scala de Daniel Spiewak (pdf), que en general me gusta, sugiere que la notación punteada principal en las llamadas al método encadenado puede ser mala (vea doc: Invocación del método / Funciones de orden superior), aunque no cubre las expresiones de varias líneas como esto directamente.

¿Hay alguna otra forma más aceptada / idiomática de escribir la función foo arriba?

ACTUALIZACIÓN: 28-jun-2011

Muchas respuestas y discusiones excelentes a continuación. No parece haber una respuesta del 100% de "debes hacerlo de esta manera", así que voy a aceptar la respuesta más popular por votos, que actualmente es el enfoque de comprensión. Personalmente, creo que me voy a quedar con la notación de los puntos sobresalientes por el momento y acepto los riesgos que conlleva.


El ejemplo es poco realista, pero para expresiones complejas, a menudo es mucho más limpio usar una comprensión:

def foo = { val results = for { x <- (1 to 100).view y = x + 3 if y > 10 z <- table get y } yield z (results take 3).toList }

La otra ventaja aquí es que puede nombrar etapas intermedias del cálculo y hacerlo más autodocumentado.

Sin embargo, si su objetivo es la brevedad, esto puede convertirse fácilmente en un trazador de líneas (el estilo sin puntos ayuda aquí):

def foo = (1 to 100).view.map{3+}.filter{10<}.flatMap{table.get}.take(3).toList //or def foo = ((1 to 100).view map {3+} filter {10<} flatMap {table.get} take 3).toList

y, como siempre, optimice su algoritmo siempre que sea posible:

def foo = ((1 to 100).view map {3+} filter {10<} flatMap {table.get} take 3).toList def foo = ((4 to 103).view filter {10<} flatMap {table.get} take 3).toList def foo = ((11 to 103).view flatMap {table.get} take 3).toList


Envuelvo toda la expresión en un conjunto de paréntesis para agrupar cosas y evitar puntos si es posible,

def foo: List[Int] = ( (1 to 100).view map { _ + 3 } filter { _ > 10 } flatMap { table.get } take(3) toList )


Normalmente trato de evitar el uso de puntos para cosas como map y filter . Entonces probablemente lo escriba como el siguiente:

def foo: List[Int] = (1 to 100).view map { x => x + 3 } filter { x => x > 10 } flatMap { table.get } take(3) toList

La notación de punto principal es muy legible. Podría comenzar a usar eso.


Esto es lo improvisado que es. No puedes equivocarte.

(specMember setInfo subst(env, specMember.info.asSeenFrom(owner.thisType, sym.owner)) setFlag (SPECIALIZED) resetFlag (DEFERRED | CASEACCESSOR | ACCESSOR | LAZY) )

Fuente de compilador auténtico!


Mi regla: si la expresión se ajusta a una sola línea (80-120 caracteres), manténgala en una línea y omita los puntos siempre que sea posible:

def foo: List[Int] = (1 to 100).view map { _ + 3 } filter { _ > 10 } flatMap table.get take 3 toList

Como señaló Kevin, el estilo sin puntos puede mejorar la brevedad (pero podría dañar la legibilidad para los desarrolladores que no están familiarizados con él):

def foo: List[Int] = (1 to 100).view map{3+} filter{10<} flatMap table.get take 3 toList

La notación de punto inicial es perfectamente aceptable si necesita separar la expresión en varias líneas debido a la longitud. Otra razón para usar esta notación es cuando las operaciones necesitan comentarios individuales. Si necesita diseminar una expresión en varias líneas, debido a su longitud o la necesidad de comentar operaciones individuales, es mejor ajustar toda la expresión en parens (como sugiere Alex Boisvert . En estas situaciones, cada operación (lógica) debería continuar. su propia línea (es decir, cada operación va en una sola línea, excepto cuando múltiples operaciones consecutivas pueden describirse de manera sucinta mediante un solo comentario):

def foo: List[Int] = ( (1 to 100).view map { _ + 3 } filter { _ > 10 } flatMap table.get take 3 toList )

Esta técnica evita posibles problemas de inferencia de punto y coma que pueden surgir cuando se utiliza la notación de punto inicial o se llama a un método 0-arg al final de la expresión.


Prefiero muchos val :

def foo = { val range = (1 to 100).view val mappedRange = range map { _+3 } val importantValues = mappedRange filter { _ > 10 } flatMap { table.get } (importantValues take 3).toList }

Debido a que no sé lo que quiere hacer con su código, elegí nombres aleatorios para los val . Hay una gran ventaja para elegir val s en lugar de las otras soluciones mencionadas:

Es obvio lo que hace tu código. En su ejemplo y en las soluciones mencionadas en la mayoría de las otras respuestas, nadie sabe a primera vista lo que hace. Hay demasiada información en una expresión. Solo en una expresión forzada, mencionada por @Kevin, es posible elegir decir nombres pero no me gustan porque:

  1. Necesitan más líneas de código
  2. Son más lentos debido a que el patrón coincide con los valores declarados (lo mencioné aquí ).
  3. Solo mi opinión, pero creo que se ven feas