sum*_*ion 8 smalltalk switch-statement pharo
我正在尝试解析一个命令和一个int来在板上做一个"乌龟"移动.我有点不知所措,因为它没有抛出异常,我甚至无法弄清楚如何在没有它的情况下打开调试器.
我的代码:
"only should begin parsing on new line"
endsWithNewLine:= aTurtleProgram endsWith: String cr.
endsWithNewLine ifTrue:[
"splits commands based on new lines"
commands := aTurtleProgram splitOn: String cr.
commands do:[:com |
"should split into command and value for command"
i := com splitOn: ' '.
"command"
bo := ci at: 1.
val := ci at: 2.
"value for command"
valInt := val asInteger.
^ bo = 'down' "attempted switch"
ifTrue: [ turtle down: valInt ]
ifFalse: [
bo = 'left'
ifTrue: [ turtle left: valInt ]
ifFalse: [
bo = 'right'
ifTrue: [ turtle right: valInt ]
ifFalse: [
bo = 'up'
ifTrue: [ turtle up: valInt ]
ifFalse: [ self assert: false ] ] ] ] ].
Run Code Online (Sandbox Code Playgroud)
Uko*_*Uko 10
您可以按照它的方式执行此操作,并且可以通过self halt在代码中插入语句来打开调试器.
通常,ifs,以及case-sytle ifs,都是一个坏兆头.所以你可以做的是打破功能到像类DownMove,LeftMove等等,然后当你调用,例如,每个类将实现其自身的功能execute:,会做什么用命令所需的方法.但在你的情况下,这种方法会很麻烦; 而且,你有非常微不足道的行动.
您可以使用带定义的字典.因此,假设您定义了一个实例变量或类变量:
moveActions := {
'down' -> [ :dist | turtle down: dist ] .
'left' -> [ :dist | turtle left: dist ] .
... } asDictionary
Run Code Online (Sandbox Code Playgroud)
然后在你的代码中,你做:(moveActions at: bo) value: valInt.此代码段将为您提供字符串(键)的块(值),然后使用整数计算块.
另一方面,由于操作模式相同且只有消息发生更改,因此您只能映射字典中的消息名称:
moveActions := {
'down' -> #down: .
'left' -> #left: .
... } asDictionary
Run Code Online (Sandbox Code Playgroud)
然后你可以让你的乌龟用字符串动态地执行一条消息:
`turtle perform: (moveActions at: bo) with: valInt`
Run Code Online (Sandbox Code Playgroud)
此外,如果您想依赖于您读取的命令与发送给乌龟的消息之间的相似性,您可以动态组合消息字符串:
`turtle perform: (bo, ':') asSymbol with: valInt`
Run Code Online (Sandbox Code Playgroud)
请注意,在您的情况下不建议这样做,因为首先,您要耦合用户输入和代码,即如果您决定将用户命令从down更改为moveDown,则必须将方法名称更改down:为moveDown:.此外,这种方法允许用户将错误代码"注入"到您的系统中,因为他可以编写一个命令become 42,这将导致代码:
`turtle perform: #become: with: 42`
Run Code Online (Sandbox Code Playgroud)
它将交换乌龟对象和42之间的指针.或者你可以考虑更糟糕的情况.但我希望这次元游览对你有好处.:)
在Smalltalk中,您不使用switch语句.相反,你使用"案例方法"(我认为Ken Beck引入了术语,但我不确定).
在你的情况下,它会是这样的:
method1
"only should begin parsing on new line"
endsWithNewLine:= aTurtleProgram endsWith: String cr.
endsWithNewLine ifTrue:[
"splits commands based on new lines"
commands := aTurtleProgram splitOn: String cr.
commands do:[ :eachCommand |
| tuple direction value |
tuple := eachCommand splitOn: ' '.
direction := tuple first.
value := tuple second asInteger.
self moveTurtleDirection: direction value: value ].
moveTurtleDirection: direction value: value
direction = 'down' ifTrue: [ ^turtle down: value ].
direction = 'left' ifTrue: [ ^turtle left: value ].
direction = 'right' ifTrue: [ ^turtle right: value ].
direction = 'up' ifTrue: [ ^turtle up: value ].
self error: 'Invalid direction'.
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这更清晰,您不需要应用"smalltalk magic"来实现高效设计.这也具有清晰,快速执行并且易于通过编译器和 JIT进行优化的优点:)
| 归档时间: |
|
| 查看次数: |
1168 次 |
| 最近记录: |