Haskell code 用Clojure实现

在看 Haskell - The Craft of Functional Programming 2e. 下面的函数

 
getWord :: String -> String
getWord [] = []
getWord (x:xs)
  | elem x whitespace = []
  | otherwise = x : getWord xs
 

可以很容易翻译为Clojure代码, 函数式语言本质都是相通的

 
(defn elem-of-whitespace [c]
  (contains?  #{(first "\n") (first " ") (first "\t")} c)
)
 
(defn get-word-list [s]
  (cond 
    (empty? s) ""
    (elem-of-whitespace (first s)) ""
    :otherwise (cons (first s) (get-word (rest s)))
  )
)
 
(defn get-word [s]
  (clojure.string/join (get-word-list s))
  ; or (apply str (get-word-list s))
)
 
(get-word "hello world today")
 

几个要点: Haskell的String类型就是字符的列表 String = [Char]. Clojure中虽然没有这个功能, 但是Clojure有seq, String可以当成sequence来用, 可以对其使用first rest等函数.

Haskell有guard expression和pattern matching, 所以代码可以写的非常简洁. Clojure可以用cond来模拟. 用if来写就会非常难看.

Haskell对递归的处理更好, Haskell中把函数写成递归是普通的事情, 而Clojure则不同, 要考虑溢出的问题.

 
user> (get-word (clojure.string/join (repeat 3000 \a)))
StackOverflowError   clojure.lang.APersistentSet.contains (APersistentSet.java:34)