Smalltalk 在#注入:块中可见
此代码:Smalltalk 在#注入:块中可见,smalltalk,Smalltalk,此代码: ((1 to: 10) inject: (WriteStream on: String new) into: [ :strm :each | ((each rem: 3) = 0) ifTrue: [ strm nextPutAll: each printString; space;
((1 to: 10)
inject: (WriteStream on: String new)
into: [ :strm :each |
((each rem: 3) = 0)
ifTrue: [
strm
nextPutAll: each printString;
space;
yourself ]]) contents
失败,因为在ifTrue:
块中使用的strm
未定义。为什么在那里看不见
编辑:我在VASt和Pharo中试用了它。问题是隐含的
ifFalse:
分支返回nil
。要解决此问题,请尝试以下操作:
((1 to: 10)
inject: (WriteStream on: String new)
into: [ :strm :each |
((each rem: 3) = 0)
ifFalse: [strm] "This is needed to avoid nil being returned"
ifTrue: [
strm
nextPutAll: each printString;
space;
yourself ]]) contents
根据方言(可用方法),您可以采用更短的方法
((1 to: 10) select: [ :each | (each rem: 3) = 0 ]) joinUsing: ' '
根据经验法则,任何集合都可以:[:每个|东西如果真的:[]]
可以变成更直接、更可读的集合选择:[]
或集合拒绝:[]
这样做会将复杂性分散到几个独立的步骤(1.过滤,2.添加到流),而不是将其全部推到一起
或者如果你想坚持你原来的想法
(((1 to: 10) select: [ :each | (each rem: 3) = 0 ])
inject: (WriteStream on: String new)
into: [ :stream :each |
stream
nextPutAll: each printString;
space;
yourself ]) contents
或
不是总是这样,但遇到这种情况时最好记住。您使用哪种方言?Dolphin、VW、VA、Pharo、Squeak、GNU……这些都是有效的,但我还是不太明白。是否有必要在第一个周期(在
ifFalse:
块中)返回strm
,以使其“初始化”?忘记上面的注释,我理解。我接受了你的回答,你说得很对。此示例是我向同事展示的fizzbuzz实现的子部分,不能简化为select:
或reject:
。
String streamContents: [ :stream |
(1 to: 10)
select: [ :each | (each rem: 3) = 0 ]
thenDo: [ :each |
stream
nextPutAll: each printString;
space
]
]