1

以下代码给出了错误 error: did not understand '#generality'

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.
    ].

不一致是在行中pqueue add: new_internal。当我删除这一行时,程序编译。[pqueue size > 1] whileTrue:我认为问题与迭代块有关pqueue add: new_internal.

注意:这是基于霍夫曼代码构建解码树的算法。

错误信息展开

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)
4

1 回答 1

2

我们可以从这个问题中学到的一个知识是养成阅读堆栈跟踪以试图理解它的习惯。让我们关注最后几条消息:

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)

这些行中的每一行都代表一个方法的激活。每行代表一条消息,并且消息的顺序向上(就像在任何Stack. 然而,在这里,我们只看到了这class >> #selector对。我们可以从这些汇总信息中识别出几个有趣的事实:

  1. 在第 1 行中,我们得到了实际的错误。在这种情况下,我们遇到了一个MessageNotUnderstood例外。消息的接收者是Character $<10>,即换行符。

  2. 第 2 行和第 3 行确认未理解的消息是#generality

  3. 第 4、5 和 6 行显示了最终发送#generality到错误对象(换行)的消息的进程。虽然对于没有经验的 Smalltalker 来说,第 4 行和第 5 行可能看起来晦涩难懂,但第 6 行有关键信息:一些人SmallInteger收到了<=消息。此消息将失败,因为该参数不合适。根据我们已经获得的信息,我们知道参数是换行符。

  4. 第 7 行显示,这SmallInteger >> #<=来自于相同选择器#<=Leaf. 它告诉我们,一个Leaf代表#<=对某些人来说是Integer众所周知的。

  5. 第 8 行说明了我们处理比较选择器的原因#<=。原因是我们正在对一些集合进行排序。

因此,我们正在尝试对Leaf依赖于一些整数进行比较的对象集合进行排序,并且不知何故,其中一个“整数”不是换行符Number而是Character换行符。

如果我们带着这些信息看一下 Smalltalk 代码,我们会看到:

  • SortedCollectionispqueueLeafobjects 是添加到其中的项目。

  • a的不变属性SortedCollection是它的元素总是按给定的标准排序。因此,每次我们add:向它添加一个元素时,该元素都会被插入到正确的位置。因此比较消息#<=

  • 现在让我们#add:在代码中寻找。除了上面的一个,下面还有一个:

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

    这个很有趣,因为它是错误发生的地方。但是请注意,我们不是在Leaf此处添加 a 而是在Tree. 但是等等,可能 aTree和 aLeaf属于同一个层次结构。实际上,Tree和都Leaf表示无环图中的节点。此外,代码在以下内容中证实了这一想法:

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

看?两者Leaf都有Tree一些key(的论点new:)和一些count。另外还有Treeshaveleftrightbranch,这Leaf不是(当然!)

因此,原则上,可以将 的实例添加Tree到我们的pqueue集合中。这不可能是导致错误的原因。

现在,如果我们仔细观察它的Tree创建方式,我们会发现一个可疑的论点nl。这很有趣,因为有两个原因:(i)变量nl没有在我们给出的代码部分中定义,(ii)变量nlkey用于Tree响应#<=消息的变量。因此,nl必须是换行符$<10>。这很有意义,因为在 Linux 世界中,换行符是换行符nl的缩写。newline

结论:问题似乎是由' 键nl使用的错误参数引起的。Tree

于 2017-11-18T16:03:08.347 回答