2017-11-17 4 views
1

Das folgende Stück Code gibt den Fehler error: did not understand '#generality'Legendes GNU Smalltalk Closure

pqueue := SortedCollection new. 
freqtable keysAndValuesDo: [:key :value | 
    (value notNil and: [value > 0]) ifTrue: [ 
     |newvalue| 
     newvalue := Leaf new: key count: value. 
     pqueue add: newvalue. 
    ] 
]. 

    [pqueue size > 1] whileTrue:[ 
     |first second new_internal newcount| 
     first := pqueue removeFirst. 
     second := pqueue removeFirst. 
     first_count := first count. 
     second_count := second count. 
     newcount := first_count + second_count. 
     new_internal := Tree new: nl count: newcount left: first right: second. 
     pqueue add: new_internal. 
    ]. 

Die Inkonsistenz in der Linie ist pqueue add: new_internal. Wenn ich diese Zeile entferne, kompiliert das Programm. Ich denke, das Problem hängt mit dem Iterationsblock zusammen [pqueue size > 1] whileTrue: und pqueue add: new_internal.

Hinweis: Dies ist der Algorithmus zum Erstellen des Decodierungsbaums basierend auf Huffman-Code.

Fehlermeldung erweitert

Object: $<10> error: did not understand #generality 
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254) 
Character(Object)>>doesNotUnderstand: #generality (SysExcept.st:1448) 
SmallInteger(Number)>>retryDifferenceCoercing: (Number.st:357) 
SmallInteger(Number)>>retryRelationalOp:coercing: (Number.st:295) 
SmallInteger>><= (SmallInt.st:215) 
Leaf>><= (hzip.st:30) 
optimized [] in SortedCollection class>>defaultSortBlock (SortCollect.st:7) 
SortedCollection>>insertionIndexFor:upTo: (SortCollect.st:702) 
[] in SortedCollection>>merge (SortCollect.st:531) 
SortedCollection(SequenceableCollection)>>reverseDo: (SeqCollect.st:958) 
SortedCollection>>merge (SortCollect.st:528) 
SortedCollection>>beConsistent (SortCollect.st:204) 
SortedCollection(OrderedCollection)>>removeFirst (OrderColl.st:295) 
optimized [] in UndefinedObject>>executeStatements (hzip.st:156) 
BlockClosure>>whileTrue: (BlkClosure.st:328) 
UndefinedObject>>executeStatements (hzip.st:154) 
Object: $<10> error: did not understand #generality 
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254) 
Character(Object)>>doesNotUnderstand: #generality (SysExcept.st:1448) 
SmallInteger(Number)>>retryDifferenceCoercing: (Number.st:357) 
SmallInteger(Number)>>retryRelationalOp:coercing: (Number.st:295) 
SmallInteger>><= (SmallInt.st:215) 
Leaf>><= (hzip.st:30) 
optimized [] in SortedCollection class>>defaultSortBlock (SortCollect.st:7) 
SortedCollection>>insertionIndexFor:upTo: (SortCollect.st:702) 
[] in SortedCollection>>merge (SortCollect.st:531) 
SortedCollection(SequenceableCollection)>>reverseDo: (SeqCollect.st:958) 
SortedCollection>>merge (SortCollect.st:528) 
SortedCollection>>beConsistent (SortCollect.st:204) 
SortedCollection(OrderedCollection)>>do: (OrderColl.st:64) 
UndefinedObject>>executeStatements (hzip.st:164) 
+0

Bitte spezifizieren Sie den Dialekt, den Sie verwenden (ich nehme an, es ist GNU) und mehr der Fehlermeldung, z. welche Klasse die Nachricht nicht versteht (eventuell eine Stack-Trace veröffentlichen, wenn Sie eine haben). –

+1

Sieht aus, als ob die SortedCollection versucht, SmallIntegers mit dem hinzugefügten Objekt (der Klasse Tree?) Zu vergleichen und schlägt fehl. Enthält Ihre Warteschlange Elemente verschiedener Typen? Wenn ja, vergewissern Sie sich, dass sie über <= vergleichbar sind, oder geben Sie beim Erstellen der Sammlung einen benutzerdefinierten sortBlock an. – JayK

+0

Ja, das funktioniert. Wenn ich das tue [putiere add: new_internal.]. es funktioniert – patzi

Antwort

2

Ein Lernen wir von dieser Frage nehmen können, ist die Gewohnheit des Lesens des Stack-Trace zu erwerben versuchen, einen Sinn zu machen. Lassen Sie uns in den letzten Nachrichten fokussieren:

1. Object: $<10> error: did not understand #generality 
2. MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254) 
3. Character(Object)>>doesNotUnderstand: #generality (SysExcept.st:1448) 
4. SmallInteger(Number)>>retryDifferenceCoercing: (Number.st:357) 
5. SmallInteger(Number)>>retryRelationalOp:coercing: (Number.st:295) 
6. SmallInteger>><= (SmallInt.st:215) 
7. Leaf>><= (hzip.st:30) 
8. optimized [] in SortedCollection class>>defaultSortBlock (SortCollect.st:7) 

Jede dieser Zeilen repräsentiert die Aktivierung einer Methode. Jede Linie steht für eine Nachricht und die Folge von Nachrichten geht nach oben (wie es in jedem Stack geschieht.) Das Detail jeder Aktivierung kann im Debugger zu sehen. Hier werden wir jedoch nur mit dem class >> #selector Paar vorgestellt. Es gibt mehrere interessante Fakten, die wir aus dieser zusammengefassten Informationen identifizieren können:

  1. In Zeile 1 wir die tatsächliche Fehler. In diesem Fall haben wir eine MessageNotUnderstood Ausnahme. Der Empfänger der Nachricht war die Character$<10>, das heißt die Zeilenvorschubzeichen.

  2. Linien 2 und 3 bestätigen, dass die Nachricht nicht #generality war verstanden.

  3. Die Zeilen 4, 5 und 6 zeigen den Fortschritt der Nachrichten, die am Ende #generality an das falsche Objekt (Zeilenvorschub) gesendet haben. Während 4 und 5 könnte für die nicht-erfahrene Smalltalker dunkel aussehen, Zeile 6 hat die wichtigsten Informationen: einige SmallInteger erhielt die <= Nachricht. Diese Nachricht würde fehlschlagen, weil das Argument nicht das richtige war. Aus den Informationen, die wir bereits erhalten haben, wissen wir, dass das Argument der Zeilenvorschub war.

  4. Linie 7 zeigt, dass SmallInteger >> #<= von der Art und Weise kam der gleiche Selektor #<= in Leaf umgesetzt wird. Es sagt uns, dass ein Leaf Delegierten #<= einige Integer ihm bekannt.

  5. Linie 8 sagt, warum wir mit dem Vergleichswähler #<= handelt. Der Grund ist, dass wir einige Sammlungen sortieren.

Also, versuchen wir, eine Sammlung von Leaf Objekte zu sortieren, die für ihren Vergleich auf einige Zahlen verlassen und irgendwie eine dieser „ganzen Zahlen“ war kein Number aber die Character Zeilenvorschub.

Wenn wir einen Blick auf die Smalltalk-Code mit diesen Informationen im Auge nehmen wir sehen:

  • Die SortedCollection ist pqueue und die Leaf Objekte sind die Elemente, wobei ihm hinzugefügt.

  • Die invariant Eigenschaft eines SortedCollection ist, dass sie immer von einem gegebenen Kriterium geordnet seine Elemente aufweist. Folglich wird jedes Mal, wenn wir ein Element zu ihm haben, das Element an der richtigen Position eingefügt. Daher die Vergleichsnachricht #<=.

  • Nun suchen wir im Code nach #add:. Neben dem einen oben, gibt es einen anderen unten:

    new_internal := Tree new: nl count: newcount left: first right: second. 
        pqueue add: new_internal. 
    

    Dieser ist interessant, weil wo der Fehler passiert. Beachten Sie jedoch, dass wir hier keine Leaf sondern eine Tree hinzufügen. Aber warte, es könnte sein, dass ein Tree und ein Leaf zu derselben Hierarchie gehören. Sowohl Tree als auch Leaf repräsentieren Knoten in einem azyklischen Graphen. Darüber hinaus bestätigt der Code diese Idee, wenn es heißt:

    Leaf new: key count: value. 
        ... 
        Tree new: nl count: newcount left: first right: second. 
    

sehen? Sowohl Leaf als auch Tree haben einige key (das Argument von new:) und einige count. Darüber hinaus haben Treesleft und right Zweige, die Leaf s nicht (natürlich!)

Also im Prinzip wäre es in Ordnung seine Instanzen Tree unsere pqueue Sammlung hinzuzufügen. Dies kann nicht sein, was den Fehler verursacht.

Nun, wenn wir näher auf die Art und Weise schauen, die Tree erstellt wird, können wir ein verdächtiges Argument nl sehen. Dies ist aus zwei Gründen interessant: (i) Die Variable nl ist nicht in dem Teil des Codes definiert, den wir erhielten, und (ii) die Variable nl ist die key, die von Tree verwendet wird, um auf die Nachricht #<= zu reagieren. Daher muss nl das Zeilenvorschubzeichen $<10> sein. Das macht sehr viel Sinn, denn nl ist eine Abkürzung für newline und in der Linux-Welt sind Zeilenumbrüche Zeilenumbrüche.

Fazit: Das Problem scheint nl für die Tree ‚s Schlüssel, die von dem falschen Argument verursacht werden.