Posts RSS Comments RSS  

Archive for May, 2007

你寫 vs. 你被寫

大約半年前我在一篇 blog 中提到我打算分割目前的 blog 一事。有朋友問,為什麼要再分割下去呢?現有的 blog 還不夠多嗎?

最近比較知道該怎麼回答這個問題了。我覺得寫作的媒介是有質感的。一定程度上我對 blog 這個媒介產生了某種疲勞感。完全不若那時決定要開始寫 blog 時,pesty 設定了一套 Moveable Type ,然後開始重新撿拾 HTML 語法、尋找說話的方式,以及看到自己從記事本中所打出的文字,套上了清爽的 default theme 之後的美麗樣子。

另一個原因是「你寫」和「你被寫」。簡言之就是:我們總認為主題是操控在自己手上,實際上是當一個寫作空間有了歷史和累積後,它本身予人的印象(「這是個什麼樣 blog」以及「寫 blog 的是什麼樣的人」),就會形成一種紋理,反過來制約寫東西的人,必須順著這樣的紋理來說話。而我最近覺得,我的 blog 有如斷裂的歷史,如果只看 2006 年之前與之後的,說不定會覺得這根本是兩個人吧。

除了寫作的疲態之外,最近也對閱讀 blog 一事感到疲勞。主觀地說是超出自己認知負荷。也許是尋找下一種表達方式和提供資訊管道的時候了,一如從 BBS 與個人報台到 blog 的過程那般。

Ruby Tuesday: 2007/5/29 (二) 在 OPCafé

每雙週二舉行的 Ruby Tuesday,5/29 (二) 同樣在新竹市中心的 OPCafé 舉行。

這次的 Ruby Tuesday ,我請來 b6s 來為我們客座講解 Apache Lucene 的基本原理。Lucene 是以 Java 寫成的全文搜尋程式庫,可說是最普遍的 search solution。由於 Ruby 的 Ferret 是根據 Lucene 的設計來實作,因此在基本概念、術語、特性上,都有和 Lucene 貼近的地方。b6s 對於全文搜尋──以及全文搜尋所根基的諸多自然語言處理的理論──瞭解深入。我想如果能讓大家對於 tokenizing, analysis, indexing 等概念有更清楚的認識,相信選用 web app 的搜尋方案時,會能更精準找到自己要的,以及做出正確的 trade-off 決定。

除了 b6s 主講 Lucene,我會補充說明 Ferret,尤其是 acts_as_ferret 這套 plug-in 的使用方法。

歡迎大家屆時來 OP !

Cocoa Tuesday: 2007/5/22 星期二 20:00在OP

這週二是 Cocoa Tuesday,打算來講一些 Cocoa 繪圖以及文字繪製的基礎,地點一樣是在OPCafé

acts_as_ferret: Rails全文搜尋快速上手(與中日韓文支援)

Here are some code snippets that I use to add CJK (Chinese, Japanese and Korean) characters support to Ferret and acts_as_ferret.

(Update: lingr.com has released their multilingual analyzer, see http://blog.lingr.com/2007/05/a_new_plugin.html for detail).

相信許多鐵道迷都聽過雪貂(Ferret)。雪貂是一套根據Lucene所開發的全文搜尋引擎。裝上了「化身為雪貂」(acts_as_ferret)這套plug-in之後就更厲害了,任何ActiveRecord model只要加上輕量之人最愛的神秘一行,瞬間就具有了全文搜尋能力。

Ferret是用C寫成的,用語和基本觀念與Lucene一致。因此對Lucene有認識的朋友應該很容易上手。雖然說化身為雪貂很好用,不過O’Reilly的Ferret一書仍有一讀的必要。該書最後還介紹如何配合其他plug-in來index諸如PDF, JPEG EXIF等metadata,幾乎可以寫一套小型的Mac OS X Spotlight。而該書對於Ferret的構成、內部運作原理、performance tuning的介紹,也相當實用(而且,不需要先學Lucene;我也還在研讀這一部份就是了……)。

以下是我用的 RegExpAnalyzer,僅僅很簡單的把歐語的單詞拆開、數字拆開,中日韓文則以字元方式來索引。這種簡單的中日韓文tokenizing在搜尋精確度不要求高的場合,大體能用。要更好的搜尋結果,或是要做到同音字搜尋、簡繁搜尋,當然就需要更複雜的 Analyzer。

請找個地方填入以下的 regex 跟 Analyzer:

GENERIC_ANALYSIS_REGEX = /([a-zA-Z]|[\xc0-xdf][\x80-\xbf])+|[0-9]+|[\xe0-\xef][\x80-\xbf][\x80-\xbf]/
GENERIC_ANALYZER = Ferret::Analysis::RegExpAnalyzer.new(GENERIC_ANALYSIS_REGEX, true)

然後在想要加入搜尋的 model 裡加入:

acts_as_ferret({:fields => [ FIELDS_YOU_WANT_TO_INDEX ] }, { :analyzer => GENERIC_ANALYZER })

之所以不把 GENERIC_ANALYZER 放在 acts_as_ferret 裡,除了可重用性的原因,另外還避免掉在 Mongrel + Rails development mode 時可能造成的 bus error / segmentation fault (原因不明)。

總之,只要做完這件事,就可以:

Model.find_by_contents("hola")

acts_as_ferret很聰明,如果是第一次使用,會幫你把這個data model所用table全部讀一遍,建立必要的全文索引。之後所有的 CRUD 動作只要透過這個 model ,「化身為雪貂」會幫你做完所有該做的 Ferret indexing 動作。

先前有一些中文論壇提到用 /./ 來處理中文斷字(說「斷詞」或「分詞」有誤導之嫌)。雖然 Ruby 的 regex engine 在 $KCODE 設為 utf-8 時,可以正確地以 /./ 來掃描 Unicode 字元,但是這樣的作法是有問題的。英文詞因此會被斷成一個字元一個字元。而,單純用 [a-zA-Z] 則忽略了歐語,這是不夠的。

偏偏 Ruby 的 Unicode 支援只做了一半,不像 Perl 可以用 /\x{80}-\x{7ff}/ 的方式來表達 Unicode range,所以我們得祭出 jcode.rb 裡處理 UTF-8 的 regex (也就是利用 UTF-8 的特性),來找出實際上為 U+80 ~ U+7FF 以及 U+800 ~ U+FFFF 的字元。當然,> U+FFFF 的字元這裡並沒有處理,而且這個方式其實過於簡化。

但總之這是可以用的方法。如果要測試或改善 regex ,可以使用Ferret一書中第65頁所列的以下方法來測試:

def test_token_stream(token_stream)
  puts "Start | End | PosInc | Text"
  while t = token_stream.next
    puts "%5d |%4d |%5d   | %s" % [t.start, t.end, t.pos_inc, t.text]
  end
end

然後在irb中:

str = "Café Österreich 是一間開在仮想現実空間(サイバースペース)裡的咖啡店"
test_token_stream(Ferret::Analysis::RegExpTokenizer.new(str, GENERIC_ANALYSIS_REGEX))

就可以看到 RegExpTokenizer 執行的效果。

OpenVanilla subversion repositoy搬家

昨天(台北時間 2007/5/15 中午)我們在 OpenVanilla 討論區中發布了 OpenVanilla subversion repository 的搬遷通知。今天早上全部的 subversion repository 已經搬遷完成。

我們新的 primary repository 位於 http://openvanilla.googlecode.com/svn/。新的計劃頁面在 Google Code Project Hosting上。

先前在 OpenFoundry 上的 repository 將改為 read only mirror。原先的計劃頁面也有進行整理的必要。

Google Code 的 subversion 為 1.4 版。配合最近版本的 svk (2.0.1),已經可以將全部的 revision history 同步到自己的 depot 中,先前在某幾個版本會斷掉的問題應不會再出現。

Ruby Tuesday的投影片和錄音: Build Your Own Gem

謝謝大家前來本次 Ruby Tuesday,投影片錄音已經可以下載了。不過有一個地方講錯了一定要修正,那就是 gem install 時是可以順便做 test 的,只是預設為關閉。

Ruby Tuesday: 5/15 星期二 20:00 在 OP

又到了每雙週一次的 Ruby Tuesday。這一次的 Ruby Tuesday 我打算介紹 gem 的包裝方式,主要是利用Dr. Nic寫的newgem generator來大幅簡化gem的包裝工作。我會介紹ObjectiveFlickr的包裝過程,並計劃在當天實際打包另一個可做為gem的module,來發布到RubyForge上。

先前有朋友問到,在新竹舉辦,實在太遠的問題。嗯,我以一個長到這麼大都一直住台北的人的立場,新竹的確是稍遠了些。不過地理學上有所謂的「空間輻合」(space convergence,應該是這麼講沒錯吧,我的地理學已經生鏽了),其中一個意思是說,因為兩城市間有便利且頻繁的交通,使得空間距離上比較遠的兩地,反而實際上所費的總交通時間,比介於其中的鄉鎮要少。台北到新竹,不管是坐火車,或從台北車站附近搭客運,都可以很快到新竹車站一帶,而從新竹車站步行約 15-20 分鐘就可以到 OP 了。以先前的舉辦經驗,只要在 22:00-22:30 左右告一段落,搭接近末班車回台北後,要搭到近末班的捷運也是沒問題的。

地點一樣是在新竹的OPCafé。到時見!

Cocoa Tuesday: 星期二5/8 20:00在OP

又到了每雙週二的Cocoa Tuesday。今次的Cocoa Tuesday,我計劃簡單介紹關於Objective-C、一點 Cocoa 的歷史,以及 Foundation classes (NSObject, NSArray, NSDictionary 等諸 NS* 開頭的 class) 的簡單用法。

地點一樣是在新竹市的無線網路免錢的有很多漫畫和小白兔唱片最重要還有咖啡好喝及隱藏菜單的OPCafé

五年一度的documenta、德國Kassel開催

因為讀到一篇關於實踐大學講師曾御欽的報導,才驚覺今年正好又是五年一度documenta開催年。1997年夏天我在布萊梅混了一個月,結果竟然沒抽空去。那一年幾乎每一班德國高速列車ICE車身都漆上了documenta X(當年是第十屆)字樣,其做為歐洲藝術盛事可見一斑。

雖然歐元貴得離譜,不過今年還有另一項和技術有關的盛會也在德國辦。不知道去得成去不成,先在這裡記一筆,當成是目標吧。

The Uselessness of RSS Reader

好一陣子沒打開我的 RSS Reader 了。某夜從一個著名 blogger (hint: 數字 0 結尾,寫成正規表示法是 \d\d\d ) 的一篇文章開始讀起,然後瘋狂地一篇篇看下去,連同一旁的評論者,看到認識的也去點一下。

就這樣,弄了一圈之後,突然驚覺:這跟我平常在看的 RSS 路徑幾乎一樣嘛。

80/20 法則:80% 的 blog read 來自 20% 的 feed。也就是說事實上 RSS Reader 所訂閱的 80% feed 中有很多最後都只有 “mark all as read” 的下場。

結論:該知道的事情最終還是會知道的。重點在於選擇一個夠熱門的 blogger 做起點,然後就可以把我自己有興趣的 bloggosphere 上的主要 node 給 traverse 一遍。

(這樣我 NetNewsWire 等於白買了啊 +_+)

- Next »