Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you translate these 2 examples from Functional Languages 101 ? (Scheme -> Clojure)

Tags:

clojure

scheme

Got these examples I would like to understand but they are in Scheme. I would like them in Clojure :D

Example 1 - counting the length of a list


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

Exemple 2 - square each element of a list


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

Example 3 - the "map" function (as in map/reduce)


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

Motivation

The examples are from a presentation on Functional Programming someone else might be interested it: Functional Languages 101: What’s All the Fuss About?

Once you submit an answer, I'd like your agreement to post it as a comment at that presentation for Clojure people to understand the original code

like image 334
Belun Avatar asked Dec 13 '22 18:12

Belun


2 Answers

I have some stoff here: http://github.com/nickik/Essentials-of-PLs-in-Clojure/blob/master/src/EssentialsOfProgrammingLanguages/core.clj

Its all scheme to clojure stuff. You can download the source of the Essentials of Programming Languages-Book to have the Scheme code.


Here are your examples:

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

Note: clojure has a count function


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

Note you can not just make a 1:1 translation. The diffrence between how '() evals and so on.

Here are the most importend ones

  • (nil? (seq list)) not (null? lst) because '() is not nil in clojure
  • conj is better then cons you can make the function work with mure datastructures
  • (empty lst) is better then '() because (empty lst) keeps the type vector, list, record, structs or something else
like image 150
nickik Avatar answered Mar 09 '23 00:03

nickik


Length of a list:

(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

Square each element of a list:

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

Map:

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

See nickik's solution.

like image 34
Vijay Mathew Avatar answered Mar 08 '23 23:03

Vijay Mathew