- 論壇徽章:
- 0
|
原帖由 DennisRitchie 于 2007-8-23 01:04 發(fā)表 ![]()
有人能認真看并提出討論真的是太開心了。
首先我沒有完全理解你所講的Symbol類,不知道Zend Engine的做法這么做是否和c++ stl中string的copy on write有類似的地方?
其次,在ruby語言中,變量有些情況下要加上:@等前綴(就像perl變量的$@%前綴),這么做雖然提高了效率,但是對于學(xué)習(xí)者來說卻增加了負擔(dān),相對而言,python、php就比較"consistency"。
關(guān)于 Symbol 類的理解有幾種辦法:
按照『Everyday Scripting with Ruby』的說法其實一個 Symbol 就是一個什么方法都沒有的 String。而這個實例的變量名稱就是它的值。也就是 :book => 'book',:work => 'work'。
按照某個 Blog (忘掉了) 的精彩講解,其實 Symbol 就是重復(fù)使用同一個 String 的辦法。他給出了一個例子。例如有一個類似數(shù)據(jù)庫的 Array Hash。
- db = [ {'no' => 0, 'lang' => 'C'},
- {'no' => 1, 'lang' => 'PHP'},
- {'no' => 2, 'lang' => 'Ruby'}
- # and so on...
- ]
復(fù)制代碼
上面這樣的用法,每次都會分配新的空間給 'no' 和 'lang',不但浪費了空間效率也會很低。當字符串用于表示一個變量的名字或者 key 的名字的時候,我們實際上完全不關(guān)心它們是不是屬于同一個 copy,或者有什么方法等等。這個使用,用 Symbol 就解決這個問題了:
- db = [ {:no => 0, :lang => 'C'},
- {:no => 1, :lang => 'PHP'},
- {:no => 2, :lang => 'Ruby'}
- # and so on...
- ]
復(fù)制代碼
這樣的話,:no 和 :lang 雖然是字符串,但是并不會分配新的空間。
Zend Engine 的做法其實某種意義上就是 copy on write。
關(guān)于 sigil……自從 Perl 有了 sigil 這種東西,很多語言都開始模仿了。但是和 Perl/PHP 不同,Ruby 的 sigil 用于指示變量的作用域,而不是內(nèi)容。而作用域這個東西是很抽象的,很難用其它的東西來描述,估計也是這個原因,所以 Ruby 并不支持 public attribute,所有成員變量不管是類的還是實例的,全部都只能內(nèi)部訪問,想外部訪問必須經(jīng)由 accessor。因為 Ruby 中的方法(也就是訊息傳遞)是不需要括號的(這點其實我也不太喜歡),所以如果允許外部訪問成員變量,那么必然成員變量和方法是在同一個命名空間,當然這樣就更一致了,但是命名空間就變小了,也將導(dǎo)致更復(fù)雜的概念問題(例如:block/variable/method/object 的區(qū)別云云)。
所以綜上所述,Ruby 的設(shè)計理念不允許用 obj.attr 來訪問 obj 的 attr 成員變量,所以的所以,在定義成員變量的時候,必須用某種方法來識別其作用域,最后,就采用 sigil 了。
上面雖然推論一堆,但是也是推論。但這里也有一個不一致的地方。那就是類方法用 ClassName.methodName 來定義,但是類變量卻是 @@attr 來定義,當然這個不一致性也可以用上面的推論來說明。
我沒有用過ruby,正在學(xué)習(xí)perl和python,按照我的猜測,應(yīng)該是必須的。在Python中:
變量不用申明
簡單變量可以直接使用
復(fù)合變量(數(shù)組、鏈表、字典、用戶自定義的類)必須先顯示的創(chuàng)建,才可以使用他們
事實證明你的猜測是正確的。但是 Ruby 也提供了快捷方式 [] 和 {},還是算比較方便的。
我覺的把這行代碼顛倒過來更容易理解,因為data[6]是被操作的對象:
- columns[:host] = data[6].match(/^http:\/\/([^\/]+)/)[1]
復(fù)制代碼
非常感謝指出這個問題。一開始想到 RegExp,就直接奔那兒去了,確實這樣比我哪個方法清晰多了。
另外感謝指教關(guān)于 =~ 的用法。因為 Unix 還不是太熟(vi 只看個兩個命令,emacs 還在學(xué)),所以還不太習(xí)慣用這個東西,不過慢慢地應(yīng)該就好了吧。
同感,我希望能有一種腳本語言能夠盡量接近C/C++的語法。
其實按 PHP4 來說,應(yīng)該是達到和 C/C++ 最接近的位置了。而 PHP5 更像 Java,連 interface 什么的都一律照搬了。不過其實最重要的是,Ruby/Python 這類語言雖然劍走偏鋒,但是卻給人一種很新穎的感覺:C-like 語法也是會有審美疲勞的,即使它是經(jīng)典。所以,用 Ruby 也好,Python 也好,都很有意思。就如 Courier New 這種經(jīng)典到不能再經(jīng)典的字體偶爾也會用膩,我偶爾也會用自己做的等寬字體換換口味,呵,當然最后還是會換回來,因為它太經(jīng)典了無法超越。
首先感謝你舉的幾個例子,現(xiàn)在我基本掌握了ruby的block語法。我有一個問題想請教你:能否把block看作是一個匿名的回調(diào)函數(shù)?
Ruby 中 block 和 callback/closure/first-class function 還是有一點點距離的……當然這個距離可以馬上達到。Block 在 Ruby 中是和環(huán)境綁定的,所以你不能直接用 a = do ... end 這種辦法。因為 block 是一個邏輯概念而不是語言實體。這里面沒有 Block 對象的參加。實際上 Ruby 也沒有所謂 Block 對象,而有 Proc 對象。這個可不是 Process (那是另外一個對象),而是 Proc(edure),也就是 Ruby 真正的「語言實體代碼塊」的實現(xiàn)。不管是包裝 closure 還是用 callback/fcf,都可以:
- a = Proc.new { puts "Hello, World!" }
- a.call # prints Hello, World!
復(fù)制代碼
當然這個東西還有一個快捷方式,你用 Python 一定不會陌生:
- a = lambda { puts "Hello, World!" }
- a.call # prints Hello, World!
復(fù)制代碼
很驚喜吧。Ruby 更會讓你驚喜的是,這個不但和 Python 很像,而且不限于單個 expression,可以是完整的函數(shù),也可以返回值云云。當然參數(shù)還是用和 Smalltalk 類似的 |arg| 來獲取。
上面兩種還有一個不同是,在 lambda 中 return 將會 return 給使用這個函數(shù)的主兒,而 Proc.new 中的 return 則會 return 給所在的函數(shù)。如下所示:
- def foo
- a = lambda { return "Spams and Eggs" }
- b = a.call
- end
- puts foo # Spams and Eggs
復(fù)制代碼
↑ a 返回給了 b。
- def foo
- a = lambda { return "Spams and Eggs" }
- a.call
- "Good good study"
- end
- puts foo # Good good study
復(fù)制代碼
↑ a 返回給了「空」
- def foo
- a = Proc.new { return "Spams and Eggs" }
- b = "Good good study" # never executed
- end
- puts foo # Spams and Eggs
復(fù)制代碼
↑ a 返回給了 foo
OVER,歡迎繼續(xù)討論~:mrgreen: |
|