Smalltalk 中的多个 if
Multiple ifs in Smalltalk
我是 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.
].
在此先感谢您的帮助!
首先,我会将您的版本重写为:
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]
闻起来像 Fizz Buzz 问题! :-)
我发现我喜欢的 Smalltalk (Pharo) 中的一种方法是使用字典,其中 Fizz and/or 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]
也看看其中的一些 other examples,有时不同的方法可能很有教育意义。我将留给您根据您的 'a'/'b'/'ab' 示例调整代码。
我是 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.
].
在此先感谢您的帮助!
首先,我会将您的版本重写为:
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]
闻起来像 Fizz Buzz 问题! :-)
我发现我喜欢的 Smalltalk (Pharo) 中的一种方法是使用字典,其中 Fizz and/or 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]
也看看其中的一些 other examples,有时不同的方法可能很有教育意义。我将留给您根据您的 'a'/'b'/'ab' 示例调整代码。