2010-04-28 13 views
6

Próbuję zaimplementować drzewo oparte na HashMap, które obsługuje wyszukiwanie podmiejskie O (1) dla danego klucza root. W tym celu, Próbuję wykonać następujące czynności:Scala: praca wokół "nielegalnego odwołania cyklicznego"

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

Więc pytanie brzmi, czy jest jakiś sposób dla mnie do zrobienia czegoś w tym rodzaju, bez uciekania się do brzydkiego HashMap[Char, Any] z późniejszego odlewania wartości do HashMap[Char, Any] ?

Teraz widzę, że mogę użyć czegoś podobnego do poniższego, aby uniknąć błędu dotyczącego cyklicznych odniesień, a może nawet być czystsze - ale byłoby fajnie dowiedzieć się, jak poprawnie wykonać to w pierwszy sposób , tylko dla wartości edukacyjnej.

import collections.mutable.HashMap 

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

Dzięki za bukiet.

+1

Czy możesz wyjaśnić, jaki rodzaj struktury chcesz zdefiniować? Drzewo, którego łuki są oznaczone symbolem "Char" i których węzły w ogóle nie zawierają żadnych informacji? Jeśli tak, twój 'LTree' jest mniej więcej taki jak to tylko możliwe, ale jak napisano, możesz tworzyć tylko puste drzewa, ponieważ' children' jest niezmienne, tak samo jak 'HashMap' i konstruktor nie przyjmuje argumentów. –

+0

Dzięki za komentarz Randall. Właśnie podkręciłem powyższą listę, aby wskazać (tak jak w moim kodzie źródłowym), że używany HashMap jest zmienny. Przypadku użycia jest rzeczywiście skierowany wykres z krawędziami i węzłami znakowanymi znakami bez żadnych informacji. Jest to w rzeczywistości prymitywny DFA z liśćmi-węzłami domyślnie uznanymi za ostateczne stany. W każdym razie powyższe zdanie nie ma związku z kwestią składni scala - domyślam się, że mały fragment, który podałem, jest jednym obejściem, byłam ciekawa, czy istnieje sposób, aby zrobić to jeszcze bardziej zwięźle, sugerowane w pierwszym zestawieniu. –

+0

Praktycznie rzecz biorąc, oczywiście, drugi sposób z 'LTree' jest bardziej odpowiedni, ponieważ mogę wrzucić pola i funkcje członkowskie w nim dla różnych operacji drzewa. –

Odpowiedz

16

pewnie nie „dostać” na pytanie, ale co

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

lub

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

Dzięki Artem! Obie te prace, dokładnie to, czego szukałem. Спасибо! :) –

+7

Następnie oznacz to jak dobrze! – Zasz

+1

Czy mógłbyś wyjaśnić tę pierwszą? –

1

Dla typów nie można extend, takich jak Either, można również użyć banalne opakowanie:

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

lub drzewo rekurencyjne z Either (coś, co doprowadziło mnie do tego wątku):

// 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]) 

który jest typu prawny wersja tego pseudo-kod:

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

Następnie wszystkie Left(...) i Right(...) połączenia staną FieldError(Left(...)) i FieldError(Right(...)) odpowiednio, takie, że np FieldError(Right(x)).get == Right(x).

Powiązane problemy