What have you found for these years?

2012-05-12

clojure 初步心得

鸚鵡傳了 4clojure 過來,我不知不覺就玩起來了。目前玩到現在,
我解了 46/149 題。怎麼說呢,原本想說全部寫完的,反正也沒
幾題,應該幾天就寫完了吧?不過現在想放棄了。

主要原因是,我覺得我還是不太適應 lisp 吧。我用到現在,主要
覺得有兩個麻煩。一是還是不太會排版,我有種 write only 的
感覺。我想事後有沒有辦法重新閱讀並理解程式,有一個很大的
重點是,有多少思考的過程有被白紙黑字寫下來。有足夠多的話,
就很容易藉由一些關聯回想起來。

我寫 clojure 的問題是,把太多東西匿名地串起來了,有太多暫時的
中間程式沒有名字,就像寫 haskell 卻不用 let/where 也不定義
function, 只用 foldr/foldl/map/filter 等等 function 把程式湊
出來,甚至是用 point free 的方式.... 這種程式當然很難懂。

這可能只是我不知道怎麼組織與排版的關係,一堆括號我還是覺得
很難有一個必然的排版法。

另一個問題我覺得可能比較嚴重一點,但我不確定。關鍵在於我有
一個 list of booleans, 我想要知道裡面是不是全部是 true.
在 haskell 裡,就是用 and 這個 function. 在 clojure 裡...
and 是 macro, 不是 function, 因此我沒辦法把 and 丟給
其他 higher-order function 用 :s 也罷,那我就用 reduce (&&)
也可以吧?結果我卻找不到 logical and, 查了半天,還看到有人說
如果 and 是 function 的話,就沒有 short-circuit 的效果。

呃,是啦,但因此不給任何一個 logical and, 也有點....
(edit 2012-05-12 05:47 忘記提,而且沒有 splat operator 的樣子)
最後的解決辦法是 (partial every? identity), 還算是會動沒問題吧。

以上是壓死駱駝的最後一根稻草。過程中還有不少其他的小挫折。
例如我不習慣 () 本身是有語意的。不小心多加一個括號,就會被
抱怨裡面的東西不是 function. 其他還有像是很多 function 本身
都具有多重意義,不同的呼叫法,給予不同的 argument, 有時候
會有不同的效果。這樣用起來是很方便,不過我還不習慣,覺得
有點混亂。

還有很多小細節,就不一一提了。嗯,還有 clj interactive mode
不支援 readline, 用起來好痛苦..。我以為 ghci 已經不太好用了
(相較 ruby 的,瞧瞧 rib),沒想到 clojure 的更是...。現在想想,
ghci 根本就已經是非常好用的 interactive mode 了。其他超難用的
根本就一大堆。

嘛,不過寫這 46 題還是帶給我滿多樂趣的。雖然最後決定是放棄,
但說真的,clojure 遠比我當初想像的好玩多了。我想這跟 4clojure
前面幾個題目真的都很簡單有關。畢竟我一直沒有試,主要還是因為
不知道怎麼上手。成功適應這種 syntax 之後,就是個人造化了。

我還算喜歡 #(+ 1 %) 這種語法,寫起來很方便,雖然不能 nested.
可以用某種形式的 pattern matching 也還不錯。例如 map (fn [[a b]])
雖然這種 ruby 也做得到,我不確定 clojure 能不能 match 其他的。
總之寫起來還算滿有彈性的,我的感覺是確實有 functional programming
的味道,雖然不是預設 curried functions 用起來還是不大方便。也有一些
scripting 的味道。也總算體會到 lisp 寫起來是什麼感覺了。

不過就這樣吧。最後附上我其中兩題 medium 問題的實作:

function composition:

(fn com [f & fs]
  (fn [& a]
    (if (= fs nil)
        (apply f a)
        (f (apply (apply com fs) a)))))
merge-with:
(fn [f & xs] (reduce 
                #(reduce (fn [r [key rhs]]
                           (let [lhs (r key)]
                             (if lhs
                               (conj r [key (f lhs rhs)])
                               (conj r [key rhs]))))
                          %1
                          %2) xs))
p.s. 所以目前最滿意的語言還是 ruby 和 haskell. 下一個看 SML,
希望這能帶給我一些從 haskell 裡看不到的東西。目前打算看的是
Favonia 給的 Programming in Standard ML

4 retries:

jaiyalas said...

什麼時候要來看 MetaOCamlm?

Lin Jen-Shin (godfat) said...

暫時不 XD

walterc said...

i did face the same problems as you did while learning clojure. but i think i had a easier time than you did because i used emacs and paredit extension for clojure mode. paredit really made programming a lisp-style language a lot simpler. after a while, you don't see parathesis anymore ;-)

Lin Jen-Shin (godfat) said...

sounds cool, i guess it's this one?
http://emacswiki.org/emacs/ParEdit
too bad i might need to learn emacs first though, which i never really succeeded.
i've heard that there are also some editors which would colorize the corresponding parentheses with the same color, which might also help.

on the other hand, trying to use def, defn and other definition helpers might as well help a lot (which is forbidden in 4clojure due to the natural of embedding the code inside the problem, i think)

i'll try again in other time, thanks!
also i think i should also try their STM support in order to compare with the one GHC provides, which should be interesting.

Post a Comment

All texts are licensed under CC Attribution 3.0