链接关键字消息

时间:2015-08-08 19:08:25

标签: smalltalk

假设我有一个对象x,它可以接受任何一个选择器,s1s2,...,{{1} }。让我们进一步假设在对象上操作的这些选择器中的任何一个的结果是相同类型的更新对象。然后我可以"链"这些选择器(只要它们是一元消息)如我所愿,例如:

sn

这将取x s1 s2 ... sn 的结果并应用选择器x s1,然后将选择器s2应用于该结果,依此类推。我想以某种顺序应用这些选择器中的一个或多个以获得各种结果:

s3

在Smalltalk中,如果选择器是一元消息,我可以这样做。但是,如果我的选择器是关键字消息,我就不能再这样做了。如果x s8 s2 单独接受选择者xs1:,...,s2:,则以下内容无效:

sn:

x s1: a1 s2: a2 ... sn: an 运算符:

;

但是使用级联:每个阶段都会修改原始的x s1: a1 ; s2: a2 ; ... ; sn: an ,在这种情况下我不想修改x

要关联关键字消息,我想我已经在括号中使用了以下语法:

x

如果我有3个或更多的keywrod消息,这让我觉得我在LISP中编程。这个的具体例子可以是多维数组。如果(...(((x s1: a1) s2: a2) ... sn: an) 是一个三维数组,并且你想访问数组中2,3,5位的对象,我认为它看起来像:

foo

当然,这是一个微不足道的例子,但说明了这一点。可能有其他类型的嵌入对象,或者您对最终结果感兴趣的其他连续对象操作链。

在Smalltalk中有更多的语法上有吸引力的方法吗?我假设没有其他运营商,也许是(((foo at: 2) at: 3) at: 5) some_object_selectors 运营商的表兄(例如我们使用;),这会将它们链接起来,例如:

&

由于我想以任何或几乎任何所需的顺序(可能是不同的结果)应用选择器,因此选择器形式x s1: a1 & s2: a2 & ... & sn: an 太局限了。此外,这提供了一种已经存在于其他语言中的工具,例如Ruby,它可以等效地表示为:

s1:s2:s3:...

缺少一个特殊的运算符,另一种选择可能是传递一个选择器 - 参数对的数组,或者可能是一个选择器 - 参数对的查找表。查找表需要设置传递文字(必须创建和填充),这使我倾向于数组,因为我可以简单地将其写为:

x.s1(a1).s2(a2)...sn(an)

这仍然有点笨重,而且我不太确定这比使用所有括号更优雅。我担心我的问题可能至少部分是主观的,但我很想知道最佳实践可能是什么,以及运营商是否存在我不知道哪些可能会有所帮助,或者是否存在由Smalltalk标准机构娱乐。

2 个答案:

答案 0 :(得分:8)

这里似乎有些混乱。

  1. 级联使用;完成,其中每条消息都发送到同一个参数。
  2. 您的x s1 s2...示例(您称之为“级联”)称为消息链接,其中每条消息都发送到上一条消息的结果(由于美丽而优雅的性质) Smalltalk的语法,只是Object message并且总是返回结果)。不,你不能总是把它们放在任何顺序。设想s1multiplyByTwos2addTwox的实例变量由这些方法修改,以1开头。订单可能很重要。 (请注意,我非常不愿意使用这些非常简短的名字作为例子 - 它不像Smalltalk那样。; - )
  3. 如果你的n太大,以至于使用括号使它看起来很尴尬,那么,呃...对不起,但是你做错了。
    • 考虑在对象上创建一个接受多个参数的方法。
    • 考虑创建一个包装器对象来携带参数。
    • 考虑使用设计模式将对象与要对其执行的操作分离。 (您需要哪种模式取决于您希望实现的目标; here's a good starting point。)
  4. 而不是寻找操作员将Smalltalk弯曲到你的意愿(你可能习惯用其他语言做事),我建议改为弯曲Smalltalk的意愿(显式命名,不要害怕创建更多的对象)和方法等)。从长远来看,你会从中获得更多,我敢说你会希望其他语言具有Smalltalk的简单性和强大功能。

答案 1 :(得分:1)

通常我们给这个对象x一个主题进行操作,然后在我们完成它时请求这个改变的主题。复制效率很低。

Object subclass: #Foo
    instanceVariableNames: 'subject'
    classVariableNames: ''
    poolDictionaries: ''
    category: 'Try'

order: y
    self subject order: y

select: z
    self subject select: z

subject
    ^subject ifNil: [ subject := FooSubject new ]

where: x
    self subject where: x