1

所以我在 smalltalk 中创建了一个名为 LazyMatrix 的类。该类只有 1 个实例变量,不能是除 Object 之外的任何子类。LazyMatrix 的实例变量称为block,必须是back。我像这样初始化 LazyMatrix:

initialize
block:=[nil]

将有一种设置值的方法

setRow:column:value:

此方法将通过将新块设置为 [#(ij value).[nil]] 来重新定义块。每个后续调用都会将一个 3 的数组添加到块中,因此它的扩展类似于 [#(ij value).[#(ij value).[nil]]],很像 s 表达式或“惰性列表”。

所以我需要访问这个块的头部(即 [#(ij value) )以及这个块的尾部(即 [#(ij value).[nil]] )。我如何在 smalltalk 中做到这一点?我知道在块上调用 value 将返回尾部......现在我需要返回头部。

4

2 回答 2

4

将数组添加到您的块不会让您到任何地方。考虑行为,而不是数据结构

我猜您的老师确实为您提供了总体思路:给定一行和一列,回答相关值;否则请向“尾巴”寻求答案。

从字面上看,这就是您在 Smalltalk 中使用块闭包实现它的方式(其中“尾部”是先前设置的块)。在块内,放置执行测试和回答以及尾递归的代码。不要制作数据结构,尾部和头部只是对这种编码风格进行推理的隐喻。

我刚刚在 Squeak 中实现了你的 LazyMatrix,它只是几行代码。可爱的例子,确实。并且根本不涉及数组或集合。

提示:这个谜题的关键是意识到每次调用 setRow:column:value: 都可以创建一个新块,该块独立于之前创建的所有块。

于 2013-04-10T17:16:54.710 回答
0

我认为你可以在这里有两种方式。第一个(我不推荐)是将您的 s 表达式建模为 lambda 演算中的列表。你基本上使用块作为函数,你就完成了。在这里,您可以喜欢使用 lambda 演算编写列表的解释。例如,在 Smalltalk 中你会写

empty = λfx.x

作为

empty := [:f :x | x].

现在,走这条路基本上就是用 OO 语言编写函数式程序,而我不会这样做。如果您想对列表使用符号方法,那么您应该使用对象对其进行建模。有一个EmptyList类和一个Cons类(Cons将有一个element和一个listinst var),以便您通过执行以下操作创建一个列表:

listWithOne := Cons element: 1 list: EmptyList new.

只需返回 inst var 值,即可在类中轻松编写headand方法。你也可以在类中定义和方法,这样现在和都是多态的。tailConsheadtailEmptyListEmptyListCons

补充:好的,只是为了好玩,一个使用块和数组的实现,函数式:

| empty cons head tail test |
empty := [nil].
cons := [:i :j :value :old | [Array with:i with:j with:value with:old]].
head := [:list | list value ifNotNil: [:v | v copyFrom:1 to:3]].
tail := [:list | list value at: 4].

test := cons value: 1 value: 1 value: 'Hi' value: (cons value: 1 value: 2 value: 'Ho' value: empty).
"Print each one"
head value: test.
head value: (tail value: test).
head value: (tail value: (tail value: test)).

高温高压

于 2013-04-09T13:33:20.597 回答