September 2,2008

booish 與 booc 編譯後的執行結果不同?

Boo Programming Language網上論壇發現了這個討論串:Problems with BooPrimer 發問者表示同樣的程式在 booish 執行與用 booc 編譯後的執行結果不同,我大吃一驚,趕緊試試,發現真的是跟發問者講的一樣,心想完蛋,怎麼會這樣...
i = 0
while i < 5:
    print i
    i += 1 
隔了一天,有人(Stoo)回覆了,說 booish 在執行結束後,會再次印出 i 的值,並建議改成這樣,可以更能看出問題所在:
i = 0
while i < 5:
    print "i=${i}"
    i += 1 
果然,執行結果就如同他回覆所說的一樣:
i = 0
i = 1
i = 2
i = 3
i = 4
5 

Posted by elleryq at 樂多Roodo!17:35回應(0)引用(0)

August 20,2008

在 ASP.Net 裡使用 Boo

方法很簡單,只要修改 web.config,然後把 Boo 相關的 assembly 放到 bin 目錄下即可:
<configuration>
	<system.web>
		<compilation debug="true">
			<assemblies>          
				<add assembly="Boo.Lang.CodeDom" />
			</assemblies>
			<compilers>
				<compiler language="Boo" extension=".boo" type="Boo.Lang.CodeDom.BooCodeProvider, Boo.Lang.CodeDom" compilerOptions="-ducky -utf8"/>
			</compilers>
		</compilation>
		<customErrors mode="Off"/>
	</system.web>
</configuration>
要注意的是,如果你的應用程式不是 code behind 而且 Hosting 是 IIS 或是 .NET framework 內建的小 web server 時,會有問題。問題出在 Indent,Boo 對於 Indent 很敏感,不知道為甚麼,在 Microsoft.NET 下,Indent 就是會錯。使用Mono XSP的話,則沒有問題。 是故,你可以改使用 code behind 的方式繞過這問題。 會發現這問題,是因為有人在 boolang 討論群組裡問了這問題:boo on asp.net,我去試才知道的。最後提問者改用 xsp...

Posted by elleryq at 樂多Roodo!16:38回應(0)引用(0)

July 22,2008

讓 Banshee 啟動時自動播放音樂之二

每次都從第一首播放,實在太沒意思,所以在播放前切換為 Shuffle 模式,播放時,就會隨機挑選一首開始播放,然後再關閉 Shuffle 模式。
import System
import System.IO
import Banshee.ServiceStack
import Banshee.PlaybackController

def AutoPlay() as bool:
        ServiceManager.PlaybackController.ShuffleMode = PlaybackShuffleMode.Song
        ServiceManager.PlayerEngine.Play()
        ServiceManager.PlaybackController.ShuffleMode = PlaybackShuffleMode.Linear

def OnClientStarted( client as Client ):
        Hyena.Log.Information( "engine is playing now..." )
        GLib.Timeout.Add(1500, AutoPlay)
        Banshee.ServiceStack.Application.ClientStarted -= OnClientStarted

Hyena.Log.Information( "autoplay script is loaded." )

Banshee.ServiceStack.Application.ClientStarted += OnClientStarted
p.s. 上次有提到要作自動記錄播放與自動播放記錄曲目的功能,我的確是做了,只是在播放完指定曲目後,又跳回第一首,這表示我還得繼續研究原始碼才行,所以暫時不釋出。

Posted by elleryq at 樂多Roodo!9:39回應(0)引用(0)

July 15,2008

用 Boo 寫 Web Service

必須先將以 Boo 寫的 Web Service 編譯為 Assembly,然後再製作一個以 c# 或 vb.net 寫的 asmx 繼承該 Web Service 類別才行。 否則會遇到 "The invoked member is not supported in a dynamic module." 的錯誤。 我是在遇到錯誤的時候,去參考 boo 源碼 examples/asp.net 下的 Math.asmx 與 Math.asmx.boo 才知道這件事情的。 本來我還在納悶,為甚麼 examples/asp.net 下會有一個用 c# 寫的 asmx,還以為是搞錯了呢~
// Math.asmx.boo
// 要先編譯好,放在 bin 目錄下:booc -t:library -out:bin/Math.dll Math.asmx.boo
import System.Web.Services

[WebService]
class Math:
        [WebMethod]
        def Add(a as int, b as int):
                return a+b

        [WebMethod]
        def Multiply(a as int, b as int):
                return a*b
<%@WebService Class="MathService" Language="C#" %>
// Math.asmx
public class MathService : Math  // 繼承用 Boo 寫的 Math 類別
{
}

Posted by elleryq at 樂多Roodo!14:08回應(0)引用(0)

July 4,2008

讓 Banshee 啟動時自動播放音樂

主要是利用上一篇介紹的 BooScript Extension,讓 Banshee 能在一開始就播放音樂...
BooScript Extension 在載入時,會檢查是否有 script 要執行,有的話,會進行編譯並執行,所以這個時候 Banshee 內部還有許多事情還沒初始完成,所以必須要將 AutoPlay 的動作排程到 Application.ClientStarted 裡,讓 Application 啟動之後去執行 AutoPlay 的動作。
import System
import System.IO
import Banshee.ServiceStack

def OnClientStarted( client as Client ):
	Hyena.Log.Information( "engine is playing now..." )
	ServiceManager.PlayerEngine.Play()

Hyena.Log.Information( "autoplay script is loaded." )

Banshee.ServiceStack.Application.ClientStarted += OnClientStarted
就這麼簡單,下次要加上自動記錄播放與自動播放記錄曲目的功能。

Posted by elleryq at 樂多Roodo!10:09回應(0)引用(0)

June 27,2008

Boo(20)-Generator 函式

Generator 函式其實就跟 C# 的 Iterator 一樣,利用 yield 關鍵字先把值傳回讓呼叫者使用。 使用 Generator/Iterator 最大的好處是可以讓函式只做必要的邏輯,而不需要把一些事情綁在迴圈裡面。 下面就是一個很標準的尋訪目錄樹的範例,尋訪的工作交給 walk,主程式則負責依據傳回的值作處理。
import System
import System.IO

def walk( path as string ):
  di = DirectoryInfo( path )
  for d in di.GetDirectories():
    yield d as FileSystemInfo
  for f in di.GetFiles():
    yield f as FileSystemInfo

for node in walk( "." ):
  if node isa DirectoryInfo:
    print "[${node.Name}]"
  elif node isa FileInfo:
    print node.Name
參考自:Generators p.s. 這系列文章一定會持續寫到 macro 出現為止。

Posted by elleryq at 樂多Roodo!14:08回應(0)引用(0)

June 20,2008

Boo 的 currying

拜讀了Jserv大的"以 C 語言實做 Functional Language 的 Currying"Thinker大的"真 C 語言實做 Functional Language 的 Currying"以後,決定也來挖掘一下 Boo 的 currying 寫法,根據這篇文章:Boo Programming Language Languages Currying Def Return World,程式碼出乎意料的簡單:
//Currying:
plusX = { a as int | return { b as int | return a + b }}

print plusX(3)(4) 
就這樣。老實說,大概懂了,可是又不是很懂,也沒想到用途。 所以,就跟沒懂是一樣的。

Posted by elleryq at 樂多Roodo!19:20回應(0)引用(0)

June 16,2008

Boo(19)-例外處理

例外處理的語法與 Python 相近,差別在於 Boo 使用 ensure,而 Python 使用 finally。
除此之外,Boo 統一使用 except 處理各種例外,而 Python 使用 else 處理無法處理的例外型態。
import System

class MyException(Exception):
  _msg as string
  def constructor( s as string ):
    _msg = s
  override def ToString() as string:
    return "MyException::${_msg}"

// 試著調整這兩個變數試試看
isExceptionHappen = false
isMyExceptionHappen = true

try:
  // .. do something ...
  if isExceptionHappen:
    raise Exception("Something wrong.")  // 提出例外情況
  // ...
  if isMyExceptionHappen:
    raise MyException("Hey!!")
except e as MyException:
  print e.ToString()
except e as Exception:
  print e.Message
ensure:
  print "不管有沒有錯誤,這裡都會被執行。"
參考:Boo Primer - 例外Python tutorial - 8. Errors and Exceptions

Posted by elleryq at 樂多Roodo!17:29回應(0)引用(0)

June 13,2008

Boo(18)-命名空間

.NET上的語言幾乎都導入命名空間了,Boo 無法置身事外...

命名的方式,則是在原始檔第一行加上: namespace 命名空間名稱
撇開註解不算,命名空間的宣告,無論如何都要是程式碼的第一行,否則會有錯誤發生。

引用時,則是使用 import 關鍵字,例如:
import System

Console.WriteLine( "Hello world!" )

// 為甚麼要引用命名空間?因為這樣寫很累...
System.Console.WriteLine( "Hello again." )
你也可以指明組件(Assembly)的名稱,所以這幾種寫法也行:
import System.Data from System.Data
import Gtk from "gtk-sharp"

對了,組件不需要特別加上 ".dll"

Posted by elleryq at 樂多Roodo!16:47回應(0)引用(0)

June 6,2008

Boo(17)-結構與列舉

結構(struct)跟類別很類似,最明顯的差別在於 class 被換成 struct 了,類別的一些特性也可以在結構上使用。 其他的差別:無法繼承類別、結構,只能實作 Interface﹔結構是值型別,在複製實體時,是整個克隆(Clone)而不是像類別一樣,只做參考。
struct Dog:
  def constructor( name ):
    _name=name
  [property(Name)]
  _name as string
emptydog=Dog()
print "emptydog.Name=${emptydog.Name}"  // 什麼都沒印出
lucky=Dog("Lucky")
print "lucky.Name=${lucky.Name}"  // 印出 Lucky
列舉(enum),如果你有用過 C/C++/C# 的話,應該不陌生:
// 宣告列舉
enum Day:
    Sunday
    Monday
    Tuesday
    Wednesday
    Thursday
    Friday
    Sunday
// 也可以指定數值
enum Task:
    TODO=100
    FIXME=101
// 列印
print Day.Sunday
// 尋訪列舉型別裡所有元素
for s in Enum.GetNames(Day):
    print s
// 另一種
for n,v in array( zip( Enum.GetNames(Task), Enum.GetValues(Task)) ):
    print "${n}=${v}"

Posted by elleryq at 樂多Roodo!14:21回應(0)引用(0)
 [1]  [2]  [3]  [4]  [最終頁]