Boo(12)-函數

函數定義方法很簡單,比較特別的就是不定個數變數。

// Say
def Say( s as string):
print s
// 也是 Say
def Say( i as int):
print i
// 不定個數
def Say(*args as (object)):
print "len(args)=${len(args)}"
for arg in args:
print arg
// 求平方
def pow( i as int ) as int:
return i*i
Say( "Hello world!" )
Say( 20 )
Say( pow( 2 ) )
Say( 1, "s", join(range(10)) )
a = (5, 8, 1, "end")
Say(*a)

as string、as int…等,其實都可以省略不寫,別忘了 Boo 會自動判定。
然後有看到 Say() 定義了三次嗎?是的,Boo 支援多載(overloading)。
不定個數變數,定義的方法比較特別,要加上 *,然後用法就當作是 enumerator 來用就行了。

ILMerge

這工具可以讓你把 .Net 不同語言編譯出來的 Assembly (組件)合併在一起。
官方網址:ILMerge
安裝以後,用法很簡單:

"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:library /out:[輸出檔名] /lib:[Assembly搜索路徑] [要合併的 Assembly 1] [要合併的 Assembly 2] ...

只想給客戶一個可執行檔,不想給一堆其他組件的時候,這樣作也行:

"c:\Program Files\Microsoft\ILMerge\ILMerge.exe" /t:[exe或winexe] /out:[輸出檔名] /lib:[Assembly搜索路徑] [執行檔] [要合併的 Assembly 1] [要合併的 Assembly 2] ...

對,合併以後,檔案絕對變大,然後千萬不要忘記了,要測試。另外,ILMerge 文件(ILMerge.doc)裡面有些限制以及問題,甚至是用法都有詳細描述,要記得閱讀…

switch-case in boo

Boo本身並沒有類似 switch-case 語法,但是可以藉著 macro 來做到,Boo extensions這個專案已經寫好了。
由於這個專案沒有釋出二進位碼,所以你需要自己 checkout 並編譯。

編譯以後,用法也很簡單,一看就能懂了。

import Boo.PatternMatching  // match 與 case 這兩個 macro 都在這裡面
def getEnglish( i as int ) as string:
s = ""
match i:
case 0:
s = "zero"
case 1:
s = "one"
case 2:
s = "two"
case 3:
s = "three"
otherwise:
s = "unknown"
return s
l = array( typeof(int), range( 5 ) )
for item in l:
print getEnglish( item )

未來 Boo extensions 會包進 Boo 嗎?很難說…Boo extensions 目前仍然很具實驗性…

P.S.

  • 編譯Boo extensions前,請下載最新的 Boo,然後解壓縮以後,放到跟 boo-extensions 同一層。再切換到 boo-extensions/extensions 下執行 nant 即可。
  • 如果 Boo extensions 無法編譯成功,試著修改 extensions/default.build 將編譯 .Test.dll 的幾個地方註解掉,再次編譯即可。這些 .Test.dll 其實是用不到的。

電影流水帳(2008/05/03~2008/05/13)

Eva Green真的正,The Golden Compass裡又再次與Daniel Craig合作,只是沒有對手戲…

  • The Golden Compass(IMDB, Wikipedia),中譯:黃金羅盤。Eva Green還是一樣很正啊,IMDB上說她有演過Arsène Lupin呢,不知道好不好看~言歸正傳,說到這部片子…嗯~或許小說會很好看吧~
  • Untraceable(IMDB, Wikipedia),中譯:Live殺人網站。誠如我老妹所說,的確是普普通通。以技術上來說,要能做到這樣的 live 網站,視訊部份可能需要 P2P TV 的技術,這樣應該可以得到一定的流暢度;以 Blog 來說,要能不被塞爆,恐怕是比較難,會需要比較多台機器…只是,要封一個網站會有多難呢?聯絡ICANN之類的單位把該網域給封了,或是跟這些單位要資訊去查 IP 來源,應該很快就能找到人了吧~這故事算是在騙不懂網路的人吧~

Boo(11)-Hash

Hash 的用法很簡單,同樣地,跟 array、List 一樣,可以用很簡潔的方式來表示,也就是大括號 { }
或者,也可以將符合 key、value 格式的有 IEnumerable 介面的變數傳入 Hash() 函數來取得。

h1 = { 'a': 65, 'b': 66, 'c': 67 }
print h1['a']
h2 = Hash( ( ('a',65), ('b',66), ('c',67) ) )
h3 = Hash( [ ('a',65), ('b',66), ('c',67) ] )

沒有 Generic 版本的 Hash 可以參考 src/boo.lang/Hash.cs,它其實是繼承自 Hashtable﹔有 Generic 版本的,就直接參考 System.Collections.Generic 裡面的 Hash 吧~

Boo(10)-Array

陣列的定義方法主要有兩種:

  • 使用小括號 (,) 來定義。
  • 使用函數: array()、matrix() 來取得。

要得到陣列的大小,則可以使用 len (參考原始碼 tests/testcases/integration/primitives/len-1.boo),直接來看範例吧:

a0 = (,) // 空的陣列
a1 = ( 1, 2, 3, 4, 5 )  // 都是整數的陣列
a2 = array( range(5) )  // 同樣也是得到整數陣列
a3 = matrix( typeof(int), 2, 3 ) // 得到一個 2x3 的陣列,也可以多傳幾個,製造一個瘋狂的多維陣列
a4 = array( typeof(int), 5 )  // 也是得到一個整數陣列
a3[0,0] = 1
a3[1,0] = 2
print "len(a3,0)=" + len(a3,0)  // 得到 a3 第一維的大小
print "len(a3,1)=" + len(a3,1)  // 得到 a3 第二維的大小
for i in a3:
print i
a4 = ( 1, 'a', 2, 'b' )  // 雖然陣列要求都是相同型別,但是這樣寫也可以,只是得到型別都是 object 的陣列
// 輸出結果
// 1
// 0
// 0
// 2
// 0
// 0
// len(a3,0)=2
// len(a3,1)=3

陣列也可以用 Generic 語法(參考原始碼 tests/testcases/parser/array_list_hash_literals.boo),只是我覺得並不是像 List 那麼的必要就是了~:

a5=(of int: 1,2,3)

Boo(9)-List

Boo的 List 並不是使用 .Net/Mono 的 List,而是自己實作。
使用的方法很簡單,用中括號或是使用List函數。

l1=[ 1, 2, 3, 4, "a", "b", "c" ]
l2=List( range(10) )
l1.Add( "d" )
l2.Add( "d" )
print l1
print l2
l1.Remove( "d" )
// 輸出結果
// [1, 2, 3, 4, "a", "b", "c", "d"]
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "d"]
// [1, 2, 3, 4, "a", "b", "c"]

除了正常 List 的操作 Add()、Remove() 以外,還提供了 Push()、Pop(),這意味著可以把 List 當 Stack 來使用。

如果你想知道更多 List 的操作,可以在 booish 裡面使用 dir(),來查看。

>>>l=[]
>>>dir(l)

由於 dir() 會傳回一個 IEnumerator,所以你也可以用下面的程式把每個項目輸出。

l=[]
for m in dir(l):
print m

或者,直接參考 Boo 的原始碼 src/boo.lang/list.cs 。

隨著 .Net framework 2.0 推出,Boo 也支援了 Generic 語法,語法可以參考這篇的說明:Boo Generic Syntax

import System.Collections.Generic
l = List[of int]()
l.Add( 10 )
l.Add( 20 )
for i in l:
print i
l.Add( "hello" )  // 這行將會發生錯誤,告訴你不可以加入字串型別

首要的一件事,就是先 import System.Collections.Generic,表明要使用 Generic,否則之後的程式會無法執行。接著使用 [of Type] 的語法,表示 List 要使用指定 Type 的泛型。

使用泛型最明顯的好處是省去轉型的麻煩,因為 List 裡面預設都是使用 object 型別,改用 Generic 以後,可以預先指定好 List 裡面的元素要使用什麼型別。

電影流水帳(2008/05/02~2008/05/02)

心不在焉地看完了三部片…

  • Blood Diamond(IMDB, Wikipedia),中譯:血鑽石。跟軍火之王一樣,都跟非洲有關係,描繪了殘酷的真實面。還好我老婆不愛鑽石,對石頭沒什麼感覺~
  • 忍 SHINOBI(改編自漫畫:甲賀忍法帖甲賀忍法帖)。漫畫裡是兩邊各派十個人幹架,電影只有五個,看完有點失望,原本以為會跟漫畫一樣有很多精彩對戰畫面,不過,當現實與想像有差距時,那就是…失望。如果你沒看過漫畫的話,不妨看看,還不錯。
  • Monster House(IMDB, Wikipedia),中譯:怪獸屋。講萬聖節的故事,屋子因為女主人的怨念而成怪,男主人愛房子,不忍心毀去,為了保護其他人,而變得兇惡、不近人情。小男孩和他的兩個朋友找到了真相,並且解放了這間房子。我覺得還不錯看的故事~