电竞比分网-中国电竞赛事及体育赛事平台

分享

.net平臺(tái)新語(yǔ)言——Boo 試用

 quasiceo 2014-01-15

最近幾年中,得益于Java和.NET平臺(tái)良好的可擴(kuò)展性,在這兩個(gè)平臺(tái)上都出現(xiàn)了一大批令人激動(dòng)的新語(yǔ)言。在Java領(lǐng)域內(nèi),人們欣喜地看到了 JRuby和Groovy這兩門(mén)語(yǔ)言的出現(xiàn),它們均在語(yǔ)法、動(dòng)作(Action)方面提供了很高程度的靈活性。若合理使用的話,會(huì)大大提高開(kāi)發(fā)者的生產(chǎn)效 率。.NET平臺(tái)上也確實(shí)出現(xiàn)了不少創(chuàng)造性的新語(yǔ)言,微軟公司官方支持的IronPython和F#都讓人們對(duì)CLI的靈活性和可擴(kuò)展性充滿了信心。

在IronPython和F#受到廣泛關(guān)注和支持的同時(shí),其他一些同樣基于CLI的語(yǔ)言也在默默地爭(zhēng)取著自己的生存空間。例如開(kāi)源社區(qū)所推崇的L#(一門(mén)CLI上運(yùn)行的基于Lisp的語(yǔ)言)、IronRuby和Ruby.NET等兩個(gè)Ruby的實(shí)現(xiàn)等。

很多這類(lèi)創(chuàng)新都是將現(xiàn)有的語(yǔ)言移植到CLI平臺(tái)上(例如,IronPython就是CLI上的Python語(yǔ)言,就像JRuby是JVM上的 Ruby語(yǔ)言一樣),但也出現(xiàn)了一些全新的、擁有自己獨(dú)特語(yǔ)法的語(yǔ)言,雖然這些全新的語(yǔ)言也難免受到目前如日中天的各種流行語(yǔ)言的影響。boo就是其中之 一。boo是CLI平臺(tái)上的一種靜態(tài)類(lèi)型的語(yǔ)言,其很多特性都受到了Python的影響,但卻又不是Python的簡(jiǎn)單移植。實(shí)際上,boo并不在意代碼 的縮進(jìn),也不強(qiáng)迫我們使用self關(guān)鍵字。另外,boo從根本上來(lái)講還是一種靜態(tài)類(lèi)型語(yǔ)言,這也與Python的動(dòng)態(tài)特性不盡相同。

借助于boo所內(nèi)建的語(yǔ)言特性以及簡(jiǎn)單的語(yǔ)法結(jié)構(gòu),加上其靜態(tài)特性,我們可以用該語(yǔ)言更加高效地編寫(xiě).NET應(yīng)用程序,程序的執(zhí)行效率甚至也能與 C#不相上下。另外,在boo中,我們還可以使用任何CLI平臺(tái)上的現(xiàn)存類(lèi)庫(kù),boo代碼同樣能夠容易地在其他CLI語(yǔ)言中被重用!

使用boo開(kāi)發(fā)非常簡(jiǎn)單

Rodrigo B. de Oliveira曾經(jīng)對(duì)C#的很多過(guò)于嚴(yán)格的編碼規(guī)則(例如類(lèi)型的強(qiáng)制轉(zhuǎn)換)及其不能通過(guò)shell測(cè)試運(yùn)行代碼感到非常郁悶。于是boo語(yǔ)言應(yīng)運(yùn)而生, 并很快發(fā)展成一個(gè)非常方便的.NET和Mono通用的平臺(tái),基于該平臺(tái),我們能夠創(chuàng)建GUI原型、單元測(cè)試甚至游戲等各類(lèi)程序。

學(xué)習(xí)boo的最簡(jiǎn)單方法就是從boo的交互shell開(kāi)始,boo的交互shell又名booish。在booish中,我們即可靈活地任意察看代碼片斷,進(jìn)而理解boo的語(yǔ)法規(guī)則。

對(duì)于最常見(jiàn)的hello world程序來(lái)講,boo的視線非常簡(jiǎn)單——print加上將要輸出的字符串即可。

>>> print "Hello Scary World!"
Hello Scary World!

需要說(shuō)明的是,我們還可以將上述代碼保存在代碼文件中,然后使用booi命令執(zhí)行該源文件。

C:\dev\projects\acme>booi src\helloworld.boo
Hello scary world!

我們還可以用booc命令將helloworld.boo腳本編譯成為Windows可執(zhí)行文件,即將boo代碼編譯成合法的CLI應(yīng)用程序。

C:\dev\projects\acmi>booc -out:bin/helloworld.exe src/helloworld.boo
Boo Compiler version 0.7.6.2237 (CLR v1.1.4322.2032)
C:\dev\projects\acme\bin>helloworld.exe
Hello scary world!

boo是一種靜態(tài)類(lèi)型的語(yǔ)言,每個(gè)變量都有自己的類(lèi)型。例如,我們可以創(chuàng)建一個(gè)值為“Hello World”的string類(lèi)型變量:

>>> var = "Hello world"
'Hello world'
>>> var.GetType()
System.String

注意到這里并沒(méi)有顯式地將var聲明為string類(lèi)型,但由于boo的靜態(tài)特性并根據(jù)該變量被設(shè)置的值,var就自動(dòng)地被設(shè)置成了string類(lèi)型。

boo字符串

與Python類(lèi)似,boo為字符串、集合等類(lèi)型添加了很多靈活的內(nèi)建(built-in)功能支持,讓我們舉例說(shuō)明。

boo支持字符串改寫(xiě)(使用${}語(yǔ)法),還支持Python風(fēng)格的多行字符串。

>>> adj = "scary"
'scary'
>>> print "Hello ${adj} world"
Hello scary world

多行字符串非常易于使用,更不用擔(dān)心字符轉(zhuǎn)義等問(wèn)題。

firstname = "Joe"
lastname = "Dirt"
accountid = "A499"
amount = "1.32"

msg = """



"""

與Python和Ruby類(lèi)似,正則表達(dá)式和集合類(lèi)型(例如list和map)的支持內(nèi)建到了boo語(yǔ)言本身中,并提供了語(yǔ)法上的快捷使用方式。

正則表達(dá)式通過(guò)“/”定義,其實(shí)際的類(lèi)型為System.Text.RegularExpressions.Regex。匹配則通過(guò)Perl風(fēng)格的“=~”操作符完成。例如,如下代碼即可用來(lái)匹配郵政編碼信息:

>>> regx = /^\d{5}([-]\d{4})?$/
^\d{5}([-]\d{4})?$
>>> if '22101-4444' =~ regx:
print "yes"

boo的集合類(lèi)型

boo支持三種內(nèi)建的集合類(lèi)型:普通數(shù)組(長(zhǎng)度固定,且只能包含某一確定類(lèi)型的數(shù)據(jù))、列表(長(zhǎng)度可變,能包含不同類(lèi)型的數(shù)據(jù))以及哈希表(用來(lái)存儲(chǔ)名稱(chēng)/值對(duì))。

數(shù)組

數(shù)組用來(lái)保存一系列相同類(lèi)型的對(duì)象,不能超過(guò)某個(gè)預(yù)定的長(zhǎng)度。在boo中的創(chuàng)建語(yǔ)法如下:

>>> myarray = (1,2,4,5)
(1, 2, 4, 5)

我們也不能在數(shù)組中添加不同類(lèi)型的數(shù)據(jù)。

>>> myarray.SetValue(6, 3)
>>> myarray
(1, 2, 4, 6)
>>> myarray.SetValue('test', 3)
System.InvalidCastException: Object cannot be stored in an array of this type.
at System.Array.InternalSetValue(Object value, Int32 index1, Int32 index2, Int32 index3)
at Input50Module.Main(String[] argv)

列表

列表是一類(lèi)長(zhǎng)度不固定的、可被索引且能夠包含多種不同類(lèi)型的數(shù)組。這是一種非常靈活的類(lèi)型,通過(guò)從Python中借來(lái)的方括號(hào)([])創(chuàng)建,屬于Boo.Lang.List類(lèi)型。

>>> mylist = [1, 2, 3, 4]
[1, 2, 3, 4]
>>> mylist.GetType()
Boo.Lang.List
>>> mylist.Add('test')
[1, 2, 3, 4, 'test']

可以看到,boo中的列表能夠包含不同類(lèi)型的對(duì)象,還能夠使用Add方法添加新元素。若想了解列表目前包含了什么,我們可以使用Contains方法,甚至還能夠通過(guò)詢(xún)問(wèn)邏輯問(wèn)題實(shí)現(xiàn):

>>> mylist.Contains(3)
true
>>> 'test' in mylist
true

哈希表

boo中的哈希表是一個(gè)保存名稱(chēng)/值對(duì)的容器。這些名稱(chēng)/值對(duì)均可為不同的類(lèi)型。

>>> myhash = {".NET":"boo", "Java":"Groovy"}
{'Java': 'Groovy', '.NET': 'boo'}

哈希表通過(guò)名稱(chēng)/值對(duì)實(shí)現(xiàn),因此,若是輸入了名稱(chēng),那么將得到其值。在下面的代碼中,我們輸入了".NET",得到了'boo'。

>>> myhash[".NET"]
'boo'

我們還可以使用ContainsKey或ContainsValue方法搜索哈希表。

>>> myhash.ContainsKey('Java')
true
>>> myhash.ContainsValue('Groovy')
true

 

迭代

與Python和Ruby類(lèi)似,boo也允許我們?nèi)菀椎貙?duì)集合類(lèi)型進(jìn)行迭代。不過(guò)boo不支持Ruby或Groovy中常見(jiàn)的塊(block)和閉包(closure)。

列表的迭代

通常情況下,boo中的迭代是使用for語(yǔ)句實(shí)現(xiàn)的:

>>> mylist
[1, 2, 3, 4, 'test']
>>> for value in mylist:
... print value
...
1
2
3
4
test
>>> myint
9
>>> myarray
(1, 2, 4, 6)
>>> for i in myarray:
... print 2*i
...
2
4
8
12

哈希表的迭代

我們也可以在哈希表上進(jìn)行迭代:

>>> myhash
{'Java': 'Groovy', '.NET': 'boo'}
>>> for key in myhash:
... print key.Value
...
Groovy
boo

需要注意的是,因?yàn)閎oo的哈希條目存貯在System.Collections.DictionaryEntry類(lèi)型中,所以我們可以根據(jù)需要訪問(wèn)其Key和Value成員。

>>> for key in myhash:
... print key.Key
...
Java
.NET

 

boo中的函數(shù)

boo允許我們?cè)陬?lèi)定義之外創(chuàng)建函數(shù),這一點(diǎn)非常類(lèi)似于Python和Groovy。在boo中,函數(shù)是“一等公民”(即函數(shù)本身也是對(duì)象),使用def關(guān)鍵字創(chuàng)建。

例如,如下代碼定義了一個(gè)值為'boo'的字符串。需要注意的是對(duì)于字符串類(lèi)型,boo中沒(méi)有Python那樣內(nèi)建的lower方法。但創(chuàng)建一個(gè)lower方法卻相當(dāng)?shù)暮?jiǎn)單:使用def關(guān)鍵字定義,并通過(guò)“as ”語(yǔ)句指定參數(shù)類(lèi)型即可。

>>> str  = "Boo"
'Boo'
>>> str.GetType()
>>> lower(str)
----^
ERROR: Unknown identifier: 'lower'.
>>> def lower(val as string):
... return val.ToLower()
...
>>> print lower(str)
boo

 

boo中的IO

通過(guò)使用using關(guān)鍵字,boo讓文件操作變得非常簡(jiǎn)單。我們根本不用擔(dān)心文件處理中的一些常見(jiàn)問(wèn)題,例如關(guān)閉文件等,因?yàn)閡sing語(yǔ)句將自動(dòng)為我們做好這些。

例如,讀寫(xiě)某個(gè)本地文件將非常容易:

>>> import System.IO
>>> myfile = "SampleFile.txt"
'SampleFile.txt'
>>> using input = File.OpenText(myfile):
... for line in input:
... print line
...
Welcome to an easy
way to read files
using the most unscary language around:
BOO!

通過(guò)使用函數(shù),我們可以重新創(chuàng)建Groovy中g(shù)etText風(fēng)格的方法:

>>> import System.IO
>>> def GetText(file as string):
... retString = " "
... using input = File.OpenText(file):
... for line in input:
... retString += line
... return retString
...
>>> myfile = "SampleFile.txt"
'SampleFile.txt'
>>> assert GetText(myfile).Equals('Welcome to an easy way to read files using the most unscary language around: BOO! ')
>>>

 

與NAnt集成

通過(guò)boo任務(wù),boo能夠與NAnt編譯文件協(xié)同工作。下面這個(gè)例子就演示了boo與NAnt協(xié)同工作能夠完成的任務(wù)——在某個(gè)dll上應(yīng)用FxCop,然后用boo將其中Critical Errors的個(gè)數(shù)統(tǒng)計(jì)出來(lái):

   value="${build.dir}\bin\${build.config}\fxcop.xml"/>

import System.IO
fpath = Project.Properties['fxcop.xml']
numerror = 0
using input = File.OpenText(fpath):
for line in input:
if line =~ /Level="CriticalError"/:
numerror++

print("There were ${numerror} Critical Errors")

 

在boo中單元測(cè)試非常簡(jiǎn)單

因?yàn)閎oo能夠與其他CLI庫(kù)共同使用,所以boo代碼也能夠容易地使用NUnit的屬性。

例如,如下代碼使用了用來(lái)測(cè)試數(shù)據(jù)庫(kù)的NDbUnit,并用NUnit創(chuàng)建了一個(gè)簡(jiǎn)單的測(cè)試用例。在該測(cè)試用例中,我們使用NDbUnit的API插入一些數(shù)據(jù),然后確認(rèn)這些數(shù)據(jù)確實(shí)保存到了數(shù)據(jù)庫(kù)中。

可以看到,與C#相比,boo代碼顯得簡(jiǎn)潔許多。因?yàn)閎oo并不使用分號(hào)和大括號(hào),且類(lèi)型聲明也少了很多。

import NUnit.Framework
import NDbUnit.Core.OleDb
import NDbUnit.Core
import System.Data
import System
import System.Data.OleDb

[TestFixture]
class WordTest:

final CONN = "Provider=SQLOLEDB...."
final SCHEMA = "Dataset2.xsd"
final XML = "XMLFile2.xml"
fixture as OleDbUnitTest

[SetUp]
def configure():
fixture = OleDbUnitTest(CONN)
fixture.ReadXmlSchema(SCHEMA)
fixture.ReadXml(XML)

[Test]
def VerifyWordTableOle():

fixture.PerformDbOperation(DbOperationFlag.CleanInsert)
select = "select spelling from word where word.word_id = 2"

adapter = OleDbDataAdapter(select , CONN)

dta = DataSet()
adapter.Fill(dta, "word")
table = dta.Tables["word"]

for row as DataRow in table.Rows:
Assert.AreEqual("pugnacious", row[0],
"word spelling wasn't pugnacious")

若你想以最快的速度開(kāi)發(fā)單元測(cè)試,那么boo將是一個(gè)明智的選擇。因?yàn)锽oo支持屬性(IronPython并不支持),因此與NUnit配合起來(lái)也沒(méi)有任何問(wèn)題。

靜態(tài)卻不失動(dòng)態(tài)特性

雖然我們并不需要顯式聲明變量的類(lèi)型,但boo卻的的確確是一種靜態(tài)類(lèi)型的語(yǔ)言。boo在底層根據(jù)變量的值來(lái)自動(dòng)決定變量的類(lèi)型。例如,如下一段腳本創(chuàng)建了一個(gè)string類(lèi)型,并嘗試調(diào)用一個(gè)并不存在的方法。

var = "BOO"
var.lower()

嘗試編譯該腳本,將得到如下錯(cuò)誤:

C:\dev\projects\acme>booc -out:bin/statictypes.exe src/statictypes.boo
Boo Compiler version 0.7.6.2237 (CLR v1.1.4322.2032)
src/ statictypes.boo(3,5): BCE0019: 'lower' is not a member of 'string'.
1 error(s).

若是直接運(yùn)行該腳本,也將得到同樣的錯(cuò)誤:

C:\dev\projects\acme>booi src\statictypes.boo
src\statictypes.boo(3,5): BCE0019: Boo.Lang.Compiler.CompilerError: 'lower' is not a member of 'string'.

盡管如此,boo在類(lèi)型方面仍提供了很多便利。通過(guò)使用duck類(lèi)型,我們可以推遲編譯期類(lèi)型檢查。若某個(gè)變量的類(lèi)型為duck,boo將嘗試用反射的方式調(diào)用方法。例如,若我們將var聲明為duck類(lèi)型,那么將不會(huì)得到編譯期錯(cuò)誤。而若是直接運(yùn)行這段腳本,將得到一個(gè)不同的錯(cuò)誤:

C:\dev\projects\acme>booi src\statictypes.boo
System.MissingMethodException: Method System.String.lower not found.
at System.RuntimeType.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Obje
ct[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters)
at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] ar
gs)
at Boo.Lang.Runtime.RuntimeServices.Invoke(Object target, String name, Object[] args)
at StatictypesModule.Main(String[] argv)

借助于duck類(lèi)型,boo能夠以非常優(yōu)雅的方式編寫(xiě)測(cè)試程序并控制Internet Explorer:

>>> ie as duck =
System.Type.GetTypeFromProgID("InternetExplorer.Application")()
System.__ComObject
>>> ie.Visible = true
true
>>> ie.Navigate2("http://www.")
>>> links = ie.Document.getElementsByTagName("a")
System.__ComObject
>>> site = "http:///2007/02/04/currying-maximum-favor-with-groovy/"
'http:///2007/02/04/currying-maximum-favor-with-groovy/'
>>> for link in links:
... if(link.href.Equals(site)):
... link.click()
...
mshtml.HTMLAnchorElementClass

注意到變量ie的類(lèi)型為duck,這樣即可更加優(yōu)雅地將執(zhí)行消息傳遞給該實(shí)例,而并不會(huì)導(dǎo)致任何錯(cuò)誤。

找到頁(yè)面上的某個(gè)鏈接之后,我們可以點(diǎn)擊該鏈接,然后精確驗(yàn)證隨后頁(yè)面中的內(nèi)容。

>>> h3s = ie.Document.getElementsByTagName("h3")
System.__ComObject
>>> for h3 in h3s:
... if(h3.id.Equals("comments")):
... assert h3.innerText =~ "5 Responses"
...
mshtml.HTMLHeaderElementClass
>>> ie.Quit()

 

使用boo進(jìn)行開(kāi)發(fā)將顯得非常自然

得益于其寬松的語(yǔ)法規(guī)則,boo允許我們以更加輕松快捷的方式完成.NET平臺(tái)上的任務(wù)。若你正在設(shè)計(jì)程序的原型,或是創(chuàng)建用戶界面元素,那么 boo將是個(gè)絕佳的選擇。不僅如此,使用boo創(chuàng)建的所有程序或組件均可以無(wú)縫地與其他.NET類(lèi)庫(kù)配合使用,無(wú)論這些組件是用C#、VB.NET還是托 管C++編寫(xiě)的。boo是一種.NET平臺(tái)上非常友好的語(yǔ)言,讓我們能夠不受約束地快速編寫(xiě)代碼。還躲什么呢——今天就來(lái)試試boo吧!

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多