魯班語言第三章: 魯班部件入門

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  http://project.soft114.com/lubankit/index_chinese.html

3. 魯班部件入門

The least flexible component of any system is the user.
- Lowell Jay Arthur


這一章講述魯班部件模型的基本構造. 魯班部件在魯班語言里的關鍵字是struct和C語言里的struct關鍵字一樣. 下面大家可以看見魯班部件和C語言的struct有某種相似之處. 這一章主要通過例子來講述怎樣構造和使用魯班部件. 更多的細節和更正式的定義在下一章還有敘述.


3.1 魯班部件構造

設想我們的」世界, 你好」程序變得很流行, 大家都想用. 怎樣讓大家可以共用這個程序呢? 魯班的辦法很簡單, 就是把這個魯班腳本程序變成一個魯班部件. 看如下例子:



namespace demo; //指明所屬名字空間



struct helloworld( ) //部件名字定義

as process // 部件是一個過程

{

std::println(obj=「Hello, world!」); // 原來的腳本代碼

}



把以上代碼敲入一個叫」hello.lbn」的文件里. 然後我們在另一個叫」callhello.lbn」的文件里輸入以下魯班腳本程序:



demo::helloworld(=);



然後在你的計算機的操作系統命令行打入以下命令啟動魯班執行這個程序.



Mycomputer > luban hello.lbn callhello.lbn

Hello, world!



在以上例子里, 在」hello.lbn」文件里我們定義了我們的第一個魯班部件」demo::helloworld」. 讓我們一行行看這個魯班部件是怎麼定義的. 第一行是指明我們這個部件所屬於的名字空間」demo」. 所有魯班部件都必須屬於一個名字空間. 所以魯班部件定義代碼的第一行必須指明所屬名字空間. 這一點和Java相似. 下一行用struct關鍵字表明這是一個魯班部件名字叫做」helloworld」. 再下一行的」as process」表明這個魯班部件是一個過程. 魯班部件可以是一個過程或者組合. 以後章節會講述什麼是組合. 這裡大家只要知道到目前為止講的所有的魯班程序腳本都是過程就行了. 最後我們把原來的」世界, 你好」腳本程序代碼放到一對花括弧里, 這個全名叫做」demo::helloworld」的魯班部件就算定義好了.

可以看出, 將魯班腳本變成魯班的部件是很簡單的. 基本上就是兩點, 一是指明一個所屬名字空間, 二是給它起個名字. 然後把腳本代碼放到一對花擴號里就好了.



在」callhello,lbn」文件里, 我們只是寫了一個一行的魯班腳本程序來調用我們剛定義的魯班部件」demo::helloworld」. 大家可能已經注意到, 調用魯班部件類型的語法有點特別, 象」demo::helloworld(=)」. 其中細節下面會講述, 這裡大家只要知道」demo::helloworld(=)」意思是調用魯班部件」demo::helloworld」就行了.


3.2魯班部件的輸入和輸出屬性

在上一節的例子里, 我們定義了一個魯班部件」demo::helloworld」. 這個部件只在屏幕上印出」Hello, World!」. 調用時不需要任何輸入, 也不產生任何輸出. 在實際應用中, 一般的魯班部件會接受輸入併產生輸出. 下面是一個簡單的帶輸入和輸出屬性的魯班部件.



namespace demo;



struct greeting

(

input:

saywhat, towhom;

output:

greetingmsg;

)

as process

{

msg = input.saywhat + 「, 「 + input.towhom + 『!』;

std::println((obj=msg);

output.greetingmsg = msg;

}



以上魯班代碼定義了一個魯班部件」demo::greeting」. 這個部件有兩個輸入屬性」saywhat」, 「towhom」分別是」說什麼」和」對誰說」的意思. 這個部件的輸出屬性是」greetingmsg」. 在這部件內部是一個過程(process). 這個過程將兩個輸入屬性連接成一個標準的問候語, 然後放在」greetingmsg」輸出屬性里. 在這過程中還把產生的問候語列印在屏幕上.

大家可以看見, 上面這個例子和前一個例子不一樣的地方是, 上一個例子在部件名字后的擴號里沒有內容, 而上面這個例子在擴號里有輸入和輸出屬性的定義. 在部件過程的定義部分, 魯班總是用input.name格式表示輸入屬性, 用output.name表示輸出屬性.

現在我們把上面魯班代碼存入到一個叫」iohello.lbn」的文件里. 再寫一個小腳本程序來調用這個叫做」demo::greeting」的部件, 腳本程序代碼如下:



demo::greeting(saywhat=」Hello」, towhom=」you」);



把以上魯班腳本程序存入一個叫」calliohello.lbn」的文件里, 然後在操作系統命令行打入如下命令執行我們編好的魯班程序.



Mycomputer > luban iohello.lbn calliohello.lbn

Hello, you!



這個魯班程序執行時會運行在」calliohello.lbn」里的腳本程序, 「calliohello.lbn」會調用魯班部件」demo::greeting」, 「demo::greeting」被調用時回列印出問候語.

再回頭看調用」demo::greeting」的魯班腳本代碼:
demo::greeting(saywhat=」Hello」, towhom=」you」);

從這行代碼可以看出調用魯班部件時, 輸入屬性的設置是通過把屬性值賦予屬性名字來實現的. 這一點和C/C++/JAVA都不一樣. 只有PYTHON的函數調用有類似的語法.


3.3 魯班部件的多種用法

上一節講述的例子是定義一個魯班部件, 然後象調用C函數一樣來調用. 需要指出的是除了能象函數一樣調用外, 魯班部件還有其他多種用法. 首先魯班部件可以是一個對象, 它的輸入和輸出屬性是構成魯班部件對象的狀態. 這和C函數完全不一樣. C函數可以說是沒有狀態的. 魯班部件對象可以象一般數據對象一樣傳遞和複製, 其輸入輸出屬性可以被外界讀寫. 下面例子列舉魯班部件的調用方法.



//第一行

greeter = demo::greeting(saywhat=」」, towhom=」」); //調用並建造魯班部件

//第二行

greeter.saywhat = 「Hello」; // 寫輸入屬性, 印出 Hello,!

//第三行

greeter.towhom = 「world」; //寫輸入屬性, 印出Hello, world!

//第四行

greeter(saywhat=」Nice to meet you」); // 部件對象動態調用,印出Nice to meet you, world!

//第五行

greeter(=); //部件對象動態調用,印出 Hello, world!

//第六行

greeter.(saywhat = 「How are you」, towhom=」Luban」); //多屬性設置, 印出How are you,Luban!

//第七行

greeter.(=); //空白部件多屬性設置,印出How are you,Luban!

//第八行

msg = greeter.greetingmsg; //讀部件對象輸出屬性

//第九行

std::println(obj=msg);// 印出 How are you, Luban!



把以上代碼存入一個叫」allhello.lbn」的文件里. 然後打入如下命令運行這段魯班腳本:



Mycomputer > luban iohello.lbn allhello.lbn

,!

Hello,!

Hello,world!

Nice to meet you,world!

Hello,world!

How are you, Luban!

How are you, Luban!

How are you, Luban!



下面我們逐行解釋這個魯班腳本程序:



1. 第一行是魯班部件對象調用加建造, 它的語法和前面已經講過的部件類型調用基本一樣. 唯一不同的是此處我們把調用結果賦予一個叫」greeter」的變數. 魯班部件類型調用的結果是產生一個新的魯班部件對象. 這個新的魯班部件對象的屬性會被設置成調用者所指定的值, 然後魯班會運行這新的部件再將這個新部件對象返回給調用者. 此處我們把返回的魯班部件對象賦予變數」greeter」. 此處這個新魯班部件運行時會在屏幕上列印問候信息. 因為我們在」saywhat」, 「towhom」輸入屬性設置的都是空字元串, 所以列印出來的問候是」, !」. 只有標點符號沒有詞語.



要點: 魯班部件類型調用不但會運行被調用的部件類型, 還會產生新的部件對象.



2. 第二和第三行是魯班屬性賦值. 第二行把字元串」Hello」賦給」saywhat」屬性. 第三行把字元串」world」賦給」towhom」屬性. 每次設置輸入屬性值的時候, 魯班部件都會被自動運行一次. 第一次運行時, 屬性」saywhat」被賦予字元串」Hello」, 但屬性」towhom」還是原來的空字元串, 所以列印出」Hello, !」. 第二次運行時」towhom」被賦予了字元串」world」, 所以列印出」Hello, world!」



要點: 每次設置魯班部件對象輸入屬性值時, 都會自動引發魯班部件執行.



3. 第四和第五行都是魯班部件對象動態調用. 可以看出魯班部件對象動態調用的語法和魯班類型調用是基本一樣的. 不同的只是這裡使用的是對象變數名而不是魯班類型名. 第四行調用時把」saywhat」設置成」Nice to meet you」, 「towhom」屬性則沒有改變, 所以魯班部件運行時列印出」Nice to meet you, world!」. 需要指出的是魯班部件動態調用時也會複製自己, 然後運行, 最後返回新的部件對象. 就和魯班部件類型調用時一樣. 調用時設置的屬性值只是對新複製的部件, 對原部件並沒有影響. 所以在第五行的另一個魯班部件對象動態調用時, 我們沒有設置任何屬性值(在括弧里只有等號=表示不另外設置屬性值), 列印出的內容是原來的」Hello, world!」. 我們在這裡沒有把魯班返回的新對象賦予變數, 而是簡單放棄了.



要點: 魯班部件對象動態調用時傳遞的屬性值對原部件對象沒有影響, 因為魯班會複製一個新的部件對象來運行. 傳遞的屬性值只設置在新的對象. 所以原來的魯班部件對象屬性不變.



4. 第六行是一次多個屬性設置. 以上說過每次設置部件的輸入屬性值時都會引發部件運行. 有時侯我們想設置多個輸入, 但是我們只需要部件在所有屬性設置完以後運行一次. 這種情況就需要做多個屬性一次性設置. 在這行代碼我們把」greeter」的輸入屬性」saywhat」設置成」How are you」, 把」towhom」設置成」Luban」. 雖然有兩個屬性設置, 但是」greeter」部件只運行一次. 所以列印出一行」How are you, Luban!」. 多個屬性一次設置的語法和魯班部件調用的語法幾乎一樣. 唯一的區別是多個屬性一次設置在部件對象名字和括弧之間有一個句點號(DOT).


要點: 多個屬性一次設置只會引發魯班部件執行一次.



5. 第七行是一個空白的多屬性設置. 雖然沒有任何屬性被賦值, 這個魯班部件仍會被執行一次. 所以又列印一個」How are you, Luban」. 請注意雖然」greeter(=)」和」greeter.(=)」都會引發部件執行. 但它們一個是魯班部件調用「greeter(=)」, 調用時會先複製部件, 然後執行. 另一個」greeter.(=)」是部件屬性設置, 不會複製新對象, 只執行原有的對象. 這一行代碼也驗證我們上一行的多個屬性設置是成功的.



要點: 如果要只執行魯班部件而不要複製的新魯班部件對象, 用屬性設置, 不要用魯班部件對象調用. 空白多屬性設置也會引發魯班部件執行.



6. 第八是讀取魯班部件屬性值. 此行讀取魯班部件對象」greeter」的屬性」greetingmsg」的值, 賦值給變數」msg」. 如果你回到魯班部件」demo::greeting」的定義, 你可以看見它除了列印問候語外, 還將問候語字元串放在輸出屬性」greetingmsg」里. 所以我們可以在這裡讀取這個屬性值.



7. 第九行把變數」msg」的值列印出來. 變數的值是」How are you, Luban!」. 所以此次列印出地三個」How are you, Luban!」.



從以上例子, 我們可以看見你可以對魯班部件做的操作有:

* 設置部件屬性值. 可以用單個或多個屬性設置語法. 設置屬性值會引發魯班部件執行.
* 讀取魯班部件屬性值.
* 調用魯班部件. 可以是直接魯班部件類型調用, 或者是魯班部件對象調用. 調用時可以從新設置屬性值. 調用會複製新的魯班部件對象. 從新設置的屬性值對原魯班部件對象沒有影響.


3.4 魯班的傳值調用規則

在調用魯班部件時, 屬性參數設置傳遞的一定是數據對象值. 魯班語言里沒有指針和位地址類型. 這一點和C++/Java都不一樣. 寫慣C的人可能會寫象下面的代碼:



namespace demo;



struct NotWorkingSwapObj

(

input:

x,y;

)

as process

{

temp = input.x;

input.x = input.y; // 此處語法錯

input.y = temp; //此處語法錯

}



以上代碼想交換兩個變數的內容. 但是魯班會報告語法錯誤. 錯誤是試圖給輸入屬性從新賦值. 魯班不允許在部件定義內部給輸入屬性賦值. 給輸入屬性賦值只能在部件外部進行.


3.5 魯班腳本程序和魯班部件定義程序

到現在我們已經看見過兩類魯班程序. 一是魯班腳本程序. 魯班腳本程序是簡單的魯班語句和表達式序列. 當碰到魯班腳本程序, 魯班解釋器會立即運行這腳本程序.

另一種是魯班部件定義程序, 就象我們上面看見的」demo::greeter」部件定義. 部件定義總是以宣布所在名字空間開始, 因為所有魯班部件都必須屬於一個名字空間. 然後部件定義會指明部件名字, 輸入輸出屬性序列, 和內部實現代碼. 魯班解釋器處理魯班部件定義時, 只是把部件定義存入內部名字空間里, 然後等待調用或建造. 不會直接運行這魯班部件.

一般的使用方法是用魯班腳本作為程序起點. 而用魯班部件定義程序來組成部件庫.






[火星人 ] 魯班語言第三章: 魯班部件入門已經有312次圍觀

http://coctec.com/docs/program/show-post-71896.html