http://blog.csdn.net/idisposable
First Eye on Boo Language
在.NET平台上,除了IronPython之外,Python還有另外一個親戚 - Boo。
但是Boo語言並不真正是Python語言的實現,它只是有著和Python一樣的外衣而已。
===========================================================
下面是我讀BooPrimer的學習筆記,:)
1. 跟其他的語言教程一樣,BooPrimer也是從"hello, world"開始。
print "Hello, World!"
或者
print ("Hello, World")
是不是跟Python中一樣?在Python 2.6及以前的print statement採用前一種形式;在Python 3.0之後,print已經成為了一個函數。Boo支援兩種形式,我想也是為了和Python相容吧。
BooPrimer推薦使用宏(print "Hello, World!")的形式,跟Python中的發展方向不一致。下面看看這二者編譯之後的代碼吧(編譯之後用.NET Reflector查看的代碼)。
(a) print "hello, world" 編譯後的代碼是:
Console.WriteLine("hello, world")
(b) print ("hello, world")編譯後的代碼:
Builtins.print("hello, world")
至於Builtins.print具體做了什麼,有興趣的讀者可以自己去看看。
2. String interpolation (字串插入)
String interpolation讓字串格式化變得很方便。看看例子:
toy = "kitty"
print "hello, ${toy}"
這裡能夠插入到字串中的可以是任何合法的Boo運算式。當展開字串時,Boo會計算該運算式,然後調用運算式結果的ToString方法。可以寫幾行簡單的代碼驗證這一點。代碼如下:
class TestObject:
def ToString():
return "This is an instance of class TestObject"
obj = TestObject()
s = "Result: ${obj}"
3. 在Boo中所有的所有都是對象
這一點不用多解釋了,Boo和Python一樣 - 在它們的世界裡,什麼都是對象,內建基礎資料類型(如整型,字元,字串),程式碼片段,解譯器都是對象。甚至類型本身也是對象(先前沒有接觸過Python/Boo的也許會覺得這很瘋狂吧)。
>>> obj as object
>>> print obj == null
>>> true
>>>
主要上面的代碼中用了as關鍵字顯式地指定了對象的類型。這也是Boo區別與Python的一個地方 - 可以指定對象的類型來增強安全性。而且有一點一定別忘記:Boo並不是真正動態類型的語言,所以對象在其生命週期中類型是固定的。
4. 檢測對象的運行時類型(Runtime type of an object)
跟Python不同,Boo因為基於.NET,它的類型系統也是使用.NET的Common Type System (CTS)。
檢測對象的方式也和.NET一致。
(a) obj.GetType()
(b) typeof
不過我發現typeof一點都不好用。如下所示:
>>> l = [1, 2, 3]
>>> typeof(l)
Error: The name 'l' does not denote a valid type.
>>> t = l.GetType()
Boo.Lang.List
>>> typeof(t)
Error: The name 't' does not denote a valid type.
>>> typeof(Boo.Lang.List)
>>> Boo.Lang.List
>>>
typeof跟Python中的type()比較起來顯得太死板了。
5. 內建函數 (Builtin Functions)
Boo支援一些內建函數如 print, gets, prompt, join, map, array, matrix, iterator,
shellp, shell, shellm, enumerate, range, reversed, zip, cat等。
6. 自訂函數
Boo中自訂函數的文法和Python是一樣的。但是對於成員函數的定義和Python有些不同,我將在以後的系列文章中詳述。
這裡是幾個自訂函數的例子:
def Hello():
print "hello"
#這個函數指定了傳回值類型
def Hello() as string:
print "hello"
def Hello(name):
print "hello, ${name}"
#這個函數指定了參數的類型
def Hello(name as string):
print "hello, ${name}"
為參數和傳回值指定類型使得程式安全性提高了,Boo可以對參數和傳回值進行類型檢查。
7. Overloading
Boo在函數重載方面做的比Python好很多。來看簡單的例子吧。
def Hello():
return "Hello, World!"
def Hello (name as string):
return "Hello, ${name}!"
def Hello(num as int):
return "Hello, Number ${num}!"
def Hello(name as string, other as string):
return "Hello, ${name} and ${other}!"
8. 可變參數
Boo也支援可變參數。e.g.
>>> def Test(*args as (object)):
>>> return args.Length
>>> print Test("hey", "there")
2
>>> print Test(1, 2, 3, 4, 5)
5
>>> print Test("test")
1
>>> a = (7, 9, 8)
>>> print Test(*a)
按照BooPrimer最後一個測試Test(*a)應該返回3。 但是實際使用Boo 0.7.6的結果是出錯:
ERROR: The best overload for the method 'Input27Module.test(*(object))' is not compatible with the argument list '(*(int))'.
9. 屬性和欄位 (property and field)
Boo區別property和field,這對於.NET程式員來說比較舒服。也可以在Boo中通過attribute來定義properties。
class Cat:
[Property(Name)] // 這是一個屬性。通過對它的訪問來讀寫欄位_name
_name as string // 這是一個欄位,不能從類的外部存取,應該使用屬性來訪問它。
看下邊的setter/getter是不是跟C#裡邊的很象啊?
class Cat:
[Getter(Name)]
_name = 'Meowster'
[Setter(FavoriteFood)]
_favoriteFood as string
fluffy = Cat()
print fluffy.Name
fluffy.FavoriteFood = 'Broccoli'
上邊的setter/getter都是隱式的形式,再來看看顯式屬性的例子。
class Cat:
Name as string:
get:
return _name
set:
_name = value
_name as string
9.1 Pre-condition of property
class Cat:
[Property(Name, Name is not null)]
_name as string
fluffy = Cat()
fluffy.Name = null # 對Name屬性設定空值會引發ArgumentException異常
不知道C#中有沒有相似的特性?
10. Class modifiers
public, protected, internal, protected internal, private, abstract, final
"public" is assumed if no modifier is specified
Boo向.NET學習定義了一堆的class modifiers, 這樣細粒度的存取控制能夠滿足更好的安全性。
11. interface support
這是Boo相對於Python的一個優點 - 從語言層支援介面的概念。
e.g.
interface IFeline:
def Roar()
Name:
get
set
12.實值型別和參考型別
和.NET一樣, 所有的類(class)都是參考型別;基礎類型為實值型別,如int, long, double, bool, byte等。實值型別永遠都擁有值(不能設定為null),他們有預設值,例如數實值型別的預設值為0。
13. Class member methods
定義成員方法和Python的文法類似,不同點在於不需要self關鍵字。
class Cat:
def Roar():
print "Meow!"
cat = Cat()
cat.Roar()
14. 建構函式和解構函式 (Constructor and Destructor)
class Cat:
def constructor():
_name = "Whiskers"
def destructor():
print "${_name} is no more..."
[Getter(Name)]
_name as string
cat = Cat()
print cat.Name
因為.NET的不確定性析構的問題,所以你的代碼不能夠依賴解構函式被調用。你不知道它什麼時候會被調用,也許永遠都不會。
15. Method modifiers
abstract: 抽象方法
static: 靜態方法
virtual, override - 虛方法和方法重寫。
這些都和C#/.NET是一致的。
16. Member visibility
成員的可見度分為幾種: public, protected, provate
如果沒有顯式聲明,所有的欄位預設都是protected, 而方法(methods),屬性(properties)和事件(events)預設都是public。
17. 在建構函式中聲明屬性 (Declaring Properties in the constructor)
這是一個比較好用的語言特性,算是文法糖吧。
class Box:
def constructor():
pass
[Property(Value)]
_value as object
box = Box(Value: 42)
print box.Value
18. 多態和繼承
多態和繼承是物件導向的兩個本質特性。Boo語言中的多態和繼承沒有什麼特別的地方,跟C#語言一樣,這樣不再贅述。
19. 結構體 (structs)
Boo語言中的結構體完全是從.NET借過來的。結構體是實值型別,也可以定義自己的方法。
e.g.
struct Rectangle:
def constructor(w as int, h as int):
_w = w
_h = h
_x as int
_y as int
def Area():
return _w * _h
20. 名字空間 (namespace)
跟Python相比這的確是個好東西 - Python只能借用module來對付名字衝突。
20.1 聲明名字空間
在檔案頭部這樣來聲明名字空間
namespace MyNamespace
class TypeInTheNamespace():
pass
如果需要匯入另外的名字空間呢?也很簡單,就想C#一樣。
import System
import MyNamespace
import Gtk from "gtk-sharp" // quoted because there is a special character '-'.
21. 枚舉 (enumerations)
沒有什麼特別的地方,看例子吧。
enum Day:
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
class Action:
[Property(Day)]
_day as Day
22. 異常 (exceptions)
拋出異常 (raising exceptions)
e.g.
import System
def Execute(i as int):
if i < 10:
raise Exception("Argument must be greater or equal to 10.")
print i
捕獲異常 (catching exceptions)
捕獲異常有三種形式:try-except, try-ensure, 和try-except-ensure
看看下邊的例子。
# try-except example
import System
try:
print 1 / 0
except e as DivideByZeroException:
print "oops"
print "Doing other stuff"
# try-ensure example
import System
try:
s = MyClass
s.DoSomethingBad()
ensure:
print "This code will be executed, whether there is an error or not."
這裡的ensure跟C#的finally是等同的東西。
try-except-ensure是上邊兩種形式的結合。
# try-except-ensure example
import System
try:
s = MyClass
s.DoSomethingBad()
except e as Exception:
print "Problem! ${e.Message}"
ensure:
print "This code will be executed, whether there is an error or not."
23. 函數調用和多線程 (functions as objects and multithreading)
在Boo中,一切都是對象,所以函數也不例外。每個函數都有三個方法:
Invoke: 跟正常調用函數一樣
BeginInvoke: 啟動一個背景工作執行緒來運行這個函數
EndInvoke: 等待先前啟動的線程完成函數調用並返回計算結果。
因為Boo提供便利的非同步函數調用,多線程編程變得很容易。
24. generators (產生器或產生子,怎麼翻譯都覺得難聽)
用過Python的讀者對generator一定不陌生。
generator 運算式的文法定義:
<expression> for <declarations> [as <type>] in <iterator> [if|unless <condition>]
e.g.
>>> List(x for x in range(5)) // 最簡單的形式
[0, 1, 2, 3, 4]
>>> List(x for x in range(5) if x % 2 == 0)
[0, 2, 4]
generator 方法:
gemerator方法使用yield關鍵字,這樣的方法看起來象普通的方法但是能夠給調用者多次返回。
是不是難明白,看看例子就知道了。
def TestGenerator():
i = 1
yield i
for x in range(10):
i *= 2
yield i
print List(TestGenerator())
generator是繼承自IEnumerable,所以可以和for ... in 一起使用。
25. 宏 (macros)
Boo提供了幾種宏讓編程更便利。不過我有一個疑問:不知道Boo是否支援使用者自訂的宏?
print Macro
這個我們已經熟悉了。 e.g.
print "Hello there"
print "Hello", "there"
print "first", "second", "third", "more", "more and more"
assert macro
這個是防禦性編程的寶貝。
assert true // 總是會通過
assert false, "message" // 總是會失敗
using macro
跟C# 中的using 用法一樣,為受保護對象提供了一個生命週期控制。
e.g.
using w = StreamWriter("test.txt"):
w.WriteLine("Hello there!")
lock macro
和C#一樣,lock macro用來在多線程環境下同步對象的訪問。
e.g.
lock database:
database.Execute("UPDATE messages SET id = id + 1")
debug macro
和print Macro類似,不同點在於print輸出到System.Console, 而debug macro輸出到System.Diagnostics.Debug。
26. Duck typing
也許不翻譯是最容易理解的了,:)
definition: duck typing is a humorous way of describing the type non-checking system. initially coined by Dave Thomas in the Ruby community, its premise is that (referring to a value) "if it walks like a duck, and talks like a duck, then it is a duck."
Even though Boo is a statically typed language, Duck Typing is a way to fake being a dynamic language. Duck typing allows variables to be recognized at runtime, instead of compile time. Though this can add a sense of simplicity, it does remove a large security barrier.
e.g.
d as duck
d = 5 // 現在d是一個整型
print d
d += 100 // 能夠做任何整型允許的操作
d = "hello" // 閑雜d變成了字串類型了
print d
d = d.ToUpper() // 可以執行任何字串操作了
print d
================================================================================================================
Boo的學習筆記就到這裡為止了。以後對它的瞭解多了再來寫吧。
相關串連:
1. Boo http://boo.codehaus.org/ Boo的官方網站
2. SharpDevelop http://www.icsharpcode.net/OpenSource/SD/ 提供了一個Boo的IDE環境
3. IronPython的介紹 http://blog.csdn.net/IDisposable/archive/2008/10/08/3035790.aspx