如果语句(无返回)在 Pharo Smalltalk 中用于扁平化列表



我正在尝试列出列表(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.的情况下工作,但它保留了一些零空格。

求求你,帮帮我!

代码中有两个语法错误:

  1. ifTrue:ifFalse:等的参数是块,Smalltalk中的块是括在方括号中的表达式,而不是括号。在你的情况下,你应该写

    (lista at: i) isNil
    ifFalse: 
    [1 to: (lista at: i               "<- [ not ("
    

    并关闭于

    z:= z +1.]
    ]].                               "<- ]] not )]."
    
  2. 长行末尾缺少一个点:

    .... 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)?好吧,因为编译器对niltruefalse都例外......哎呀!

另请注意,在 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 个一般评论,很少需要按索引访问集合元素,如果您正在这样做,请停止并思考是否有更优雅的方法可用。当您想要收集一系列结果时,第二个写入流很方便。

最新更新