2015-08-08 115 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的榮譽! :-) –