亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
樓主: send_linux
打印 上一主題 下一主題

《ruby元編程》有獎試讀中!(獲獎名單已公布) [復制鏈接]

論壇徽章:
0
21 [報告]
發(fā)表于 2012-02-27 17:30 |只看該作者
本帖最后由 琳琳的小狗 于 2012-02-27 17:41 編輯
OwnWaterloo 發(fā)表于 2012-02-24 11:36
整個章節(jié)可以吐槽的地方很多,這里只說一點:這功能又不是什么稀奇的事情,連許多被認為是靜態(tài)語言并使 ...


作者給出的這個例子,只是為了向讀者揭示Ruby的”open class“特性,因為在ruby社區(qū)里這種用法實在是太常見了,以至于被很多人濫用,要不怎么叫”Monkey patch“呢:)

時至今日,Rubyist們也逐漸了解到了super男說的那句話”能力越大責任也就越大“,在打猴子補丁的時候都知道要多長個心眼,所以在元編程這本書里面有一整章講述怎么預防各種陷阱(怎樣安全地元編程)。另外,在Ruby的下一個版本也就是2.0中,也傾聽了社區(qū)的訴求,加入了”選擇子“來最大限度的防止猴子補丁帶來的問題(也就是你所說的第二點使用using all):
module MonkeyPatch
  refine Integer do
    def +(v) #嘿嘿,ruby也有“重載”哦,所有的操作符只不過是普通的方法加上語法糖而已,正所謂一切皆對象……
      self - v
    end
  end
end

class MonkeyIsland
  using MokeyPath #聲明使用MokeyPath之后,在此詞法作用于中,猴子補丁都有效

  puts "1 + 1 = #{1 + 1}"  #輸出 1 + 1 = 0
end

puts "1 + 1 = #{1 + 1}"  #輸出 1 + 1 = 2,因為修補被限制而不會影響標準庫的行為

利用選擇子,可以不用再擔心污染現(xiàn)存對象的行為,而把猴子補丁限制在可控的范圍類。

至于全局變量,自古至今都不被認為是最佳實踐,這個沒有什么好爭論的。在Ruby社區(qū)中,如何最大限度的消除此依賴,一直都是重構(gòu)的話題之一。拿Erlang的話來說,連可變“狀態(tài)”都是罪無可恕的東西,更別說這玩意兒了(并行計算中的狀態(tài)同步,簡直是噩夢)。

另外針對“面向?qū)ο蟆毕嚓P(guān)敘述,個人決定不予任何置評,保留沉默的權(quán)利。

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
22 [報告]
發(fā)表于 2012-02-27 18:04 |只看該作者
回復 20# 琳琳的小狗

終于來了個能打的了……  激動死我了……

琳琳的小狗 發(fā)表于 2012-02-27 16:55
這一節(jié)作者只是站在Ruby的角度上來看元編程,因為ruby是解釋執(zhí)行的,其元編程實現(xiàn)手段都是通過運行時修改對象模型來實現(xiàn),因此他一開始就在這個上下文中,給出跟明確的定義(元編程是編寫在運行時操縱語言構(gòu)件的代碼)是應該的,這個結(jié)論在后續(xù)章節(jié)中有所呼應?偛恢劣谡f,在一本講Ruby技術(shù)內(nèi)幕的書中,去講C++或者其他語言的實現(xiàn)細節(jié)吧?

其實就我閱讀這本書的過程來看,并沒有感受到作者對其他語言,特別是靜態(tài)語言的貶伐之意。作為一名實在的程序員,對某種語言有特別的嗜好完全可以理解,這就好比你言語之中透露的對C++的喜好。對于Lisp,書中一上來就講了,Ruby是借鑒了Lisp以及Smalltalk的語法優(yōu)勢,屬于后來之輩,怎么好意思說前輩的壞話?只不過對于同一事物的處理方式不同而已了,抬高點說,僅僅是世界觀有所區(qū)別,正所謂“求同存異”嘛。

我是見過大量的書/文章/博客等等,總喜歡用貶低(也許是無意的)X的方式來抬高Y。
而且確實又存在大量的人學不會全面的分析,真將某種權(quán)衡當作了優(yōu)勢。

比如看到j(luò)avaer說C++不支持interface,不是純OO,不是……什么的,有閑情就去調(diào)戲兩把,沒逸致就笑笑了之……
我擔心的是書中這種說法,會不會又導致大量ruby程序員說C++不支持元編程。

C++不支持元編程這方面是我的錯,我最初是在is-programmer上的某個博客看到這書的,那文章只引用了書中的一部分。
書里有一個灰框里面有提到 http://book.douban.com/reading/15986307/  《代碼生成器與編譯器》。
不過這部分依然有一些問題,這是ruby(或者說這本書)對元編程的定義。
至少在試讀部分里介紹的那些技術(shù),只能算是dynamic programming(不是動態(tài)規(guī)劃,也不是動態(tài)類型dynamic typed),還沒達到code transformation的程度。
不同社區(qū)對相同事物有不同的term,同一term描述不同事物其實也很正常,所以我也不打算繼續(xù)說了……

關(guān)于lisp。用貶低C++的方式抬高java至少在兩者都是靜態(tài)類型方面還說得過去。
而用C++來對比ruby,說C++編譯后沒有類型信息…… 這不是明顯的么,否則還叫什么靜態(tài)類型語言?
所以,要比較元編程,應該與lisp比較。

最后,我以前對C++有喜好,現(xiàn)在沒什么特殊感覺了。



琳琳的小狗 發(fā)表于 2012-02-27 16:55
1、別說的Ruby多流行似的好嗎?

恩,Ruby在國內(nèi)是非常不受待見,這點從相關(guān)的書籍出版物慘淡的銷量上就能看出(希望這本元編程能帶來點漣漪)。但是,不流行就代表很差勁么?反之,流行就代表高雅、牛逼?恐怕不見得。37things就是那么一個名不經(jīng)傳的小公司,使用如此垃圾的ruby語言開發(fā)了rails這么個另類的敏捷開發(fā)框架,不也在小眾社會活的有滋有味么?如果Ruby真的這么垃圾,我想Uncle bob、Martin叔叔這些老家伙也不會親言流露對其贊賞有加;另外Ruby社區(qū)的活力,恐怕也是有目共睹的,慣例優(yōu)于配置、BDD實用化……無窮的創(chuàng)造力(可以參見rspec以及cucumber):
http://rspec.info/
http://cukes.info/

如原帖
>> 如果TIOBE具有參考性的話,Ruby也就10x左右徘徊而已,與Lisp是一個水平的好嗎?
不僅僅是國內(nèi)而已。

另外,流行與優(yōu)秀之間沒有直接關(guān)系我是贊同的。
這里僅僅是就事論事的說書里提到ruby的流行只是相對的。并沒有說因此ruby就不好,也沒有說因此ruby就好。



琳琳的小狗 發(fā)表于 2012-02-27 16:55
2. 說最友好不害臊嗎?

說對程序員“友好”,這個標準是需要實踐的,如果沒有對ruby語言的實際使用感受,妄談友好還是憎惡都不妥當,何不嘗試一下呢?鄙人作為一名專職Ruby程序員,使用Ruby以及Rails已經(jīng)有六年之久,深感這個社區(qū)的人文風格(如第一條的兩個工具,給團隊的開發(fā)人員實施BDD、ATDD帶來了無窮的愉悅),我只想說,自從將項目從Java遷移到Ruby平臺之后,加班少了,熬夜少了,一人頂三人,身體倍兒棒……

看吧,與java比了。java有什么好比的? 雖然我對C++無愛了,但我對java一直都是鄙視的。
而且與上面一條相同,說ruby好(暫且不論它是否真的好)并不能反叛ruby不流行,說ruby比java友好也不能證明ruby就是最好的。只能說明它比java好而已,這里我也承認。

能與lisp比較一下么?


琳琳的小狗 發(fā)表于 2012-02-27 16:55
3. 只有一個世界并不是優(yōu)勢,能將多個世界融合、一致化才牛b

Ruby并沒有排斥多元世界,相反,元編程在Ruby身上反而是通過一種簡單的、高度一致的基礎(chǔ)原則,也即”對象模型“來實現(xiàn)的,在Ruby中,真正的做到了”一切皆對象“,不相信?且看《Ruby元編程》的精彩剖析:)

排斥了。 排斥了編譯這個事情。 lisp/lua/python/js都有編譯,就只有ruby是單趟直接解釋。
這里不需要與lisp比了,lisp區(qū)分了幾種time,但又能將其融合。

一切皆對象什么的,正好是我對ruby的資料看不進去的原因之一。
lisp一切都是form,haskell一切都是function,但這兩社區(qū)的人很理智,不會在無關(guān)緊要的地方提到這種哲學上的考慮。
比如haskell就不會說它支持參數(shù)多態(tài)是因為haskell里一切都是函數(shù)的原因。 不將一切都處理為函數(shù)同樣可以支持前者, 只是haskelll恰好將一切按照函數(shù)對待。
同樣, 不將一切視為對象同樣可以支持(甚至是一致性地)許多優(yōu)美的表達, 面向?qū)ο蟛⒉皇沁@些優(yōu)美表達的原因, 只是ruby恰好將一切設(shè)計為對象而已。

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
23 [報告]
發(fā)表于 2012-02-27 18:58 |只看該作者
回復 21# 琳琳的小狗

open class后除了修改class的定義,還有其他用法么?

修改class的定義,或者修改某個object的定義:
1. 并不只有ruby才可以, 在lisp/lua/python/js里面都可以做到
2. 在上面提到的其他語言里,沒有哪一門將這個叫做metaprogramming。
它們,包括ruby,都是dynamic language, 運行時修改class/object是天經(jīng)地義的,不能修改才叫奇怪了。
3. 即使是在C/C++里, 有意識地將class設(shè)計為可以讓用戶修改也是很容易的事。
難的,但也可以做到的,同時也是不推薦的,是修改那些沒有被設(shè)計為打算被修改的東西。

我好奇的是ruby能不能做到code transformation。
例如,scheme,寫作let:

  1. (let ((x 12) (y 26)) (+ x y))
復制代碼
但實際上代碼是被轉(zhuǎn)換為一個接受2參數(shù)的匿名函數(shù),并以12,26作為參數(shù)立即調(diào)用

  1. ( (lambda (x y) (+ x y)) 12 26 )
復制代碼
也就是前面引用豆瓣試讀里面那個灰框里的技術(shù)。

為什么lua/python/js不將修改class/prototype/object的技術(shù)稱作元編程?
也許是因為它們都知道自己不能很好的完成code transformation,所以不敢稱自己能元編程。

所以,我好奇的其實是ruby是真正支持lisp里面那種元編程? 只是我還沒看到對應的章節(jié)?
還是ruby其實做不到, 它只是將元編程的定義給改了。



關(guān)于全局量,我也認為它不應該被濫用。但我表達我支持使用全局變量的意思?
全局變量不好的地方只是因為它可變的。
如果是全局常數(shù)?全局函數(shù)?全局class?全局module? 它們通常被認為是不變的,所以它們出現(xiàn)在全局里其實是很常見的。
而且你也應該清楚這些被認為是不變的東西被不加克制的打補丁不是什么好事。



關(guān)于面向?qū)ο,我有一個(或者說兩個)問題。
ruby是否是函數(shù)式語言?
如果是, 那么我用過的語言里面只有common lisp是將oo與functional結(jié)合好了的, 只不過common lisp的oo又不被其他oo社區(qū)接受就是了。
比如, ruby有map吧? 對集合每一個元素應用一個操作, 將操作的結(jié)果作為新的集合?

  1. ; scheme
  2. (map (lambda (x) (+ 1 x)) '(0 1 2))
  3. ; => (1 2 3)

  4. # ruby
  5. [0,1,2].map{|x| x+1 }
  6. # => [1,2,3]
復制代碼
ruby的代碼是這樣么?
如果要求平方根呢? (map sqrt '(0 1 4)) => (0 1 2)


那么,ruby里如何對2個集合執(zhí)行一個二元操作?
比如加法: (map + '(0 1 2) '(2 1 0)) => (2 2 2)
比如向容器添加元素: (map cons '(0 1 2) '( (a b) (c d) (e f) )) => ((0 a b) (1 c d) (2 e f))
有3個容器(a b) (c d) (e f), 分別添加 —— cons —— 0 1 2, 產(chǎn)生3個新的容器(0 a b) (1 c d) (2 e f)
添加在前在后都無所謂, 因為scheme里的list是單鏈表, 最方便的是在頭添加。

進一步地,如何對n個集合執(zhí)行n元操作?

論壇徽章:
0
24 [報告]
發(fā)表于 2012-02-27 23:38 |只看該作者
本帖最后由 琳琳的小狗 于 2012-02-28 01:04 編輯

首先聲明,我不是“能打的”,更不是來打架的。只不過是以一個Ruby程序員的角度,來反駁某些言論,為《Ruby元編程》這本書正名。以下針對上面的疑問,試著逐一解答:

修改class的定義,或者修改某個object的定義:
1. 并不只有ruby才可以, 在lisp/lua/python/js里面都可以做到
2. 在上面提到的其他語言里,沒有哪一門將這個叫做metaprogramming。
它們,包括ruby,都是dynamic language, 運行時修改class/object是天經(jīng)地義的,不能修改才叫奇怪了。


恩,確實如此,如果不能在程序執(zhí)行過程中隨心所欲的修改類定義(這只是對象模型中的一個元素而已)的話,根本不能稱之為“動態(tài)語言”,這也就是為啥C++他們不能算是一族的根本原因。但是,相比ruby,其他幾種動態(tài)語言,在語言設(shè)計層面,并沒有竭盡全力為程序員考慮,比方說,javascript中雖然具備原型鏈可以耍點小花招,但卻不具備method_missing(對象在接收到某個不認識的消息時,會被觸發(fā))特性,我不能在一個地方抽象出未知方法調(diào)用并做下一步打算,真是遺憾。了解Rails框架的人都知道,這正是ActiveRecord的實現(xiàn)基石(《Ruby元編程》這本書的第二部分有詳細、深入的講解)。例如我數(shù)據(jù)庫中有張users表,其對應的model類定義可以簡單到這樣:
  1. class User < ActiveRecord
  2.   #類主體可以不寫任何代碼
  3. end
復制代碼
Rails利用元編程,實現(xiàn)了ORM的0配置,你可以這樣來使用(假設(shè)users表中存在name、sex、age字段):
  1. 
  2. #動態(tài)查詢方法,根據(jù)姓名和年齡查找數(shù)據(jù)庫中對應的記錄
  3. u = User.find_by_name_and_age 'metaprogramming', 28
  4. #獲取、修改name字段的值
  5. u.name
  6. u.name = 'ooxx'
復制代碼
這所有的一切,都源于ActiveRecord在第一次調(diào)用某個尚未定義的方法時,通過method_missing機制捕獲了它,并利用相關(guān)信息查詢、修改了數(shù)據(jù)庫中對應的記錄,也即書中所說的“幽靈方法”。ActiveRecord的實現(xiàn)遠比這個精巧,為了兼顧效率,并不是每次都執(zhí)行完整的方法查找過程,重復調(diào)用的時候,這個方法已經(jīng)是真正存在于模型類中了。請問其他語言如何實現(xiàn)此功能?同樣,實現(xiàn)模型關(guān)聯(lián),一句類宏就搞定:
  1. class User
  2.   has_many :skills
  3. end

  4. class Skill
  5.   belongs_to :user
  6. end
復制代碼
注意到上面類定義中的語句沒?其結(jié)果是,分別在兩個類中定義了兩個關(guān)聯(lián)方法(User#skills以及Skill#user)其實,這只是兩個類方法調(diào)用而已,通過省略方法調(diào)用的括號,讓其看起來更像是一句聲明,所以《元編程》這本書把這種手段叫做“類宏”。

總結(jié)一下,Ruby對元編程的定義其實可以這么理解:通過運行時修改對象模型,最大化程序員對語言構(gòu)件的控制力。如果非要說他不是元編程,那絕對是說得通的,套用本書第一部分的結(jié)束語:“根本就沒有什么元編程,從來都只是編程而已”——這充分說明了,在Ruby中,你是很難嚴格界定某段代碼是不是元編程,因為構(gòu)成這些代碼的元素,都是純純粹粹的ruby語法而已。

3. 即使是在C/C++里, 有意識地將class設(shè)計為可以讓用戶修改也是很容易的事。
難的,但也可以做到的,同時也是不推薦的,是修改那些沒有被設(shè)計為打算被修改的東西。


在Ruby中,不需程序員下意識的去設(shè)計就獲得了這種能力,你用不用哪倒是另一回事情。很多情況下,具備靈活的修改、打補丁的特性可以創(chuàng)造出更多有意思的玩意兒,比如單元測試中常見的Mock框架,我拿Rspec來舉例,其自帶的mock框架可以讓你自由的生成mock、stub對象,甚至是stub已有對象的行為,這讓程序員編寫的測試代碼更加健壯靈活(具體原因請參考TDD的相關(guān)書籍):

m = mock(:user)
m.should_receive(:sex).and_return(:unknow)

String.stub!(:class).and_return(:OOXX)

具體請參見:http://rubydoc.info/gems/rspec-mocks/frames

我好奇的是ruby能不能做到code transformation。


Ruby吸收了Lisp以及Smalltalk的特性,骨子里自然是具備FP特性的。在Ruby中,對FP的支持主要依靠可調(diào)用對象家族來實現(xiàn),其中最為常見的是代碼塊(block)以及l(fā)ambda表達式,代碼塊可以對應到Lisp中的閉包,在元編程這本書里面,對其進行了詳細介紹,包括由它引申而來的技巧——“扁平作用域”。模仿你那個例子:

  1. lambda {|x, y| x + y}.call(12, 26) #一個匿名、立刻執(zhí)行的lambda對象,返回38
  2. -> (x, y) {x + y}.call(12, 26) #同上,返回38,但使用了ruby1.9新增的“詭異”語法,哈哈
  3. [0,1,4].map {|i| Math.sqrt i} #返回[0, 1, 2]
  4. [0,1,2].zip([2,1,0]).map {|i| i.reduce(&:+)} #返回[2,2,2]
  5. [0, 1, 2].zip([[:a, :b], [:c, :d], [:e, :f]]).map(&:flatten)  #返回[[0, :a, :b], [1, :c, :d], [2, :e, :f]]
復制代碼
這里就不再列舉了,實在是沒意思……Ruby元編程的最大用途,就是用來實現(xiàn)領(lǐng)域特定語言,也就是DSL,而且在Ruby社區(qū)比較流行的是“內(nèi)部DSL”(由合法的ruby語法元素構(gòu)成)而非“外部DSL”,Rails屬于DSL,Rspec同樣也是:
  1. describe "語言之爭" do
  2.   it "毫無意義"
  3.   it "不需要鉆牛角尖"
  4.   it "各自具有擅長的領(lǐng)域"
  5. end
復制代碼
運行測試,結(jié)果如下(按照TDD的原則,下一步迫切需要要做的,就是實現(xiàn)這些Pending狀態(tài)的example,所以請停止毫無意義的爭論吧):


同理,要實現(xiàn)一個Lisp解釋器并非什么難事,已經(jīng)很多現(xiàn)成的代碼了,比如這些個,都是純ruby實現(xiàn),git上有源碼可供下載觀摩,這也是Ruby元編程的絕佳展現(xiàn)(題外話,我本人也是FP的愛好者,不過對Lisp而言,僅了解Scheme方言,只看過過兩本書,《How to desgin program》以及《SICP》):
http://thingsaaronmade.com/blog/introducing-flea.html
Flea is a tiny Lisp interpreter implemented in Ruby. Flea is designed to be an example of how simple it can be to bootstrap the core of a small flexible language. Flea essentially defines an informal subset of Scheme, just enough to be fun and interesting.
  1. (define number (+ (rand 9) 1))

  2. (display "\n\nI'm thinking of a number between 1 and 10,\n")
  3. (display "try to guess it!\n\n")

  4. (define user-guess
  5.    (lambda ()
  6.      (display "Take a guess - ")
  7.      (define guess (string-to-num (gets)))
  8.      (if (equal? guess number)
  9.        (display "Good guess!\n")
  10.        (begin
  11.          (if (greater-than? guess number)
  12.            (display "Lower!\n")
  13.            (display "Higher!\n"))
  14.          (user-guess)))))

  15. (user-guess)
復制代碼
感覺怎么樣?嘿嘿……下面這個是國人作品哦:

http://code.google.com/p/orzlisp/
a lisp interpreter implmention on ruby by ssword , just for study & fun


再來一個:
https://github.com/tmountain/Liby
Liby is a simple Lisp interpreter written in Ruby. It's heavily derived from
slisp which was written by Sandro Sigala. Liby implements a good number of
constructs seen in typical Lisp systems and may be useful for learning the
basis of the Lisp language.


所以,Ruby對FP的支持程度,也就不言自明了,再加上完善的面向?qū)ο髮崿F(xiàn),絕對稱得上是Lisp與SmallTalk的結(jié)合。廣告時間:關(guān)于領(lǐng)域特定語言(說實話,我不太喜歡書里面的翻譯“領(lǐng)域?qū)僬Z言”),在《Ruby元編程》一書中對這個主題也有詳細介紹,想自己實現(xiàn)DSL的朋友建議認真看看。


最后嘮叨幾句,我之前的帖子,就語言本身,并沒有將Ruby與Java語言本身做任何優(yōu)劣對比,我只不過是對兩者的開發(fā)效率有所感觸。話說回來,Java作為主流編程語言發(fā)展至今,其社區(qū)積累了豐富的理論學說及最佳實踐,我個人也是通過Java主題的相關(guān)書籍來學習那些好東西的,比如設(shè)計模式(說起這個,如果OwnWaterloo看了Ruby的另一本叫《Design Patterns in Ruby》的書,估計會吐血的吧,里面有句話是這樣說的:“設(shè)計模式體現(xiàn)了編程語言的特性匱乏”,在ruby中,很多所謂的模式,都是多此一舉)、重構(gòu)、TDD等,這些都是無關(guān)語言、無關(guān)平臺的通用思想和有價值的知識。對于C++,我沒有學習過,也沒有任何的概念,并不了解相關(guān)特性和具體的細節(jié),故不做任何評價,因為對自己不了解的事物做出任何評判,恐怕都會有失偏頗。倒是蘑菇叔叔的這篇評論比較實在,來看看這位非Ruby程序員是如何感受這本書的:
《Ruby 元編程》——十年來讀到的最好的編程技術(shù)書籍

不扯遠了,希望這些爭論不要影響到大家試讀本書,Rubyist們,趕緊加入進來呀,所有關(guān)于Ruby元編程的一切,都可以貼出來討論。對了,最后賣下關(guān)子,后續(xù)鄙人會放出專題screencasts,針對書中的一些知識點進行探討,并加入部分實戰(zhàn)內(nèi)容,敬請關(guān)注:)

論壇徽章:
7
戌狗
日期:2013-12-15 20:43:38技術(shù)圖書徽章
日期:2014-03-05 01:33:12技術(shù)圖書徽章
日期:2014-03-15 20:31:17未羊
日期:2014-03-25 23:48:20丑牛
日期:2014-04-07 22:37:44巳蛇
日期:2014-04-11 21:58:0915-16賽季CBA聯(lián)賽之青島
日期:2016-03-17 20:36:13
25 [報告]
發(fā)表于 2012-02-27 23:59 |只看該作者
試讀中!

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
26 [報告]
發(fā)表于 2012-02-28 02:11 |只看該作者
本帖最后由 OwnWaterloo 于 2012-02-28 02:13 編輯

回復 24# 琳琳的小狗

先說我最關(guān)心的,OO與functional的混合。很多語言都沒做好這東西。
許多OO語言是將data(instance)與function(method)綁在了一起。

你的答案其實已經(jīng)將我的問題了,我的問題是在n個集合上應用n元函數(shù)。

  1. [[0,1,2].zip([2,1,0]).map {|i| i.reduce(&:+)} # [2,2,2]
復制代碼
map不是一個獨立的函數(shù),而是Array的一個instance method,于是只能先將 [0,1,2], [2,1,0] zip 為一個Array, 然后在此Array上map。
注意此處zip依然只是一個instance method, 比較: (zip '(0 1 2) '(2 1 0)) => ( (0 2) (1 1) (2 0) )。
之后顯然也不是直接在 0 2, 1 1, 2 0 上使用二元函數(shù), 而是再將先前zip得到的 (0 2) (1 1) (2 0) reduce 到一個值。

  1. [0, 1, 2].zip([[:a, :b], [:c, :d], [:e, :f]]).map(&:flatten)  #[[0, :a, :b], [1, :c, :d], [2, :e, :f]]
復制代碼
依然是先zip得到 [0,[:a,:b]], 然后在這個集合上flatten。而不是將0直接加入[:a,:b]。
而且被修改的問題不僅如此, 還包括flatten。 我本意是想問push。

對比:

  1. (map atan '(0.0 -0.0) '(1 1)) ; => (0.0 -0.0)
  2. [0.0,-0.0].zip([1,1]).map(&Math.method(:atan2)) # => [0.0, -0.0]
復制代碼
后面那行ruby代碼我都不知道該怎么解釋……
但至少暴露出了一個問題,Ruby沒有first class function,必須用一個Method作為包裝,然后call。這問題暫且放下。

functional與OO的一個矛盾的地方是,因為OO將method與object綁定,所以有些函數(shù)會少一個元。
atan 數(shù)學意義上是一個2元函數(shù) —— 有兩個集合 (a b) (x y), 通過map得到新集合 (list (atan a x) (atan b y))。
cons 數(shù)學意義上也是2元函數(shù) —— 有兩個集合 (a b) (xs ys), 通過map得到新集合 (list (cons a xs) (cons b ys))。

而許多OO語言, 比如ruby:
Math的類方法atan2 本意是一個2元函數(shù), 調(diào)用時也需要傳入2個參數(shù)。
如果類方法其實也是class object(我不知道ruby的術(shù)語怎么說), 也是會傳入一個隱式參數(shù)的話,其實那個隱式參數(shù)沒有被使用, 依然是2元函數(shù)。
Array的實例方法 push ,如果有兩個集合 [ ["x0","x1"] , ["y0","y1"] ] 與 [0,1], 想構(gòu)造一個新的集合 [ ["x0","x1",0] , ["y0","y1",1] ], 就會遇到問題。
[ F(["x0","x1"], 0) , F(["y0","y1"],1) ] —— 怎么表示那個F?
(這里修改了一下, 使用: x1 且中間沒有空格會被認為是表情……)

如果不使用high order function,不將函數(shù)傳入傳出(函數(shù)傳出在ruby里面依然有問題,稍后再說), object.method(arg)只是一個語法問題。
但如果想要傳入一個F, 它可以 F(object,arg), 各種語言就會想出各種方法, C++里是mem_fun, python里面叫unbounded-method, js里面叫indirection call —— 于是將語言弄得很復雜。
而其目的只有一個 —— 將那個隱式的self/this,重新顯式化。 那何不一開始就顯式化?
lua就是這樣做的, 沒有隱式參數(shù), 只有一個語法糖。

  1. local a = {0.0,-0.0}
  2. local b = {1,1}
  3. local c = map(math.atan2 , a , b) # map不是lua的標準庫
復制代碼
假設(shè)lua有一個Array庫,就可以:

  1. local xs = Array{1}
  2. Array.push(xs,2) --> 或者
  3. xs.push(xs,3) --> assert(Array.push == xs.push)
  4. xs:push(4) --> 使用 : 語法糖, 與上面一行相同

  5. map(Array.push,{ {"a"}, {"b"}, {"c"},{"d"} },xs) --> 就不需要有unbounded/bounded之分。
復制代碼
如果是非OO的functional語言,就只有data與function(甚至只有function)。
而一旦加入OO,事情就會非常復雜,class/prototype/instance,unbounded/bounded-method, normal/method/indirection/construction call……
這是我反感OO的一個地方, 引入了許多繁瑣的概念, 而且完全沒必要。

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
27 [報告]
發(fā)表于 2012-02-28 02:28 |只看該作者
回復 24# 琳琳的小狗

關(guān)于method_missing。
lua支持,通過metatable的__index/__newindex。

更一般地,method_missing可以通過一個更范化的機制實現(xiàn),可恢復的異常。
我不知道ruby的異常是不是可恢復的,但基本主流(python/js/C++/Java/C#)語言的異常都是一旦拋出就無法回到拋出點。
common lisp的condition system直接支持這個概念。

而可恢復的異常又是另一個更范化的機制的特殊化 —— coroutine, 被lua支持。
而coroutine又是另一個更范化的機制的特殊化 —— continuation, 被scheme支持。
ruby貌似這兩者都支持。

那method_missing根本不需要語言作為特性提供,直接在method_missing的handler里補上然后回到拋出點就完了。
而這種通過很小的核心語言自身來增加新的語意結(jié)構(gòu),當然也包括DSL,就是lisp的賣點。
所以我很關(guān)心的那個問題: ruby是否支持code transformation? 你貌似還沒回答呢……

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
28 [報告]
發(fā)表于 2012-02-28 02:41 |只看該作者
回復 24# 琳琳的小狗

關(guān)于語言之爭是否有意義?
只有認為自己所學語言就是最有表達力的,或者干脆很懶的程序員才認為語言之爭沒有意義。
以你自己的例子來說, 你也能體會到并且承認ruby相對于java能得到巨大的生產(chǎn)力的提高, 但ruby就是生產(chǎn)力最高的語言么? 我看不見的。
或者你就只滿足于這樣的生產(chǎn)力?

這就是語言之爭的意義。


關(guān)于ruby實現(xiàn)的lisp。
我不知道你舉這個的意圖何在?
因為ruby可以實現(xiàn)(或者說很容易實現(xiàn))lisp,所以就不需要比較ruby與lisp了?
那很多語言都不需要與lisp比較了,都可以實現(xiàn),
而且,為何不直接用lisp?


關(guān)于設(shè)計模式。
如果你逛C/C++社區(qū),就知道我是反OO與反模式的。
在我還熱衷C++的時候(那時候只用過lua,因為WOW,其他動態(tài)語言都沒用過),就知道這玩意不行。
學了lisp更是懶得給別人指出設(shè)計模式為什么渣了。


關(guān)于“《Ruby 元編程》——十年來讀到的最好的編程技術(shù)書籍”。
這本書的試讀章節(jié)我沒發(fā)現(xiàn)任何亮點。都是我在各種語言里早就玩得不想玩的東西 —— 信不信只好由你了。
十年來讀到的最好書籍就是這個樣子? 我只能說井太小……

跑這里來踢場子(其實發(fā)帖時沒注意到這是ruby板塊,因為它也在C/C++板置頂了),也是為了能讓(或者說激將)一些有經(jīng)驗的ruby程序員說出ruby到底好再哪?
至少到目前為止,從你提到的那些ruby的功能里,我還是沒發(fā)現(xiàn)任何亮點 —— 同樣信不信只好由你了。

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
29 [報告]
發(fā)表于 2012-02-28 03:53 |只看該作者
回復 24# 琳琳的小狗

最后說兩點。關(guān)于ruby的語法以及新語法,還有ruby與FP。

怎么說呢,這也許不算ruby的缺陷,ruby并不需要是一個核心簡單清晰卻又支持很強表達能力的語言,也不需要支持FP編程。
但如果與之比較的語言少,就不會將ruby的某些東西理解為權(quán)衡,只會當作優(yōu)勢。


先說語法。
lambda {|x, y| x + y}.call(12, 26) #一個匿名、立刻執(zhí)行的lambda對象,返回38
-> (x, y) {x + y}.call(12, 26) #同上,返回38,但使用了ruby1.9新增的“詭異”語法,哈哈

無節(jié)制地引入新語法并不是好事。 為什么在scheme里是( (lambda (x y) (+ x y)) 12 26 ) 而在ruby里要多一個call? 你想過這問題沒有?
為什么函數(shù)的調(diào)用方式有這么多種 —— JS是4種,我看ruby也好不到哪去。

1. f(x)
ruby可以簡化語法,寫f x。但代價就是它沒有語法來區(qū)分函數(shù)的行為與函數(shù)的結(jié)果。
其他語言里,f求值就得到函數(shù)本身,f(x)就是函數(shù)應用得到的結(jié)果, ruby里沒法區(qū)分這兩者,不能將f傳遞給另一個函數(shù)。
于是ruby就沒有first class function, 于是就需要 method(:f)來做一個包裹傳入, 并使用call。

連傳入一個函數(shù) —— 高階函數(shù),函數(shù)式編程的重要特性 —— 都這么麻煩,怎么談FP?

2. f.call(x) 上面說了

3. yield x
我不知道block有什么好的地方,在我看來它是設(shè)計缺陷。平白無故地(也許并不是,后面會說我的猜測)增加了Proc這種概念, 以及Proc.new/lambda這樣的復雜性。
在FP里,anonymous function是first class的。 而在ruby里, block是語法結(jié)構(gòu), 不是1st class value, method包裹的那個才是。

而且我現(xiàn)在就可以指出因為block的語法產(chǎn)生的代價, 沒法很好的傳出一個函數(shù) —— 同樣是高階函數(shù)。
以compose作為傳出高階函數(shù)的例子, lua里可以 compose(f,g)(x) --> f(g(x))。 注意第2個調(diào)用。
而ruby里, f(arg) 這里是為block保留的。 寫第2個調(diào)用就是錯誤。


語法很難被編程。
lisp的路線是放棄過多的語法,盡量讓語言的各個部分都可以被編程
common lisp支持read-macro,scheme有readtable,不過我不知道有沒有被標準化。通過它們改變語法是很容易的事情。
比如支持clojure的 #(+ %1 %2) <=> (lambda (x y) (+ x y)。
但通常cl與scheme程序員不會這么做,而且clojure也明確地表示不會支持read-macro。
因為lisp更喜歡增加語意結(jié)構(gòu)而非語法結(jié)構(gòu),過多地引入語法會增加AST(abstract syntax tree)在大腦中的轉(zhuǎn)換層次,增加語意結(jié)構(gòu)的轉(zhuǎn)換難度。

再舉個語法結(jié)構(gòu)與語意結(jié)構(gòu)的例子。 x,y = y,x 貌似ruby管這叫并行賦值? 許多語言 —— 包括lua/python都以此自豪。
而cl(也被emacs lisp偷學)的做法是(rotatef x y):
1. 互換變量的值是更一般化的rotate的一個特例, 還可以

  1. (let ((x 12) (y 26) (z 86))
  2.   (rotatef x y z)
  3.   (list x y z))
  4. ; => (26 86 12)
復制代碼
2. 至少它沒有違法DRY(Do not Repeat Yourself), x,y只出現(xiàn)了一次
3. rotatef 自己只是一個macro, 你可以看到它是怎樣實現(xiàn)的, 而不是聽人解釋它是什么功能。

而通過增加語法結(jié)構(gòu)的語言,學習成本高。C++在這方面也很惱火。
比如haskell的do notation、list comprehension都是用起來方便,但會影響到更深入地學習, 比如manod。
如果打算專注這語言的話這并不是特別嚴重的問題。
但至少還有一個潛在地缺陷 —— 你得語言的下一個版本支持它。
因為在很多語言里它都是不能被編程的, 是語言核心的一部分(haskell 語言是例外,可以重定義許多語法,但不是通過read-macro)。
比如你說的那個1.9支持的新詭異語法, cl 想做隨時都可以做, 還可以做得更詭異。



最后,再說FP。

>> Ruby吸收了Lisp以及Smalltalk的特性,骨子里自然是具備FP特性的。
這說法你覺得科學么?
我還是很在意ruby是否吸收了lisp的code transformation —— 這與函數(shù)式編程無關(guān),稍微又跑題了, 因為我確實關(guān)心這個。
只要支持這個, 語言核心就可以很簡單, 只要支持if與continuation就是圖靈完備了, 而且可以很容易地支持所有語言里的其他控制結(jié)構(gòu)。
不過考慮到continuation實現(xiàn)的復雜性, 可以再加一個lambda。 if+lambda就是圖靈完備, continuation只是讓非局部跳轉(zhuǎn)更容易實現(xiàn)。
如果使用惰性求值, 連if都可以不用。

>> 同理,要實現(xiàn)一個Lisp解釋器并非什么難事,已經(jīng)很多現(xiàn)成的代碼了
>> 所以,Ruby對FP的支持程度,也就不言自明了
這種說法同樣不科學, C也可以實現(xiàn)lisp解釋器, C是函數(shù)式語言么?

functional style programming與functional programming language是兩回事。
前者連C語言里都可以做。 除了非結(jié)構(gòu)化的語言, 似乎都可以使用functional style programming。
問題是容易程度。
就像metaprogramming, 許多動態(tài)語言(dynamic language)都可以做, 靜態(tài)語言只能在編譯時做。
但只有l(wèi)isp將這件事變得很容易, 容易到像呼吸那樣平常。

其他更高階的函數(shù)式編程支持,比如尾調(diào)用優(yōu)化、純函數(shù)與顯式副作用、惰性求值…… 就不說了,支持這些的語言不多。
但ruby不支持1st class function,要用Proc.new或者lambda包裹出一個method, 要用call/yield而不是直接調(diào)用……
支持嵌套函數(shù)么? 這我不清楚, 貌似不行。
支持閉包, 這我很確定, 也就只支持一個沒多少語言不支持的閉包……
這樣的語言大量使用functional style programming絕對不會輕松。

另外,不只是語言本身,庫是否使用函數(shù)式接口也很重要。
這點上C++/lua/python都做得不好,因為它們骨子里其實是命令式語言(我就不說OO了,我認為OO根本排不上programming paradigm)。
比如上面的:

  1. (map cons '(1 2) '( (10 100) (20 200) )) ; => ( (1 10 100) (2 20 200) )
  2. # python使用unbounded-method還是很容易,只是概念很復雜
  3. map(list.append,[ [10,100],[20,200] ] , [1,2])
復制代碼
但結(jié)果是 [None,None], 因為list.append不返回新list, 而只是in-place更改。

而scheme的庫就是一個正面例子。
Ruby,至少Array.push是返回array本身, 但我想這里更多的考慮是為了鏈式表達而不是函數(shù)式接口。
更多的我就不了解了。

因此,我認為Ruby是函數(shù)式語言的說法只是相對的。
只是許多人并沒有函數(shù)式編程的精確定義,只知道籠統(tǒng)的說什么語言是,什么語言不是。
而Ruby支持的函數(shù)式語言的構(gòu)造上面已經(jīng)列出了, 貌似就只有閉包…… 真的少得可憐……

論壇徽章:
2
青銅圣斗士
日期:2015-11-26 06:15:59數(shù)據(jù)庫技術(shù)版塊每日發(fā)帖之星
日期:2016-07-24 06:20:00
30 [報告]
發(fā)表于 2012-02-28 04:10 |只看該作者
回復 29# OwnWaterloo

哦,前面還有一個關(guān)于block的猜測忘記說了。
這個猜測就是:松本的在編程語言方面的理論水平,尤其是函數(shù)式編程,其實很差,甚至比Python的作者還要差。

http://www.artima.com/intv/closures.html

Yukihiro Matsumoto: Basically, blocks are designed for loop abstraction. The most basic usage of blocks is to let you define your own way for iterating over the items.

這段真把我看吐血了……

其實Python的作者還是懂函數(shù)式編程,只是他本人不喜歡。
松本根本就不知道…… 僅僅為了loop abstraction就定義了一種語法結(jié)構(gòu)? 之后才發(fā)現(xiàn)block不是1st class, 再搞出method已經(jīng)晚了。
我不知道ruby的發(fā)展歷史, 如果block比 Proc/lambda 更先加入語言, 那猜測基本就正確了。


查看編程語言的發(fā)展很有意思, 尤其是Python與Lua的比較。
可以很清晰地觀察到Python自下而上的設(shè)計,case by case: 我覺得那里不方便了, 于是添加一個特性。
而Lua是自上而下的設(shè)計: 語言需要支持那些范化且通用的構(gòu)造? 那么就支持這些, 那些零零碎碎的特性不過是這些范化特性的特殊化而已。
就Python的generator的發(fā)展過程, 相比Lua的coroutine, 就看得人吐血了……
而且Python語言是越來越發(fā)散, 而Lua是越來越內(nèi)聚…… 無他,作者的理論水平?jīng)Q定的。

看到上面引用的松本那段話,我相當懷疑他的理論水平。
當然,不被我吐槽的語言也沒幾個,連C++都經(jīng)常被我吐槽。
可能只有Lua與各種Lisp在語言的表達能力與簡煉方面有最高的比值, haskell這種奇葩我還沒能學會…… 也許也能稱上鬼斧神工……

您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP