2010-04-28 10 views
6

Estoy intentando implementar un árbol basado en HashMap que admitiría la búsqueda O (1) de subárbol para una clave raíz determinada. Para ese objetivo, estoy tratando de hacer lo siguiente:Scala: trabajando en torno a la "referencia cíclica ilegal"

scala> type Q = HashMap[Char, Q] 
<console>:6: error: illegal cyclic reference involving type Q 
     type Q = HashMap[Char, Q] 
         ^

Entonces la pregunta es, ¿hay alguna manera de que yo haga algo por el estilo sin tener que recurrir a la fea HashMap[Char, Any] con la posterior conversión de valores a HashMap[Char, Any] ?

Ahora, también veo que puedo usar algo como lo siguiente para evitar el error de referencia cíclica, e incluso podría ser más limpio, pero sería bueno saber cómo hacerlo correctamente de la primera manera , solo por el valor educativo.

import collections.mutable.HashMap 

class LTree { 
    val children = new HashMap[Char, LTree] 
} 

Gracias a un montón.

+1

¿Puedes aclarar qué tipo de estructura quieres definir? ¿Un árbol cuyos arcos están etiquetados con un 'Char' y cuyos nodos no contienen ninguna información? Si es así, tu 'LTree' es lo mínimo posible, aunque como está escrito, solo puedes crear árboles vacíos ya que' children' es inmutable como lo es 'HashMap' y el constructor no toma argumentos. –

+0

Gracias por el comentario de Randall. Acabo de ajustar el listado anterior para indicar (como está en mi código fuente) que el HashMap utilizado es mutable. El caso de uso es de hecho un gráfico dirigido con bordes y nodos etiquetados con carbón que no contienen ninguna información. De hecho, este es un DFA rudimentario con nodos de hoja considerados implícitamente como estados finales. En cualquier caso, lo anterior no es tan relevante para la cuestión de la sintaxis scala. Supongo que el pequeño fragmento que he dado es una solución, solo tenía curiosidad si hay una manera de hacerlo aún más sucinto, ya que sugerido en la primera lista. –

+0

Hablando en términos prácticos, por supuesto, la segunda forma con 'LTree' es más apropiada ya que puedo agregar campos y funciones de miembros dentro de ella para varias operaciones de árbol. –

Respuesta

16

Probablemente no "sale" a la pregunta, pero ¿qué pasa

class L { 
    type Q = java.util.HashMap[Char, this.type] 
} 

o

class Q extends java.util.HashMap[Char, Q] 
+0

Gracias Artem! Ambos funcionan, eso es exactamente lo que estaba buscando. Спасибо! :) –

+7

¡Entonces márcalo como correcto! – Zasz

+1

¿Podría explicarme el primero, por favor? –

1

Para los tipos no se puede extend, como Either, también se puede utilizar una envoltorio trivial:

class MyEither(get: Either[String, MyEither]) 

o, un árbol recursivo con Either (algo que me llevó a este hilo):

// represents (validation) errors for a tree structure of nested dictionaries 
type FieldName = String 
type Error = String 

type Errors = List[(FieldName, FieldError)] 
case class FieldError(val get: Either[Error, Errors]) 

que es la versión de tipo legal de este pseudo-código:

type Error = String 
type Errors = List[(FieldName, Either[Error, Errors])] 

Entonces, todos sus Left(...) y Right(...) llamadas se convertirían en FieldError(Left(...)) y FieldError(Right(...)) respectivamente, de manera que, por ejemplo, FieldError(Right(x)).get == Right(x).

Cuestiones relacionadas