你能从Functional Languages 101翻译这两个例子吗? (方案 - > Clojure)

时间:2010-10-15 10:08:10

标签: clojure scheme

我想了解这些例子,但他们在Scheme中。我希望他们在Clojure:D

示例1 - 计算列表的长度


(define length
  (lambda (ll)
    (cond
      ((null? ll) 0)
      (#t (add1
        (length (cdr ll)))))))

例2 - 对列表中的每个元素进行平方


(define squares
  (lambda (li)
    (cond
      ((null? li) ())
      (#t (cons
            (* (char li) (char li))
            (squares(cdr
    li)))))))

示例3 - “地图”功能(如map / reduce中所示)


(define map (lambda (func lst)
  (cond ((null? lst) ())
        (#t (cons (func (car lst))
              (map func (cdr lst)))))))

咖喱“地图”


(define map2
  (lambda (func)
    (lambda (lst)
      (cond ((null? lst) ())
        (#t (cons (func (car lst))
              ((map2 func) (cdr lst)))))))

动机

这些例子来自其他人可能感兴趣的功能编程演示文稿:Functional Languages 101: What’s All the Fuss About?

一旦您提交了答案,我希望您同意将其作为评论发布在Clojure人员的演示文稿中,以了解原始代码

4 个答案:

答案 0 :(得分:6)

我有一些stoff:http://github.com/nickik/Essentials-of-PLs-in-Clojure/blob/master/src/EssentialsOfProgrammingLanguages/core.clj

它的所有方案都是为了解决问题。您可以下载Essentials of Programming Languages-Book的源代码以获得Scheme代码。


以下是您的示例:

(defn length [lst]
    (cond
      (seq ll) 0
      :else (inc (length (rest lst))))))

注意:clojure有一个计数功能


(defn squares1 [li]
   (cond (nil? (seq li)) (empty li)
     :else (conj (squares1 (rest li)) (* (first li) (first li)))))

(defn squares2 [li]
   (map #(* % %)  li))

(defn mymap [f coll]
        (cond (nil? (seq coll)) (empty coll)
          :else (conj (mymap f (rest coll)) (f (first coll)))))

(defn map2 [f]
    (fn [lst]
        (cond (nil? (seq lst)) (empty lst)
              :else (conj ((map2 f) (rest lst)) (f (first lst))))))

请注意,您不能只进行1:1的翻译。 '()evals之间的差异等等。

以下是最重要的那些

  • (nil?(seq list))not(null?lst)因为'()在clojure中不是nil
  • conj更好,然后你可以使功能与mure数据结构一起使用
  • (空lst)比'()更好,因为(空lst)保持类型向量,列表,记录,结构或其他东西

答案 1 :(得分:5)

列表长度:

(defn my-length [lst]
    (loop [len 0 x lst]
        (if (empty? x)
            len
            (recur (+ 1 len) (rest x)))))

user=> (my-length '(1))
1
user=> (my-length '(1 2 3 4))
4
user=> (my-length '())
0

对列表中的每个元素进行平方:

(defn squares [lst]
    (loop [sqrs '() x lst]
       (if (empty? x)
           (reverse sqrs)
           (recur (cons (* (first x) (first x)) sqrs) (rest x)))))

user=> (squares '(1 2 3 4))
(1 4 9 16)

地图:

(defn my-map [func lst]
    (loop [res '() x lst]
       (if (empty? x) 
           (reverse res) 
           (recur (cons (func (first x)) res) (rest x)))))

user=> (my-map (fn [x] (* x 2)) '(1 2 3))
(2 4 6)

地图2:

请参阅nickik的解决方案。

答案 2 :(得分:2)

map的更多clojurey翻译:

(defn map
  [f coll]
  (lazy-seq
    (when-let [s (seq coll)]
      (cons (f (first s)) (map f (rest s))))))

利用闭包:定义map-inner,例如上面的map

(defn map
  [f]
  (fn [coll]
    (map-inner f coll)))

在惯用语中,通常你会利用nil是逻辑错误的。

(defn length
  [coll]
  (loop [s   (seq coll)
         len 0]
    (if s
      (recur (next s) (inc len))
      len)))

map一样:您将使用延迟序列而不是急切列表。

(defn squares
  [coll]
  (lazy-seq
    (when-let [s (seq coll)]
      (let [fst (first s)]
        (cons (* fst fst) (squares (rest s)))))))

答案 3 :(得分:0)

define在{* 1}}中是deflambdafn,函数参数写为向量[],而不是列出(),{ {1}}为null?emptycarfirstcdrrest的默认大小写为{{1} }},而不是cond

因此,对于您的第一个示例,我们得到:

:else

使用#t而不是(def length (fn [ll] (cond (empty? ll) 0 :else (+ 1 (length (rest ll)))))) defn可以更简洁地写出来,但对于方案版本也是如此,所以我选择了最接近的方式原来的。

其他例子可以用同样的方式翻译。