2015-08-08 76 views
7

让我们假设我有一个对象,x,它可以接受任何一个选择器,s1,s2,...,sn。我们进一步假设对这个对象进行操作的任何一个选择器的结果都是一个相同类型的更新对象。然后我可以“链”,这些选择器(只要它们是一元的消息)如我所愿,如:链接关键字消息

x s1 s2 ... sn 

这将需要的x s1结果和应用选择s2,然后应用选择s3到那结果,等等。我想申请在一些为了一个或多个这些选择的各种结果:

x s8 s2 

在Smalltalk中,我可以做到这一点,如果选择是一元的消息。但是,如果我的选择器是关键字消息,我不能再执行此操作。如果x单独接受选择,s1:s2:,...,sn:,那么下面不起作用:

x s1: a1 s2: a2 ... sn: an 

还有就是;操作:

x s1: a1 ; s2: a2 ; ... ; sn: an 

但使用级联 :每个阶段都沿途修改原始的x,我不想在这种情况下修改x

要链接的关键字的消息,我想我使用下面的语法与左括号:

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

这让我觉得我在Lisp程序,如果我有3个或更多keywrod消息。一个具体的例子可能是一个多维数组。如果foo是一个3维数组,你希望在位置2,3,5阵列中的访问对象,我认为它看起来像:

(((foo at: 2) at: 3) at: 5) some_object_selectors 

那是当然的一个简单的例子,但说明案子。一个可能有其他类型的嵌入对象,或其他连续对象操作链,您对最终结果感兴趣。

在Smalltalk中是否有语法上更有吸引力的方法?我假定没有其他操作,也许是表弟;运营商(比方说我们用&为例),这将连锁它们,如:

x s1: a1 & s2: a2 & ... & sn: an 

因为我想申请的选择以任何或几乎任何期望的顺序(对于可能不同的结果),选择器表格s1:s2:s3:...太局限了。此外,这给已存在于其它语言,如红宝石,设施哪里会被等效地表示为:

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

缺乏一个特殊操作,另一种可能是通过选择参数的对阵列,或者可能是选择器参数对的查找表。查找表需要设置为通过文本(它必须创建和填充),这让我瘦朝着一个数组,因为我可以简单地把它写成:

x { {s1. a1}. {s2. a2}. ... {sn. an} } 

这仍然是一个有点笨重,而且我米不太确定这是比只使用所有括号更优雅。恐怕我的问题可能至少有一部分是主观的,但我有兴趣知道最佳实践可能是什么,以及运营商是否存在,我不知道哪些可能有所帮助,或者是否有人正在通过Smalltalk进行娱乐标准组织。

+0

好的问题,有时也表示为消息管道或管道 - 您不是第一个错过此功能的人,它定期在邮件列表中进行讨论。我推荐这个优秀的博客http://blog.3plus4.org/2007/08/30/message-chains/ –

+0

@ aka.nice是的,看起来他们在8年前打败了我。 :) – lurker

回答

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 
+0

我明白了。例如,我正在寻找一种方法来获得与x.s1(a1).s2(a2)... sn(an)相同的效果,例如,不必诉诸所有括号。主题x是我可能想要在不同的时间对不同的选择器集应用不同的操作。所以我不想改变它。如果它发生变化,那么我必须在这种情况下复制它,所以我再次以原始形式复制它。如果我想保存一个在其上执行了一些操作的对象,我会这样做,'newX:= x s1:a1 |例如,s3:a3.'。 – lurker

+0

你想达到什么目的?我不确定如何用该构造编写可理解的代码。 –

+0

这种结构被普遍用于Ruby on Rails。当用'ActiveRecord'构造查询时,可以做一些事情,比如'Foo.where(...)。order(...)。select(...)',但是'Foo'没有改变。代码的语义非常清晰。也许在这种情况下,在Smalltalk paradyme中,我确实需要每次复制一个'Foo'并让操作员修改它。我将不得不提出一些想法。 – lurker

8

这里似乎有些混淆。

  1. 级联使用;,其中每个消息被发送到相同的参数来完成。
  2. x s1 s2...例子(你所谓的“级联”)被称为消息链接,其中每个消息被发送到先前消息的结果(由于Smalltalk的语法的美丽和优雅的本质,这简直是Object message和总是返回结果)。不,你不能总是把它们放在任何位置。设想s1multiplyByTwos2addTwo,x具有通过这些方法修改的实例变量,其开始为1。订单可能很重要。 (请注意,我非常不愿意使用如此短的名字作为例子 - 它不是很Smalltalk的样子;;)
  3. 如果你的n是如此之大,使用括号使它看起来很尴尬,那么,呃..抱歉,但你做错了。
    • 考虑在您的对象上创建一个方法来接受多个参数。
    • 考虑创建一个包装对象来携带您的参数。
    • 考虑使用设计模式将您的对象与要执行的操作分离。 (哪一种模式,你需要将取决于你想要达到的目标。here's a good starting point

而不是找一个运营商弯曲的Smalltalk,以你的意志(你可以如何利用其他做事语言),我建议向Smalltalk的意愿倾斜(明确命名,不要害怕创建更多的对象和方法等)。从长远来看,你会从中得到更多的收益,而且我敢说你会希望其他语言具有Smalltalk的简单性和强大功能。

+0

感谢您的输入。我很抱歉,我有错误的术语。我最近开始学习ST,并已经忘记了术语的差异。至于“n”有多大,有多大?我认为如果它是4或5,它看起来很丑。但这是主观的。当然,我试图更好地理解语言哲学,并且已经阅读了很多。我不一定“试图屈服于我的意志”,而是寻求理解。对我来说(最近转换为ST),只链接*没有参数的选择器的能力似乎与我不一致。 – lurker

+0

我意识到我不能总是按照我想要的顺序放置消息。我正在谈论一个问题,就我而言,我*确实希望这样做。因此,我不能把它当作强制命令的's1:s2:s3:...'。感谢您提供链接,我会阅读它。 – lurker

+0

不用道歉,只是想我会澄清一下,因为我在第一次阅读问题时感到困惑。当然,你是正确的,它是主观的。我发现从其他语言来到Smalltalk的人往往更不愿意创建新的(小)对象和方法。对消息顺序足够公平,谢谢解释。听起来好像你可能是在模式之后,那么。尝试_get_ Smalltalk的荣誉! :-) –