Можете ли вы перевести эти 2 примера из «Функциональных языков 101»? (Схема -> Clojure) - PullRequest
4 голосов
/ 15 октября 2010

Есть эти примеры, которые я хотел бы понять, но они есть в Схеме.Я хотел бы, чтобы они были в 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" (как на карте / уменьшить)


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

Curried "map"


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

Мотивация

Примеры взяты из презентации по функциональному программированию, которой может заинтересоваться кто-то другой: Функциональные языки 101: Что всеО суете?

Как только вы отправите ответ, я хотел бы, чтобы вы согласились опубликовать его в качестве комментария на этой презентации, чтобы люди Clojure могли понять исходный код

Ответы [ 4 ]

6 голосов
/ 15 октября 2010

У меня есть кое-что здесь: http://github.com/nickik/Essentials-of-PLs-in-Clojure/blob/master/src/EssentialsOfProgrammingLanguages/core.clj

Все это замыкание.Вы можете скачать исходный код Основы языков программирования, чтобы иметь код Схемы.


Вот ваши примеры:

(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.Разница между тем, как '() исчезает и т. Д.

Вот наиболее важные из них

  • (nil? (Seq list)) not (null? Lst), потому что' () это не ноль в clojure
  • con лучше, чем минусы, вы можете заставить функцию работать с структурами данных mure
  • (пустой lst) лучше, чем '(), потому что (пустой lst) сохраняет типвектор, список, запись, структуры или что-то еще
5 голосов
/ 15 октября 2010

Длина списка:

(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)

map2:

См. Решение Никика.

2 голосов
/ 15 октября 2010

И еще clojurey перевод map:

(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)))

В идиоматическом замыкании обычно вы используете, что ноль является логическим ложным.

(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)))))))
0 голосов
/ 15 октября 2010

define равно def в ближайшем будущем, lambda равно fn, аргументы функции записываются как векторы [], а не списки (), null? равно empty, car равно first, cdr - это rest, а регистр по умолчанию для cond задается с помощью :else, а не #t.

Итак, для вашего первого примера мы получим:

(def length
  (fn [ll]
    (cond
      (empty? ll) 0
      :else (+ 1 (length (rest ll))))))

Это можно записать немного более кратко, используя defn вместо def и fn, но то же самое верно для версии схемы, поэтому я выбрал путь, наиболее близкий к оригиналу.

Другие примеры можно перевести так же.

...