Skip to content

Instantly share code, notes, and snippets.

@JoshuaSkootsky
Last active November 12, 2019 04:16
Show Gist options
  • Save JoshuaSkootsky/53402d8c528e36e8ea463d5fc106c652 to your computer and use it in GitHub Desktop.
Save JoshuaSkootsky/53402d8c528e36e8ea463d5fc106c652 to your computer and use it in GitHub Desktop.
; This is a file I had lying around where I went through the beginning of SCIP (A scheme book) and translated it
; into Clojure as I went. Perfect for a gist?
; Joshua Skootsky, 2016
; See xkcd #312
Clojure : Scheme
def : define var
defn : define function
Clojure:
(defn square "Docstring - squares a number" [variable_1_to_be_squared]
(* variable_1_to_be_squared variable_1_to_be_squared ))
Scheme:
(define (square x) (* x x))
Clojure:
(defn square [x] (* x x))
lojure-noob.core=> (defn square [x] (* x x))
#'clojure-noob.core/square
clojure-noob.core=> (square 6)
36
clojure-noob.core=> (defn sum-of-squares [x y] "Sum of two squares"
#_=> (+ (square x) (square y)))
#'clojure-noob.core/sum-of-squares
clojure-noob.core=> (sum-of-squares 3 4)
25
clojure-noob.core=> (defn f [a] "Does something with sum of squares"
#_=> (sum-of-squares (+ a 1) (* a 2)))
#'clojure-noob.core/f
clojure-noob.core=> (f 5)
136
Scheme:
(define (abs x)
(cond ((> x 0) x)
((= x 0) 0)
((< x 0) (- x))))
Clojure:
(defn abs [x] "Takes the absolute value of x"
(cond (> x 0) x
(= x 0) 0
(< x 0) (- x)))
Scheme:
(define (abs x)
(cond ((< x 0) (- x))
(else x)))
Clojure:
(defn abs [x] "Gives absolute value of x"
(cond
(< x 0) (- x)
:else x))
Scheme:
(define (abs x)
(if (< x 0)
(- x) x))
Clojure:
(defn abs [x] "Gives absolute value of x"
(if (< x 0)
(- x) x))
Scheme:
(define (a-plus-abs-b a b)
((if (> b 0) + -) a b))
Clojure:
(defn a-plus-abs-b [a b]
((if (> b 0) + -) a b))
Newton's method
Scheme:
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
(define (improve guess x)
(average guess (/ x guess)))
(define (average x y)
(/ (+ x y) 2))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
Clojure:
(defn sqrt-iter [guess x] "Iteratively calculate square root x based on a guess and Newton's method"
(if (good-enough? guess x) guess
(sqrt-iter (improve guess x) x)
)
)
(defn improve [guess x] "Improves a guess of x"
(average guess (/ x guess)))
(defn average [x y] "Takes the average of x and y"
(/ (+ x y) 2))
(defn good-enough? [guess x] "Checks to see if a guess is good enough"
(< (abs (- (square guess) x)) 0.001))
Copy into REPL:
;;;; Square root approximation method
(defn abs [x] "Gives absolute value of x"
(if (< x 0)
(- x) x))
(defn square [x] (* x x))
(defn good-enough? [guess x] "Square guess to see if it could be the square root of x"
(< (abs (- (square guess) x)) 0.001))
(defn average [x y] "Calculate mean of two terms, x and y"
(/ (+ x y) 2))
(defn improve [guess x] "Improves a guess (square root of x?) by averaging with x/guess"
(average guess (/ x guess)))
(defn sqrt-iter [guess x] "Iteratively calculate square root x based on a guess and Newton's method"
(if (good-enough? guess x) guess
(sqrt-iter (improve guess x) x)))
(defn sqrt [x] "Calculates Square root of x"
(sqrt-iter 1.0 x))
Fibonacci
(defn fib [x] "Returns fib x"
(cond (= x 2) x
(= x 1) x
:else
(+
(fib (- x 1))
(fib (- x 2)))))
Memoize Fibonacci:
(def memo-fib (memoize fib))
; memoizes for future use - first call is still slow
Recursive fib?
(defn fib [x] "Returns fib x"
(cond (= x 2) x
(= x 1) x
:else
(+
(fib (- x 1))
(fib (- x 2)))))
You want memoized fib to call the memoized fib
(def fib (memoize
(fn [n]
(if (>= 1 n) n
(+
; fib is the memoized function
(fib (- n 1))
(fib (- n 2)))))))
http://danmidwood.com/content/2013/02/24/exploring-clojure-memoization.html
This is an important pattern.
1.6
Alyssa P. Hacker
if and cond
Can if be defined in terms of cond?
Scheme:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
Clojure version:
(defn new-if [predicate then-clause else-clause] "Is this an if?"
(cond predicate then-clause
:else
else-clause))
;; seemingly this works
Alyssa writes a new part of the square root program:
Scheme:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
Clojure:
(defn sqrt-iter [guess x] "Uses a conditional if by Alyssa P. Hacker"
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
problems using Alyssa's new-if:
clojure-noob.core=> (sqrt 9)
StackOverflowError clojure.lang.Numbers$DoubleOps.multiply (Numbers.java:595)
;;;; Interesting!
; In Alyssa's new-if procedure, an infinite recursive loop occurs because the
; sqrt-iter procedure is evaluated, which evaluates its recursed sqrt-iter
; procedure, which evaluates its recursed sqrt-iter, and so on.
;
; The top-level sqrt-iter procedure in Alyssa's new-if procedure has no way
; to expand to its primitive reductions.
;
; The new-if's recursion problem didn't happen during Eva's two demonstration
; runs because the evaluated arguments were at their primitive reductions.
;
; The infinite recursive loop problem doesn't occur with if expressions
; because the consequent and alternative expressions behave as single
; expressions. The (sqrt-iter (improve guess x) x) alternative expression
; is evaluated only one time and not multiple times recursively as is
; done for conditional expressions.
https://github.com/raywritescode/sicp/blob/master/ch01/exercises/exercise-1.6.scm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment