<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="http://blog.ithome.com.tw/styles/rss.css" type="text/css"?>
<rss version="2.0" 
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:georss="http://www.georss.org/georss"
>
<channel>
<title>Fillano&#039;s Learning Notes</title>
<link>http://fillano.blog.ithome.com.tw</link>
<description>&lt;p&gt;就是個人的一些學習心得啦，不入大雅之堂。&lt;/p&gt;
</description>
<pubDate>Sat, 20 Mar 2010 21:45:39 +0800</pubDate>
<generator>http://www.lifetype.net</generator>
<item>
<title>用php做圖片臉部偵測</title>
<description>
&lt;p&gt;原文：&lt;a href=&quot;http://ithelp.ithome.com.tw/question/10036727&quot; target=&quot;_blank&quot;&gt;用php做圖片臉部偵測&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;這是自己在ithelp網站上分享的文章，想一想如果需要在圖片上針對臉部特徵做一些處理的話，可以做參考，所以在這裡提一下，不另外寫文章了。&lt;/p&gt;
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/65007</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/65007</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/65007</guid>
<dc:creator>fillano</dc:creator>
<category>PHP學習日誌</category>
<pubDate>Fri, 22 Jan 2010 23:26:56 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>練習開發 php extension - Tokyo Cabinet</title>
<description>
&lt;p&gt;之前想要熟悉一下PHP Extension的開發，剛好看到&lt;a href=&quot;http://opensource.plurk.com/LightCloud/&quot; target=&quot;_blank&quot;&gt;LightCloud&lt;/a&gt;，他是基於另外一個專案&lt;a href=&quot;http://1978th.net/tokyotyrant/&quot; target=&quot;_blank&quot;&gt;Tokyo Tyrant&lt;/a&gt;，Tokyo Tyrant的底層則是一個高速Key-Value pair資料庫，叫做&lt;a href=&quot;http://1978th.net/tokyocabinet/&quot; target=&quot;_blank&quot;&gt;Tokyo Cabinet&lt;/a&gt;。TokyoTyrant已經有不少專案支援，包括純php以及extension，但是Tokyo Cabinet似乎還沒有，所以就拿他來開刀。
&lt;/p&gt;&lt;p&gt;結果在這裡：&lt;a href=&quot;http://www.fillano.idv.tw/tokyocabinet3-0.1.src.tar.gz&quot; target=&quot;_blank&quot;&gt;http://www.fillano.idv.tw/tokyocabinet3-0.1.src.tar.gz&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;其實我之前是根據TokyoCabinet 1.4.X的TCADB這個介面來開發，不過最近都在使用Ubuntu，他安裝的套件是1.3.X版本的，之前許多功能不能使用...所以就先把他改成與1.3.X相容，也稍微調整一下程式碼再釋出。
&lt;/p&gt;&lt;p&gt;這個Extension主要是提供幾個東西：TokyoCabinet的Hash及B+ Tree格式的資料庫檔案及Hash的記憶體資料庫的支援，可以開啟（如果apache有讀寫權限，那檔案不存在時會產生檔案）、寫入、查詢、讀出等功能。另外雖然可以支援記憶體資料庫，但是用php extension的方式使用不太有意義，我當初寫這個extension除了練習之外，還順便拿來做檔案資料庫來測試使用。
&lt;/p&gt;&lt;p&gt;要安裝，必須先安裝php的developer功能，解開檔案後，在目錄中執行phpize，然後./configure -&amp;gt; make -&amp;gt; make install等。mytest目錄中有兩個php檔案可以用來做測試。當然，在安裝前要先裝好tokyocabinet。
&lt;/p&gt;&lt;p&gt;Tokyo Cabinet的key與value都是binary safe的，而且不限長度，所以拿來存放大檔案來做streaming也許是個不錯的用法。
&lt;/p&gt;&lt;p&gt;因為是習作，所以歡迎指教囉，有些地方其實不太確定就硬上了，心有點虛......
&lt;hr width=&quot;100%&quot; size=&quot;1&quot;/&gt;
2010-1-22 17:22 補充
&lt;/p&gt;&lt;p&gt;除了透過memcached的協定來存取TokyoTyrant，PECL上面已經有extension支援TokyoTyrant，作者還在持續更新中：&lt;br /&gt;
&lt;quote&gt;&lt;a href=&quot;http://pecl.php.net/package/tokyo_tyrant&quot; target=&quot;_blank&quot;&gt;http://pecl.php.net/package/tokyo_tyrant&lt;/a&gt;&lt;/quote&gt;&lt;br /&gt;
開發的主站在github：&lt;br /&gt;
&lt;quote&gt;&lt;a href=&quot;http://github.com/mkoppanen/php-tokyo_tyrant&quot; target=&quot;_blank&quot;&gt;http://github.com/mkoppanen/php-tokyo_tyrant&lt;/a&gt;&lt;/quote&gt;&lt;br /&gt;
作者的blog有不少好物：&lt;br /&gt;
&lt;quote&gt;&lt;a href=&quot;http://valokuva.org/&quot; target=&quot;_blank&quot;&gt;http://valokuva.org/&lt;/a&gt;&lt;/quote&gt;&lt;/p&gt;
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/64937</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/64937</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/64937</guid>
<dc:creator>fillano</dc:creator>
<category>PHP學習日誌</category>
<pubDate>Fri, 22 Jan 2010 17:16:22 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>ECMA5的getter/setter語法</title>
<description>
&lt;p&gt;ECMA-262 Edition5在去年（2009）十二月通過成為新的javascript標準，最近看到一篇（其實就是node.js）blog文章&lt;a href=&quot;http://wiki.github.com/ry/node/ecma-5mozilla-features-implemented-in-v8&quot; target=&quot;_blank&quot;&gt; &quot;ECMA 5/Mozilla Features Implemented in V8&quot; &lt;/a&gt;提到Chrome瀏覽器目前對於新標準的支援，其中有getter及setter，所以就來嘗試一下囉。
&lt;/p&gt;
&lt;p&gt;有興趣的話可以參閱ECMA-262 Edition5的&lt;strong&gt;11.1.5 Object Initialiser&lt;/strong&gt;，以下用簡單的例子來看看怎麼使用：
&lt;pre class=&quot;brush: javascript;&quot;&gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
var obj = function(){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var b = &quot;hey&quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return {get a(){return b;}, set a(x){b=x;}};
}();
alert(obj.a);
obj.a = &quot;ney&quot;;
alert(obj.a);
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
（這個例子簡單模仿javabean，但是因為scope的關係在setter裡面不可能有一個變數可以在getter取用，所以這裡用closure來把值用變數b保存）
&lt;p&gt;簡單地說，在ECMA3的object initialiser語法之外，可以用類似函數的方式來宣告物件屬性。用 get 屬性名稱(){函數本體} 就會在取用這個物件的屬性時呼叫函數執行所返回的結果，用 set 屬性名稱(參數列表){函數本體} 就會在指派值給屬性時把值傳給函數本體來執行。
&lt;p&gt;不過在getter/setter內使用本身的屬性名稱會有邏輯上的問題，或者可以說，下面這樣的作法是無效的：
&lt;pre class=&quot;brush: javascript;&quot;&gt;
var obj = {get a(){return this.a}, set a(x){this.a=x;}};
&lt;/pre&gt;
（這樣理論上會造成一個無窮迴圈）
&lt;p&gt;但是可以存取其他屬性，例如：
&lt;pre class=&quot;brush: javascript;&quot;&gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
var obj = function(){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var b = &quot;hey&quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return {get a(){return b;}, set a(x){b=x;}, get b(){return this.a;}, set b(x){this.a=x;}};
}();
alert(obj.a);
obj.a = &quot;ney&quot;;
alert(obj.a);
obj.b = &quot;nei nei&quot;;
alert(obj.a);
alert(obj.b);
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;至於getter/setter能怎樣使用，則看大家的想像力了。
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/64559</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/64559</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/64559</guid>
<dc:creator>fillano</dc:creator>
<category>Javascript學習日誌</category>
<pubDate>Sat, 16 Jan 2010 22:21:20 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>替Chromeos加上nvidia驅動程式</title>
<description>
&lt;p&gt;之前試用Chromeos時，在我的機器上跑起來非常慢，而且一段時間就會當掉。在噗浪上看到Jserv大大的噗說，Chromeos的window manager使用到Clutter這個函數庫，於是去&lt;a href=&quot;http://www.clutter-project.org/&quot; target=&quot;_blank&quot;&gt;http://www.clutter-project.org/&lt;/a&gt;網站看了一下，發現這個函數庫底層除了xlib，最主要的就是包裝OpenGL做出來的GUI API...所以強烈懷疑是因為驅動程式沒有支援硬體3D加速所以才讓Chromeos跑得那麼慢。（我的Asus U6S搭的是nvidia的8400M G）&lt;/p&gt;
&lt;p&gt;所以就來自己手動把nvidia的驅動程式加到chromeos吧。&lt;/p&gt;
&lt;p&gt;我使用的平台是Ubuntu 9.04。以下提到的方法會需要一些先備知識，包括：怎樣自己建構編譯出可執行的Chromeos、一些核心編譯的知識、一些軟體編譯的知識、把disk image掛載到檔案系統、chroot及下面提到的一些其他命令。（我不會詳細把命令列出來，所以最好熟悉這些命令）&lt;/p&gt;
&lt;h3&gt;作法&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;到nvidia網站下載最新的linux驅動程式，是一個以.run結束的可執行檔，我使用的應該是190.42這個版本&lt;/li&gt;
&lt;li&gt;用-x參數來執行，他會把所有檔案解出到一個與檔名相同的目錄(不含.run)。然後把usr/src/nv（應該沒記錯）目錄拷貝到chromeos開發的chroot環境中（應該是在chromiumos/src/chroot）&lt;/li&gt;
&lt;li&gt;在chromeos開發的chroot環境中，在執行完build_platform_package.sh, build_kernel.sh, build_image.sh後，進入到上述目錄，使用make module SYSSRC=/path/to/the/kernel/source（這個目錄會在~/trunk/src/build/kernel/{kernel_name}/{kernel_version}（希望沒記錯，有錯等一下再改））命令來建構nvidia的kernel module。完畢後會在nv目錄裡面產生nvidia.ko。（之前想要用dkms來做，但是發現有點麻煩，所以放棄了。如果真的要使用dkms的話，需要修改Makefile.kbuild來配合環境）&lt;/li&gt;
&lt;li&gt;接下來需要手動安裝這個kernel module，把剛剛用build_image.sh建構好的disk image（檔名叫做rootfs.image，會放在~/trunk/src/build/image/{build_version}目錄底下）掛載到檔案系統中，使用install命令把nvidia.ko安裝到disk image掛載目錄底下的/lib/modules/{kernel_name}/kernel/drivers/video目錄中。然後執行depmod命令來更新dependency檔。（要用哪些參數請自行man一下，需要用到正確的System.map、指定正確的version及檔名）&lt;/li&gt;
&lt;li&gt;接下來需要離開X，用sudo init 1然後選擇使用root帳號&lt;/li&gt;
&lt;li&gt;把剛剛的rootfs.image掛到檔案系統，然後可以先執行步驟1提到的執行檔，加上-A來看看有哪些進階參數可以用，需要指定所有安裝細節的目錄選項，並且選擇不執行kernel module的安裝選項，（用到的大概有十幾個選項，而且要加上許多完整目錄名稱以指到rootfs.image中的相關目錄，所以落落長，最好做成script來跑，這樣也方便調整參數）來進行X Window驅動程式、extension以及一些軟體、動態程式庫的安裝。安裝完畢後，chroot到rootfs.image掛載的目錄，執行ldconfig -v來確保上面的東西有正確安裝。&lt;/li&gt;
&lt;li&gt;修改rootfs.image掛載目錄中的etc/X11/xorg.conf，適當調整參數，需要把driver指定為&#039;nvidia&#039;，並且載入glx模組。&lt;/li&gt;
&lt;li&gt;修改rootfs.image掛載目錄中的boot/extlinux.conf，拿掉i915.modeset=1核心參數&lt;/li&gt;
&lt;li&gt;使用image_to_usb.sh把chromeos安裝到usb隨身碟（至少需要4G），然後用他開機&lt;/li&gt;
&lt;li&gt;Chromeos跑起來就非常快&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;過程這麼複雜，主要是因為nvidia驅動程式安裝方式無法與chromeos建構的過程搭配，所以需要把安裝過程拆成kernel module及X兩部份。另外一個我自己不太熟的是xorg.conf，所以花了一點時間嘗試錯誤，其實nvidia的驅動程式裡面有非常詳細的readme可以參考。
&lt;h3&gt;測試結果&lt;/h3&gt;
&lt;p&gt;沒有使用nvidia的官方驅動程式時，在xterm使用top，會看到chromeos_wm使用cpu大約在14%，安裝好以後...嘿嘿，平均是0%，速度超快，而且不會當掉了。&lt;/p&gt;
&lt;p&gt;（昨天更新source時，看到ibus-chewing目錄喔，不過好像還沒放進platform package的建構中，應該不久就會有新酷音輸入法可以用了）&lt;/p&gt;
&lt;hr width=&quot;100%&quot; size=&quot;1&quot;&gt;
2009-11-30 21:43 by Fillano
&lt;p&gt;我把檔案上傳到一個分享伺服器，可以下載來跑跑看。（請使用chromiumos的image_to_usb.sh來把他放入USB隨身碟。另外，這個影像檔只支援nvidia的顯示卡，別的顯示卡跑起來會出問題。）&lt;/p&gt;&lt;br /&gt;
&lt;a href=&quot;http://www.keepandshare.com/doc/view.php?u=1580589&quot; target=&quot;_blank&quot;&gt;http://www.keepandshare.com/doc/view.php?u=1580589&lt;/a&gt;
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/60185</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/60185</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/60185</guid>
<dc:creator>fillano</dc:creator>
<category>Linux學習日誌</category>
<pubDate>Sat, 28 Nov 2009 22:59:44 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>在Javascript中使用Reflection與Proxy Pattern實作AOP</title>
<description>
&lt;p&gt;Spring Framework有兩個主要的功能，就是IoC容器與AOP。有接觸過AOP的人，就會知道AOP有許多好處，主要是有許多程式的需求其實跟程式的邏輯沒有直接關係，但是又需要在適時插入到邏輯中，最常見的就是在程式中插入紀錄log的功能。像這類的需求可以把它稱作Aspect或是cross-cutting concern，AOP(Aspect Oriented Programming)主要的目的，就是集中處理這一類的需求，讓這一類的需求與邏輯可以拆開，但是又可以在適當的時機介入到程式邏輯中。&lt;/p&gt;
&lt;p&gt;AOP可以通過Proxy Pattern來實作，也就是說，透過一個Proxy來執行程式，因為是透過Proxy，所以有機會在做執行動作的前後做介入。Proxy有兩種，一種是靜態Proxy，它必須為每個要透過Proxy執行的類別設計一個相同介面的Proxy類別，然後透過這個Proxy來執行這個類別，這樣在實作上非常麻煩。自從Java有了Reflection能力後，可以用他來偵測類別的介面然後動態地產生Proxy來執行類別，這樣可以節省很大的功夫。&lt;/p&gt;
&lt;p&gt;Javascript具備有基本的Reflection功能，所以也有可能用這個功能來實現動態Proxy，然後用來實作AOP。&lt;/p&gt;
&lt;h3&gt;結構&lt;/h3&gt;
&lt;p&gt;Javascript可以利用for...in語法，來列舉出一個物件所擁有的properties。像這樣：&lt;/p&gt;
&lt;pre class=&quot;brush: javascript;&quot;&gt;
function a() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.p1 = &quot;p1&quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.showP1 = function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(this.p1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
}
var b = new a();
var str = &#039;&#039;;
for (var i in b) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;str += &#039;[&#039; + i + &quot;]\n&quot;;
}
alert(str);
&lt;/pre&gt;
&lt;p&gt;同時，Javascript可以用[]來存取物件的Properties。像這樣：&lt;/p&gt;
&lt;pre class=&quot;brush: javascript;&quot;&gt;
function a() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.p1 = &quot;p1&quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.showP1 = function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(this.p1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
}
var b = new a();
alert(b[&#039;p1&#039;]);
b[&#039;showP1&#039;]();
&lt;/pre&gt;
&lt;p&gt;透過這兩種語法，Javascript就可以有Reflection的能力。不過這有個限制，一些內建的物件，他的屬性可能會是[[DontEnum]]，也就是不可列舉的，而自訂的物件在下一版的ECMA-262中，也可以這樣設定他的屬性。如此一來可能會讓一些Properties不會被列舉出來。所以要能完整支援Reflection的物件，就不能額外設定這個property的屬性。&lt;/p&gt;
&lt;p&gt;底下就實作一個動態Proxy物件，並讓它可以透過constructor來傳入被代理的物件，並設定要在被代理物件的函數執行前、執行後、以及包裹在所執行函數外的函數。除了使用Reflection，為了方便把函數包裹起來，我從google的base.js裡面偷來了一個函數叫做bind，它可以在函數執行前先把參數指派給它，這樣到了要實際執行時，我只要用函數的參考後面加上()就可以正確執行。下一版的ECMA-262，也會把這個函數加入到Function.prototype中，所以Javascript的函數都可以先把他的參數用這個方法先bind上去。&lt;/p&gt;
&lt;pre class=&quot;brush: javascript;&quot;&gt;
(function(){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var bind = function(fn, selfObj, var_args) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var boundArgs = fn.boundArgs_;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (arguments.length &amp;gt; 2) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var args = Array.prototype.slice.call(arguments, 2);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (boundArgs) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;args.unshift.apply(args, boundArgs);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boundArgs = args;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;selfObj = fn.boundSelf_ || selfObj;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;fn = fn.boundFn_ || fn;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var newfn;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var context = selfObj || goog.global;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (boundArgs) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newfn = function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var args = Array.prototype.slice.call(arguments);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;args.unshift.apply(args, boundArgs);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return fn.apply(context, args);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newfn = function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return fn.apply(context, arguments);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newfn.boundArgs_ = boundArgs;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newfn.boundSelf_ = selfObj;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;newfn.boundFn_ = fn;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return newfn;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AOP = function(o, c) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var methods = [];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var before = function(){};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var after = function(){};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var arround = function(f){f();};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (c.before &amp;amp;&amp;amp; typeof c.before === &#039;function&#039;) before = c.before;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (c.after &amp;amp;&amp;amp; typeof c.after === &#039;function&#039;) after = c.after;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (c.arround &amp;amp;&amp;amp; typeof c.arround === &#039;function&#039;) arround = c.arround;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (typeof o == &#039;function&#039;) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var o = new o();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (var i in o) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (typeof o[i] == &#039;function&#039;) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;methods.push(i);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (; i&amp;lt;methods.length; i++) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this[methods[i]] = function(methodName) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;before(methodName);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;arround( bind( o[methodName], o, Array.prototype.slice.call(arguments) ) , methodName);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;after(methodName);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}(methods[i]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
})();
&lt;/pre&gt;
&lt;p&gt;接下來可以實驗一下：&lt;/p&gt;
&lt;pre class=&quot;brush: javascript;&quot;&gt;
function a() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.show=function(msg) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(&#039;a.show: &#039; + msg);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
}
var b = new a();
b.show(&#039;hey&#039;);
&lt;/pre&gt;
&lt;p&gt;執行這個範例中的b.show(&#039;hey&#039;)，就會顯示&#039;a.show： hey&#039;。接下來我們用上面實作的AOP類別來包裹b，產生物件變數c，並且加入在他的函數執行前後，及包裹了函數並在執行前後顯示訊息的程式：&lt;/p&gt;
&lt;pre class=&quot;brush: javascript;&quot;&gt;
var c = new AOP(b, {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;before: function(m){alert(&#039;before method: &#039;+m);},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;after: function(m){alert(&#039;after method: &#039;+m);},
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;arround: function(f, m){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(&#039;before within arround method: &#039;+m);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;alert(&#039;after within arround method: &#039;+m);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
});
c.show(&#039;hey&#039;);
&lt;/pre&gt;
&lt;p&gt;這樣就會依序顯示訊息：&#039;before method: show&#039;、&#039;before within arround method: show&#039;、&#039;a.show: hey&#039;、&#039;after within arround method: show&#039;、&#039;after method: show&#039;。&lt;/p&gt;
&lt;p&gt;上例可以透過&lt;a href=&quot;http://jsbin.com/icuxi&quot;&gt;http://jsbin.com/icuxi&lt;/a&gt;來試用。&lt;/p&gt;
&lt;h3&gt;應用&lt;/h3&gt;
&lt;p&gt;範例裡面只是一個非常粗糙的實作，功能也有限。要看別人怎麼做、怎麼用，會更有價值。&lt;/p&gt;
&lt;p&gt;我上網找了一下，YUI3這個Javascript框架裡面，有在Custom Event架構中實作AOP，也許可以拿來參考。另外，如果我自己要拿來用的話，也許可以在做單元測試的時候，用它來產生mock object，只是還沒仔細研究是否可行。&lt;/p&gt;
&lt;p&gt;（這一篇原本是發表在ithelp第二屆鐵人賽的文章，我覺得比較有放到blog的價值，所以也把他貼過來。）&lt;/p&gt;
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/59403</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/59403</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/59403</guid>
<dc:creator>fillano</dc:creator>
<category>Javascript學習日誌</category>
<pubDate>Wed, 18 Nov 2009 14:04:13 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>今晚的傅聰音樂會</title>
<description>
&lt;p&gt;海頓我真的不熟，很難比較批評，但是傅聰真的是以音樂為宗教的一個人。
&lt;/p&gt;&lt;p&gt;今天的傅聰看起來其實精神不是很好，年紀不小了吧...但是他彈起琴來真是極度專注與享受，坐下來彷彿就變了一個人似的，每個音都非常注意地把它彈出來，難怪他不願意在記者會上彈琴秀兩手，因為他尊重音樂，不希望這樣輕易對待。
&lt;/p&gt;&lt;p&gt;整體來說，今天的海頓充滿了活潑的線條與變化，很有樂趣。海頓的音樂在形式上非常好，我太太喜歡形容他好像是工程師在寫規格書，形式、趣味、優美都恰到好處。我個人其實不那麼喜歡這樣的形式，但是不能不佩服他可以做到這種程度。他是形式的建立者，但是又在一些地方幽默地把這些打破，留下一點意外的驚喜，傅聰把這些幽默感表現地恰到好處。而音樂線條的流暢，其實有時讓人感覺不到這是古典樂派的東西。
&lt;/p&gt;&lt;p&gt;對於今晚各個曲目的印象，個人覺得最迷人的是第二首（Sonate in B minor, HOB XVI:32）（疑？這不是貝多芬嗎？）、第三首（Sonate in E flat major HOB XVI:49）（疑？這不是莫札特嗎？）、第四首（Variations in F minor HOB XVII:6）（這首真的讓人感受到對朋友的思念跟哀傷）。
&lt;/p&gt;&lt;p&gt;時代、人生與天才造就了獨一無二的傅聰，聽完音樂會回家再把他的CD拿出來聽，感覺更能理解這個人跟他對音樂的想法了。（我太太對他的形容是，他就像一位大廚師用他的人生熬了一鍋的湯頭，把各個作曲家丟到湯裡，都會煮出美味的菜）&lt;/p&gt;
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/39905</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/39905</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/39905</guid>
<dc:creator>fillano</dc:creator>
<category>音樂印象</category>
<pubDate>Fri, 09 Oct 2009 23:15:26 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>Safari的Web Worker速度非常搶眼</title>
<description>
&lt;p&gt;為了測試自己寫的PHP &lt;a href=&quot;http://1978th.net/tokyocabinet/&quot; target=&quot;_blank&quot;&gt;Tokyo Cabinet&lt;/a&gt; Extension是否在多人運作下不會有問題，興起了利用Web Worker來做測試的念頭。
&lt;/p&gt;&lt;p&gt;（按：我自己寫的extension只是包裝他的tcadb函式庫，這樣就可以做local access他的資料庫檔案或是記憶體資料庫。其實透過&lt;a href=&quot;http://1978th.net/tokyotyrant/&quot; target=&quot;_blank&quot;&gt;Tokyo Tyrant&lt;/a&gt;才是最好方法，Plurk的LightCloud也是基於Tokyo Tyrant的。Tokyo Tyrant已經有初期的&lt;a href=&quot;http://pecl.php.net/package/tokyo_tyrant&quot; target=&quot;_blank&quot;&gt;PECL Connector&lt;/a&gt;可以支援，同時也有&lt;a href=&quot;http://openpear.org/package/Net_TokyoTyrant&quot; target=&quot;_blank&quot;&gt;純PHP實現的Connector&lt;/a&gt;。）
&lt;/p&gt;
&lt;p&gt;簡單的測試程式如下：
&lt;pre class=&quot;brush: php;&quot;&gt;
&amp;lt;?php
header(&quot;Pragma: no-cache&quot;);
/*$tt = new TokyoTyrant();
$tt-&amp;gt;connect( &#039;localhost&#039;, 1978 );
$c=$tt-&amp;gt;add(&#039;count525&#039;,0);
$c1 = $tt-&amp;gt;add(&#039;count525&#039;, 1);
echo &#039;{result: &quot;&#039;.$c1.&#039;:&#039;.($c1-$c).&#039;&quot;}&#039;;*/
$tcadb = tcadbnew();
tcadbopen($tcadb, &#039;test.tch&#039;);
$c = tcadbaddint($tcadb, &#039;count525&#039;, 0);
$c1 = tcadbaddint($tcadb, &#039;count525&#039;, 1);
tcadbclose($tcadb);
echo &#039;{result: &quot;&#039;.$c1.&#039;:&#039;.($c1-$c).&#039;&quot;}&#039;;
&lt;/pre&gt;
（註解掉的部份是用PECL的Tokyo Tyrant Connector做的程式）
&lt;p&gt;簡單地說，就是counter啦...每次access會加1，同時檢查在加1之前之後的數字是否只增加1，看看會不會有操作問題。
接下來是Web Workder，首先是html與內嵌的Javascript：
&lt;pre class=&quot;brush: js; html-script: true;&quot;&gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;div id=&quot;panel&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&amp;lt;script&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var w = [];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var i = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var limit = 975;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var count = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var start = new Date().getTime();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for (;i&amp;lt;25;i++) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w[i] = new Worker(&#039;test525.js&#039;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w[i].onmessage = function(e) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.getElementById(&#039;panel&#039;).innerHTML += e.data + &#039;&amp;lt;br&amp;gt;&#039;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (count&amp;lt;limit) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;this.postMessage(10);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;count++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var duration = new Date().getTime() - start;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;document.getElementById(&#039;panel&#039;).innerHTML += &quot;duration: &quot;+duration+&quot;&amp;lt;br&amp;gt;&quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w[i].onerror = function(e) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw(e.data);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w[i].postMessage(10);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;lt;/script&amp;gt;
&lt;/pre&gt;
&lt;p&gt;接下來是worker的程式：
&lt;pre class=&quot;brush: js;&quot;&gt;
onmessage = function(e) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var w = new XMLHttpRequest();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w.onreadystatechange = function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (w.readyState==4) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;clearTimeout(tid);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (w.status == 200) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;postMessage(w.responseText);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} else {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;postMessage(&#039;{result: \&#039;error: &#039;+w.status+&#039;\&#039;}&#039;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w.onerror
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w.open(&quot;GET&quot;, &quot;test525.php&quot;, true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w.send(null);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var tid = setTimeout(function() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;postMessage(&quot;{result: -1000}&quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}, 1000*30);
}
&lt;/pre&gt;
&lt;p&gt;這樣就可以讓25個worker做大約1000次access。如果網路環境單純，counter的增長看起來幾乎是依照順序的，偶而有例外，如果開不同的瀏覽器，可以看到counter的數字會變得不連續，但是基本上counter累加的計算沒有被干擾，不過我想恐怕需要做更複雜一點的測試才能知道這樣是否不會有race的問題（就是php extension的部份），不過tokyo cabinet有支援transaction操作，也許要一併測試......
&lt;p&gt;Firefox3.5、Chrome3與Safari4都已經支援worker，Opera10似乎還不支援。速度上，則是Safari4 &amp;gt; Chrome3 &amp;gt; Firefox3.5，而且Safari4跑web worker真的很快，我想Safari團隊在這一部份恐怕有特別下功夫，其他瀏覽器要加油了。
&lt;hr width=&quot;100%&quot; size=&quot;1&quot;&gt;
2009-10-7 13:55 補充：
&lt;p&gt;在公司測試，很訝異地發現，Safari4的速度飛快，Chrome3牛步化，跟Firefox的差距不大...我猜恐怕Chrome3在net access上有一些效能瓶頸。（差距很明顯，同樣的測試，Safari4只花34秒，Chrome3花了215秒，Firefox3.5花了222秒。測試方式一樣是用25個worker跑大約一千次access。）
&lt;hr width=&quot;100%&quot; size=&quot;1&quot;&gt;
2009-10-7 21:09:09
&lt;p&gt;另一個有趣的現象，在家裏用區網連伺服器，Chrome3用了13秒，Safari4用了17秒。換到用外網連到伺服器，Chrome3變成18秒，Safari4還是17秒。Safari4用了怎樣的技術嗎？真是有趣。
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/39564</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/39564</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/39564</guid>
<dc:creator>fillano</dc:creator>
<category>PHP學習日誌</category>
<category>Javascript學習日誌</category>
<pubDate>Wed, 07 Oct 2009 10:43:37 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>今晚的Vasary音樂會</title>
<description>
&lt;p&gt;這位七十六歲的老先生只能用一個字形容：「爽」。
&lt;/p&gt;&lt;p&gt;上半場的貝多芬「離別」奏鳴曲一開始就非常個人風格，說實話，已經有點辨認不出...絕對是不中規中矩、循序漸進、醞釀張力的，而是時而獨自低語，但是高興起來就如火一樣奔放的貝多芬。有許多地方旋律跟伴奏似乎刻意不分主從，這樣的感覺頗奇妙。（因為從來沒有聽過有人這首這樣彈得，我實在很想聽他對於貝多芬的想法阿）
&lt;/p&gt;&lt;p&gt;舒伯特的流浪者幻想曲我不是很熟，他彈安靜的地方非常安靜溫柔，但是速度一直有一個不穩定的緊張感，似乎隱隱要向前衝出去。
&lt;/p&gt;&lt;p&gt;下半場的氣氛是越來越奇妙。依序是德布西的鋼琴組曲、六首前奏曲及快樂島。沉沒的教堂有一個在靜謐中隱隱浮現鐘聲的感覺，棕髮少女非常高雅而落落大方，西風果然到處肆虐，煙火真的有火花四冒的感覺...
&lt;/p&gt;&lt;p&gt;彈快樂島之前，他對觀眾說，你們好安靜，真是太棒了...然後坐下來彈快樂島，真的頗快樂，煞車剎不住熱情奔放，結束時還順勢轉個身子起來致意。接下來才是重頭戲...
&lt;/p&gt;&lt;p&gt;觀眾鼓掌鼓了不久，也獻過花，他很高興的說你們真是太好了，我要彈十五分鐘的安可（應該不止十五分鐘），然後坐下來彈貝多芬的「月光」奏鳴曲（全曲），這首開始時好像突然踩了煞車，非常的高雅、深情款款，當然第三樂章還是熱情如火。接下來彈了蕭邦的升C小調夜曲BI49，這首也是感情全開，一路殺到底。（這首比較簡單，我不時會彈一下，他彈的真的像是開了眼界了）最後，還彈了李斯特的匈牙利狂想曲第十五號（拉高基進行曲）...全場奔騰。鼓掌了許久，他謝幕幾次，然後輕輕闔上琴蓋，大家就知道意思了，很有一種默契感，這樣演奏者跟觀眾水乳交融的感覺很好。
&lt;/p&gt;&lt;p&gt;這位老先生今天真是熱情如火又充滿個性阿，只是這樣的感覺恐怕在CD裡面不容易聽到。&lt;/p&gt;
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/39214</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/39214</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/39214</guid>
<dc:creator>fillano</dc:creator>
<category>音樂印象</category>
<pubDate>Wed, 30 Sep 2009 22:46:08 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>噗浪中毒症候群</title>
<description>
&lt;p&gt;之前在噗浪看到有人調查，自從用了噗浪後，減少了多少在部落格上發布的文章呢？自己想了一下，好像真的變少了...
&lt;/p&gt;&lt;p&gt;其實看一下我自己在Twitter上面有在追蹤的人，例如John Resig，他一天頂多也只推兩三次，我用噗浪好像....超過了不少。
&lt;/p&gt;&lt;p&gt;反省一下，今日不噗了...
&lt;/p&gt;&lt;p&gt;（你看你看，連字數都變少了...）&lt;/p&gt;
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/32294</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/32294</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/32294</guid>
<dc:creator>fillano</dc:creator>
<category>一般</category>
<pubDate>Wed, 19 Aug 2009 16:03:59 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
<item>
<title>Higher Order PHP - start from callback</title>
<description>
&lt;p&gt;PHP 5.3.0開始，有一個重要的特性正式加到PHP裡面，就是匿名函數。（請參考：&lt;a href=&quot;http://tw.php.net/manual/en/functions.anonymous.php&quot; target=&quot;_blank&quot;&gt;Anonymous functions&lt;/a&gt;。手冊還有提到，匿名函數目前是用
&lt;a href=&quot;http://tw.php.net/manual/en/reserved.classes.php#reserved.classes.closure&quot; target=&quot;_blank&quot;&gt;Closure&lt;/a&gt;內部類別實作，但是不要管他，因為實作方式有可能修改。）
&lt;/p&gt;&lt;p&gt;在提到匿名函數之前，先看看PHP的callback應用。callback是php非常好用的功能，可以利用他來用自訂的方式處理資料，例如array_map，就可以用一個callback函數一次處理陣列中所有元素，不用iteration，也不用loop。下面是用callback函數處理一個整數陣列，傳回每個元素的平方：
&lt;/p&gt;
&lt;pre class=&quot;brush: php;&quot;&gt;
function power($v) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return $v*$v;
}
print_r(array_map(&quot;power&quot;, range(1,10)));
&lt;/pre&gt;
&lt;p&gt;結果是：
&lt;pre class=&quot;brush: php;&quot;&gt;
Array
(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[0] =&amp;gt; 1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[1] =&amp;gt; 4
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[2] =&amp;gt; 9
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[3] =&amp;gt; 16
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[4] =&amp;gt; 25
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[5] =&amp;gt; 36
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[6] =&amp;gt; 49
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[7] =&amp;gt; 64
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[8] =&amp;gt; 81
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[9] =&amp;gt; 100
)
&lt;/pre&gt;
&lt;p&gt;在php 5.3定義匿名函數很簡單，底下是一個例子：
&lt;pre class=&quot;brush: php;&quot;&gt;
$func = function ($name) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo &quot;\&quot;anonymous function invoked with params: &quot;.$name;
};
$func(&quot;hello anonymous function\n\&quot;&quot;);
&lt;/pre&gt;
&lt;p&gt;像這樣可以把一個匿名函數指派給$func變數，然後透過$func變數就可以使用。執行結果如下：
&lt;pre class=&quot;brush: php;&quot;&gt;
&quot;anonymous function invoked with params: hello anonymous function&quot;
&lt;/pre&gt;
&lt;p&gt;一般的場合大概比較少這樣用就是了（看習慣）。PHP 5.3.0之前的版本，callback函數要用字串來指派，到了PHP 5.3.0則可以直接用匿名函數來指派。透過匿名函數定義中新增的use語法來運用外層scope的變數，就可以完整使用到Closure的便利性。以array_map為例，之前的callback只能針對個別元素做處理，如果你想做做出所有元素累加的功能，就會被迫使用global變數，這樣既不優雅，又缺乏重用性。利用Closure就可以用簡潔的語法做出這樣的功能：
&lt;pre class=&quot;brush: php;&quot;&gt;
function sumUp() {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$init = 0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return function ($v) use(&amp;amp;$init) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$init += $v;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return $init;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
}
print_r (array_map(sumUp(), range(1,5)));
print_r(array_map(sumUp(), range(1,10)));
&lt;/pre&gt;
&lt;p&gt;這樣執行的結果是：
&lt;pre class=&quot;brush: php;&quot;&gt;
Array
(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[0] =&amp;gt; 1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[1] =&amp;gt; 3
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[2] =&amp;gt; 6
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[3] =&amp;gt; 10
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[4] =&amp;gt; 15
)
Array
(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[0] =&amp;gt; 1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[1] =&amp;gt; 3
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[2] =&amp;gt; 6
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[3] =&amp;gt; 10
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[4] =&amp;gt; 15
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[5] =&amp;gt; 21
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[6] =&amp;gt; 28
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[7] =&amp;gt; 36
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[8] =&amp;gt; 45
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[9] =&amp;gt; 55
)
&lt;/pre&gt;
&lt;p&gt;雖然用起來還是有點囉唆（要用use來宣告要用到的外層變數），不過PHP的表現力又往前進了一大步。在上面的例子也展示了Higher Order Function的特性：函數可以當作變數傳遞，可以當作傳給函數的參數，也可以當作函數的返回值。
</description>
<link>http://fillano.blog.ithome.com.tw/post/257/29785</link>
<comments>http://fillano.blog.ithome.com.tw/post/257/29785</comments>
<guid>http://fillano.blog.ithome.com.tw/post/257/29785</guid>
<dc:creator>fillano</dc:creator>
<category>PHP學習日誌</category>
<pubDate>Wed, 22 Jul 2009 00:00:06 +0800</pubDate>
<source url="http://fillano.blog.ithome.com.tw/rss/rss20/257">Fillano&#039;s Learning Notes</source>
</item>
</channel>
</rss>