我正在尝试列出列表(30(的列表(30(。 我有这个:
#(#(a a a) nil nil #(b) #(c) #(d) nil nil nil #(e e) nil #(f f) nil #(g)
#(h) nil nil nil #(i i) nil nil nil #(j) nil nil nil nil nil
#(k) #(l l l)
我想做一个程序,把它变成这样的列表:
#(a a a b c d e e f f g hi i j k l l l)
我的代码是这样的:
ToList: lista
| retorno y z |
retorno := Array new: 30.
y := 1.
(1 to: lista size)
do: [ :i |
z := 0.
(lista at: i) isNil
ifFalse:
(1 to: (lista at: i) size do: [ :j | retorno at: (y + z) put: ((lista at: i) at: j )
y:= y+1.
z:= z +1.]
)].
^retorno
我认为 if 语句存在一些问题,因为没有回报。我不知道该怎么办,因为它可以在没有y:= y+1.
的情况下工作,但它保留了一些零空格。
求求你,帮帮我!
代码中有两个语法错误:
-
ifTrue:
、ifFalse:
等的参数是块,Smalltalk中的块是括在方括号中的表达式,而不是括号。在你的情况下,你应该写(lista at: i) isNil ifFalse: [1 to: (lista at: i "<- [ not ("
并关闭于
z:= z +1.] ]]. "<- ]] not )]."
-
长行末尾缺少一个点:
.... put: ((lista at: i) at: j) "<- dot missing" y:= y+1. z:= z +1.
修复这两个问题后,您应该能够运行代码以查看它是否按预期工作(如果没有,则对其进行调试(。但那是另一回事了...
补遗
这里也有一些可疑的东西。
在Smalltalk中,我们使用单引号来分隔文字字符串('Hello world'
(和文字字符前面的美元符号,如$a
。
此外,我们还有文字数组,它由其他文字组成,并包含在#(
和)
之间,如#('a' $a)
.
现在,在您的代码中,您编写了表达式,例如#(a a a)
,它们不符合我们刚刚看到的格式。那么,这意味着什么呢?更准确地说,Smalltalk编译器将如何解释这种表示法?答案是,它将假设您的意思是:
#(#a #a #a)
即,一个Symbols
数组,并且您不想写那么多#
。因此,在练习中,您应该考虑是否真的想要字符#($a $a $a)
,字符串#('a' 'a' 'a')
或符号#(#a #a #a)
。
其他字符串也是如此。例如,#(abc de)
将被编译为#(#abc #de)
...
。嗯。。。
但是等一下。如果是这样,为什么#(#(a a a) nil)
没有被编译为#(#(a a a) #nil)
?好吧,因为编译器对nil
、true
和false
都例外......哎呀!
另请注意,在 Smalltalk 的某些方言中,编译器会将#((a a a))
解释为#(#(a a a))
,因此您不必键入那么多井号......
总结。如果您选择在文字数组中节省一些英镑,请保持一致并写入#((a a a))
而不是#(#(a a a))
。否则,请完全明确并写入#(#(#a #a #a))
。
你可以把它写成:
flattenArray: anArray
| ws |
ws = WriteStream on: (Array new).
anArray do: [:subArr| :
subArr notNil ifTrue: [
subArr do: [ :el | ws nextPut: el ]]].
^ws contents.
有 2 个一般评论,很少需要按索引访问集合元素,如果您正在这样做,请停止并思考是否有更优雅的方法可用。当您想要收集一系列结果时,第二个写入流很方便。