我真的是smalltalk的新手,还在努力弄清楚基本的东西。下面是我写的一个简单的程序。如果数字可以被5整除,则应该打印"a",如果可以被3整除,应打印"b",如果它可以被5和3整除则应打印"ab"。在任何其他情况下,程序只打印数字本身。它当然是这样工作的,但我觉得代码不是很漂亮——我想避免第三个"if",但我真的不确定如何做到。你将如何重构它?
1 to: 100 do: [ :i |
(i % 5 == 0)
ifTrue: [ Transcript show: 'a' ].
(i % 3 == 0)
ifTrue: [ Transcript show: 'b' ].
((i % 3 == 0) or: (i % 5 == 0))
ifFalse: [ Transcript show: i ].
Transcript cr.
].
提前感谢您的帮助!
闻起来像个嗡嗡声问题!:-)
我在Smalltalk(Pharo)中看到的一种方法是使用一本字典,其中Fizz和/或Buzz单词作为值,布尔值表示它是否可以被3和5整除。一旦你有了它,你只需查找1到100之间的每个索引的值。哦,不用自己去除法和检查余数是否为零——这是Smalltalk,所以一个数字应该知道它是否可以被另一个数字整除。
| fizzbuzz |
fizzbuzz := Dictionary
with: #(true true)->'FizzBuzz'
with: #(true false)->'Fizz'
with: #(false true)->'Buzz'.
1 to: 100 do: [ :eachIndex |
Transcript
show: (fizzbuzz
at: {eachIndex isDivisibleBy: 3. eachIndex isDivisibleBy: 5}
ifAbsent: [ eachIndex ]);
cr]
看看其他一些例子,有时不同的方法可能很有教育意义。我将让您根据您的"a"/"b"/"b"示例调整代码。
首先,我会将您的版本重写为:
1 to: 100 do: [:i |
i % 5 = 0 ifTrue: [Transcript show: 'a'].
i % 3 = 0 ifTrue: [Transcript show: 'b'].
(i % 3 = 0 or: [i % 5 = 0]) ifFalse: [Transcript show: i].
Transcript cr]
变化是:
- 使用
=
而不是==
(没什么大不了的) - 使用带括号的
or: [i % 5 = 0]
你可以引入的另一个变化是
1 to: 100 do: [:i | | label |
i % 5 = 0 ifTrue: [label := 'a'].
i % 3 = 0 ifTrue: [label := 'b'].
label isNil ifTrue: [label := i].
Transcript show: label; cr]
请注意,我并没有过多地关注IF,而是关注Transcript show:
在代码中出现三次这一事实。
编辑
唉!我上面的版本与你的版本不等效,因为如果数字除以5
和3
,它将不会打印'a'
!
编辑2
以下是如何再现原始代码的行为:
1 to: 100 do: [:i | | label |
label := ''.
i % 5 = 0 ifTrue: [label := 'a'].
i % 3 = 0 ifTrue: [label := label , 'b'].
label isEmpty ifTrue: [label := i].
Transcript show: label; cr]