2009-03-23 39 views
31

Viniendo de un fondo Java, estoy acostumbrado a la práctica común de hacer frente a las colecciones: es evidente que no habría excepciones, pero por lo general el código se vería así:colección Scala práctica estándar

public class MyClass { 
    private Set<String> mySet; 

    public void init() { 
    Set<String> s = new LinkedHashSet<String>(); 
    s.add("Hello"); 
    s.add("World"); 
    mySet = Collections.unmodifiableSet(s); 
    } 
} 

Tengo que confesar que Estoy un poco aturdido por la gran cantidad de opciones en Scala. No:

  • scala.List (y Seq)
  • scala.collections.Set (y Map)
  • scala.collection.immutable.Set (y Map, Stack pero no List)
  • scala.collection.mutable.Set (y Map, Buffer pero no List)
  • scala.collection.jcl

¡Preguntas!

  1. ¿Por qué List y Seq definido en el paquete scala y no scala.collection (a pesar de que las implementaciones de Seq están en las sub-paquetes de colecciones)?
  2. cuál es el mecanismo estándar para iniciando una colección y luego congelar (lo que en Java se encierra en un unmodifiable)?
  3. ¿Por qué algunos tipos de colección (por ejemplo, MultiMap) solo se definen como mutables? (No hay inmutable MultiMap)?

He leído Daniel Spiewak's excellent series on scala collections y todavía estoy desconcertado por cómo uno realmente los usaría en la práctica. El siguiente parece un poco difícil de manejar debido a las declaraciones de paquete completo forzadas:

class MyScala { 
    var mySet: scala.collection.Set[String] = null 

    def init(): Unit = { 
    val s = scala.collection.mutable.Set.empty[String] 
    s + "Hello" 
    s + "World" 
    mySet = scala.collection.immutable.Set(s : _ *) 

    } 
} 

Aunque podría decirse que esto es más correcto que la versión Java como la colección inmutable no puede cambiar (como en el caso de Java, donde la colección subyacente podría alterarse envoltorio debajo del unmodifiable)

Respuesta

26

¿por qué lista y la SEC define en Scala paquete y no scala.collection (a pesar de que las implementaciones de la SEC están en las sub-paquetes de colecciones)?

Porque se consideran generalmente tan útiles que se importan automáticamente en todos los programas a través de sinónimos en scala.Predef.

¿Cuál es el mecanismo estándar para inicializar una colección y luego congelarla (que en Java se logra envolviendo de forma no modificable)?

Java no tiene un mecanismo para congelar una colección. Solo tiene un modismo para envolver la colección (aún modificable) en un contenedor que arroja una excepción.La expresión apropiada en Scala es copiar una colección mutable en una inmutable, probablemente usando: _ *

¿Por qué algunos tipos de colecciones (por ejemplo, MultiMap) solo se definen como mutables? (No hay un MultiMap inmutable)?

El equipo/comunidad simplemente no ha llegado todavía. La rama 2.7 vio un montón de adiciones y se espera que 2.8 tenga mucho más.

El siguiente parece un poco difícil de manejar debido a las declaraciones de paquete completo forzadas:

Scala permite a los alias de importación así que siempre es menos detallado que Java en este sentido (véase, por ejemplo java.util.Date y Java .sql.Date - utilizando tanto las fuerzas que uno sea totalmente calificado)

import scala.collection.{Set => ISet} 
import scala.collection.mutable.{Set => MSet} 

class MyScala { 
    var mySet: ISet[String] = null 

    def init(): Unit = { 
    val s = MSet.empty[String] 
    s + "Hello" 
    s + "World" 
    mySet = Set(s : _ *) 
    } 
} 

por supuesto, usted realmente acaba de escribir de inicio como el def init() { mySet = Set("Hello", "World")} y guardar todos los problemas o mejor aún, sólo hay que poner en el constructor var mySet : ISet[String] = Set("Hello", "World")

+1

Supongo que es más probable que el bucle atraviese algo y lo agregue al conjunto, en lugar de solo un grupo de valores. – runT1ME

4

Un par de pensamientos al azar:

  1. nunca uso null, utilizo Option, lo que a continuación, echar un error decente. Esta práctica ha eliminado las oportunidades de ton y obliga a las personas a escribir errores decentes.
  2. Trata de evitar mirar las cosas "mutables" a menos que realmente lo necesites.

Por lo tanto, mi posición básica en su ejemplo Scala, donde usted tiene que inicializar el equipo más tarde, es

class MyScala { 
    private var lateBoundSet:Option[ Set[ String ] ] = None 
    def mySet = lateBoundSet.getOrElse(error("You didn't call init!")) 

    def init { 
    lateBoundSet = Some(Set("Hello", "World")) 
    } 
} 

He estado en una lágrima recientemente por la oficina. "null es malvado"

3

Tenga en cuenta que puede haber algunas incoherencias en la API de colecciones de Scala en la versión actual; para Scala 2.8 (que se lanzará más adelante en 2009), la API de colecciones se está revisando para que sea más coherente y más flexible.

Ver este artículo en el sitio web Scala: http://www.scala-lang.org/node/2060

Para agregar al ejemplo de Tristan Juříček con un lateBoundSet: Scala tiene un mecanismo incorporado para la inicialización perezosa, utilizando el "perezoso" palabra clave:

class MyClass { 
    lazy val mySet = Set("Hello", "World") 
} 

Al hacer esto, mySet se inicializará en el primer uso, en lugar de hacerlo inmediatamente al crear una nueva instancia de MyClass.

7

Las colecciones mutables son útiles de vez en cuando (aunque estoy de acuerdo en que siempre debe mirar primero las inmutables). Si su uso, tiendo a escribir

import scala.collection.mutable 

en la parte superior del archivo, y (por ejemplo):

val cache = new mutable.HashMap[String, Int] 

en mi código. Significa que solo tiene que escribir "mutable.HashMap", no scala.collection.mutable.HashMap ". Como el comentarista mencionado anteriormente, se puede volver a asignar el nombre en la importación (por ejemplo, “scala.collection.mutable importación {HashMap => MMAP}.”), Pero:

  1. prefiero no mangle los nombres, para que esté más claro qué clases estoy usando, y
  2. Uso 'mutable' raramente basta que tener "mutable.ClassName" en mi fuente no es una carga excesiva .

(También, puedo hacerme eco del comentario "evitar los nulos". Hace que el código sea mucho más robusto y comprensible. Encuentro que ni siquiera tengo que usar Option tanto como cabría esperar .)

+0

Me gusta esa convención de nombres. Debes contribuir aquí: http://groups.google.com/group/liftweb/browse_thread/thread/4460656773dc8729/47359c9e7cd08c80 – Trenton

Cuestiones relacionadas