Smalltalk 如何将代码块存储在变量中,并在需要时调用它并获取其返回值?
我正在用Smalltalk做一个文本冒险。它由“屏幕”组成,包括文本和其他屏幕的选择。因为我希望游戏是动态的,所以我也希望包括分支。例如,如果玩家在铁匠店里想买一把斧头,那么玩家会立即进入屏幕检查玩家是否有足够的钱,并根据这一点跳转到其他两个屏幕中的一个 我已经有了这个工作:屏幕(名为Smalltalk 如何将代码块存储在变量中,并在需要时调用它并获取其返回值?,smalltalk,Smalltalk,我正在用Smalltalk做一个文本冒险。它由“屏幕”组成,包括文本和其他屏幕的选择。因为我希望游戏是动态的,所以我也希望包括分支。例如,如果玩家在铁匠店里想买一把斧头,那么玩家会立即进入屏幕检查玩家是否有足够的钱,并根据这一点跳转到其他两个屏幕中的一个 我已经有了这个工作:屏幕(名为Place)有一个列表,其中第一项是函数,下面的项是参数。然而,我用一种非常丑陋的方式完成了它:第一项是一个字符串,然后在一个大的“action”方法中与之进行比较,所以它看起来像这样: 游戏数据方法: 动作方法:
Place
)有一个列表,其中第一项是函数,下面的项是参数。然而,我用一种非常丑陋的方式完成了它:第一项是一个字符串,然后在一个大的“action”方法中与之进行比较,所以它看起来像这样:游戏数据方法: 动作方法:(currentScreen也是一个
位置
;该类还包含一个执行实际决策的BranchMoney
方法)
这显然不理想,我想通过这样做来压缩它:游戏数据方法: 行动方法: 因此,游戏不需要进行字符串检查,而是直接按照我想要的方法进行 但是,它似乎不起作用-我尝试过对代码进行不同的更改,问题似乎是
currentScreen:=(currentScreen操作at:1)
行仅将currentScreen的内容替换为代码块内容–它不计算块的内容并使用其结果值(类型为Place
)
我曾尝试在game data方法中使用圆括号–这会抛出一个列表越界异常,因为它试图在添加其他参数之前立即计算表达式。将游戏数据方法中的第一个项目名称更改为currentScreen BranchMoney
似乎没有什么区别。我还尝试在游戏数据方法中添加一个返回值,如下所示:
铁匠动作添加:[^blacksmith BranchMoney]
,这样它将有一个返回值,没有运气。在action方法中执行类似于currentScreen:=[^currentScreen action at:1]
的操作也不起作用。对于一些黑暗中的拍摄,我尝试了
ExternalProcedure
call
和call:
方法,但也失败了。在Smalltalk中,每个块都是一个常规对象,您可以存储和检索与任何其他对象相同的对象:
b := [self doSomething]
存储在b
块中(就像b:=“Hello”
在b
中存储字符串一样)。我认为您缺少的是#值
消息。要执行该块,请执行以下操作
b value "execute self doSomething and answer with the result"
如果您的块只有一个参数,请使用#value:
b := [:arg | self doSomethingWith: arg]
后来
b value: 17 "execute the block passing 17 as the argument"
(对于两个参数使用#value:value:
,对于三个参数使用#value:value:
,对于许多参数使用#valueWithArguments:
)
但是请注意,这种使用块和参数数组的方法看起来并不优雅(甚至不方便)。然而,为了帮助你找到更好的选择,我们需要更多地了解你的游戏。所以,去看看#value
(和朋友们)是否能让你进步一点,然后再回来问你的下一个问题。经过几次迭代后,我们可以引导您走向更清晰的路线
示例
b := [:m | m < 20 ifTrue: ['bad'] ifFalse: ['good']].
在Smalltalk中,每个块都是一个常规对象,可以存储和检索与任何其他对象相同的对象:
b := [self doSomething]
存储在b
块中(就像b:=“Hello”
在b
中存储字符串一样)。我认为您缺少的是#值
消息。要执行该块,请执行以下操作
b value "execute self doSomething and answer with the result"
如果您的块只有一个参数,请使用#value:
b := [:arg | self doSomethingWith: arg]
后来
b value: 17 "execute the block passing 17 as the argument"
(对于两个参数使用#value:value:
,对于三个参数使用#value:value:
,对于许多参数使用#valueWithArguments:
)
但是请注意,这种使用块和参数数组的方法看起来并不优雅(甚至不方便)。然而,为了帮助你找到更好的选择,我们需要更多地了解你的游戏。所以,去看看#value
(和朋友们)是否能让你进步一点,然后再回来问你的下一个问题。经过几次迭代后,我们可以引导您走向更清晰的路线
示例
b := [:m | m < 20 ifTrue: ['bad'] ifFalse: ['good']].
这很有效,谢谢!我想在这里输入更多内容,但是注释将所有内容压缩成一大块文本。简言之,我不再使用列表方法,而是将那些笨拙的add:s转换成类似于
铁匠动作:[铁匠分店钱:20 yes:blacksmith\u good no:blacksmith\u bad]。
,它看起来更漂亮,而且稍微不那么笨拙。再次感谢你的帮助!这很有效,谢谢!我想在这里输入更多内容,但是注释将所有内容压缩成一大块文本。简言之,我不再使用列表方法,而是将那些笨拙的add:s转换成类似于铁匠动作:[铁匠分店钱:20 yes:blacksmith\u good no:blacksmith\u bad]。
,它看起来更漂亮,而且稍微不那么笨拙。再次感谢你的帮助!