Skip to content

Instantly share code, notes, and snippets.

@brianstorti
Last active December 17, 2015 23:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianstorti/5692240 to your computer and use it in GitHub Desktop.
Save brianstorti/5692240 to your computer and use it in GitHub Desktop.
; sum the square of the parameters.
(def add-squares
(fn [& args]
(apply + (map * args args))))
(add-squares 1 2 5)
; factorial without iteration/recursion.
(def factorial
(fn [number]
(apply * (range 1 (inc number)))))
(factorial 5)
(take 2 [1 2 3])
(repeat 4 [1])
(interleave [1 2] [4 5])
(drop 1 (drop-last 1 [1 2 3]))
(flatten [1 2 [3 4]])
(partition 2 [1 2 3 4 5 6])
(every? even? [2 4 6])
(def prefix-of
(fn [candidate sequence]
(= (take (count candidate) sequence) candidate)))
(prefix-of [1 2] [1 2 3 4]) ; true
(prefix-of [1 2 3 1] [1 2 3 4]) ; false
(def tails
(fn [seq]
(map drop
(range (inc (count seq)))
(repeat (inc (count seq)) seq))))
(tails [1 2 3 4])
(repeat (inc (count [1 2 3 4])) [1 2 3 4])
(range (inc (count [1 2 3 4])))
{:a 5, :b "2"} ; a map. in clojure, commas are white spaces, the reader ignores them
(get {:a 5, :b "2"} :a) ; unusual
(:b {:a 3, :b 2}) ; keywords act like a function when places as the first element of a list
({:a 1 :b 2} :a)
(apply hash-map [:x 1 :y 2])
(def do-something-to-map
(fn [function]
(function {:a "a value", :b "another value"})))
(do-something-to-map :a)
(do-something-to-map count)
(assoc {:a 1} :b 2, :c 3, :d 4)
(assoc {:a 1} :a 2)
(merge {:a 1} {:b 2} {:c 3})
(dissoc {:a 1 :b 2 :c 3} :b :a)
; minimal class
(def Point
(fn [x y]
{:x x,
:y y}))
; three ways to implement an "x" accessor
(def x
(fn [this]
(get this :x)))
(def x
(fn [this] (:x this)))
(def x :x)
(def y :y)
(x (Point 1 2)) ; call the accessor to get the value of "x"
(def Point
(fn [x y]
{:x x,
:y y,
:__class_symbol__ 'Point}))
(def class-of :__class_symbol__)
(class-of (Point 1 2))
(def shift
(fn [point x-inc y-inc]
(Point (+ (x point) x-inc)
(+ (y point) y-inc))))
(shift (Point 1 200) -2 -100)
; add function not using shift
(def add
(fn [point1 point2]
(Point (+ (x point1) (x point2)),
(+ (y point1) (y point2)))))
(add (Point 1 3) (Point 3 4))
; using shift
(def add-with-shift
(fn [point1 point2]
(shift point1 (x point2) (y point2))))
(add-with-shift (Point 1 3) (Point 3 4))
(def make
(fn [type & args]
(apply type args)))
(make Point 1 1)
(def Triangle
(fn [point1 point2 point3]
{:point1 point1
:point2 point2
:point3 point3
:__class_symbol__ 'Triangle}))
(def right-triangle (Triangle (Point 0 0)
(Point 0 1)
(Point 1 0)))
(def equal-right-triangle (Triangle (Point 0 0)
(Point 0 1)
(Point 1 0)))
(def different-triangle (Triangle (Point 0 0)
(Point 0 10)
(Point 10 0)))
(def equal-triangles?
(fn [source target]
(and
(= (:point2 source) (:point2 target))
(= (:point3 source) (:point3 target))
(= (:point1 source) (:point1 target)))))
(def equal-triangles? =)
(equal-triangles? right-triangle right-triangle)
(equal-triangles? right-triangle equal-right-triangle)
(equal-triangles? right-triangle different-triangle)
; there are no repeated points
(def valid-triangle?
(fn [& points]
(= points (distinct points))))
(valid-triangle? (Point 1 1) (Point 1 2) (Point 1 3))
(def send-to
(fn [object message & args]
(apply (message (:__methods__ object)) object args)))
(def Point
(fn [x y]
{:x x
:y y
:__class_symbol__ 'Point
:__methods__ {
:class :__class_symbol__
:x :x
:y :y
:shift
(fn [this x-inc y-inc]
(make Point (+ (send-to this :x) x-inc)
(+ (send-to this :y) y-inc)))
}}))
(def point (make Point 1 2))
(:shift (:__methods__ point))
(print ((:shift (:__methods__ point)) point -2 -3))
(def Point {
:__own_symbol__ 'Point
:__instance_methods__
{
:add-instance-values
(fn [this x y]
(assoc this :x x :y y))
:shift
(fn [this xinc yinc]
(make Point (+ (:x this) xinc)
(+ (:y this) yinc)))
}
})
(def make
(fn [class & args]
(let [seeded { :__class_symbol__ (:__own_symbol__ class) }
constructor (:add-instance-values
(:__instance_methods__ class))]
(apply constructor seeded args))))
(def point (make Point 1 2))
(def send-to
(fn [object message & args]
;; the "eval" is needed because we get the *symbol* Point, not the value this symbol is bound to
(let [class (eval (:__class_symbol__ object))
method (message (:__instance_methods__ class))]
(apply method object args))))
(send-to point :shift -2 -3)
(def method-from-name
(fn [message class]
(message (:__instance_methods__ class))))
(def apply-message-to
(fn [class instance message args]
(apply (method-from-name message class) instance args)))
(def make
(fn [class & args]
(let [seeded { :__class_symbol__ (:__own_symbol__ class) }]
(apply-message-to class seeded :add-instance-values args))))
(def send-to
(fn [object message & args]
(let [class (eval (:__class_symbol__ object))]
(apply-message-to class object message args))))
(send-to (make Point 5 5) :shift -2 -3)
(def class-from-instance
(fn [instance]
(eval (:__class_symbol__ instance))))
(def Point
{
:__own_symbol__ 'Point
:__instance_methods__
{
:add-instance-values (fn [this x y]
(assoc this :x x :y y))
:class-name :__class_symbol__
:class (fn [this] (class-from-instance this))
:shift (fn [this xinc yinc]
(make Point (+ (:x this) xinc)
(+ (:y this) yinc)))
:add (fn [this other]
(send-to this :shift (:x other)
(:y other)))
}
})
(def point (make Point 1 2))
(send-to point :class-name)
(send-to point :class)
(def Holder
{
:__own_symbol__ 'Holder
:__instance_methods__
{
:add-instance-values (fn [this held]
(assoc this :held held))
}
})
(def method-from-message
(fn [message class]
(message (:__instance_methods__ class))))
; search for accessor method, if it's not found, get the "variable"
(def apply-message-to
(fn [class object message args]
(let [method (or (method-from-message message class)
message)]
(apply method object args))))
(def send-to
(fn [object message & args]
(let [class (eval (:__class_symbol__ object))]
(apply-message-to class object message args))))
(send-to (make Holder "stuff") :held)
;; Inheritance
(declare class-from-instance send-to make)
(def Point
{
:__own_symbol__ 'Point
:__superclass_symbol__ 'Anything ;; <<= New
:__instance_methods__
{
:add-instance-values (fn [this x y]
(assoc this :x x :y y))
:shift (fn [this xinc yinc]
(make Point (+ (:x this) xinc)
(+ (:y this) yinc)))
:add (fn [this other]
(send-to this :shift (:x other)
(:y other)))
}
})
(def Anything
{
:__own_symbol__ 'Anything
:__instance_methods__
{
:add-instance-values identity
:class-name :__class_symbol__
:class (fn [this] (class-from-instance this))
}
})
(def class-symbol-above
(fn [class-symbol]
(assert (symbol? class-symbol))
(:__superclass_symbol__ (eval class-symbol))))
(def recursive-function
(fn [class-symbol]
(if (nil? class-symbol)
nil
(cons class-symbol
(recursive-function (class-symbol-above class-symbol))))))
(recursive-function 'Point)
(def lineage-1
(fn [class-symbol so-far]
(if (nil? class-symbol)
so-far
;; "recur" tell the JVM you have a tail recursion, so it can be optimized
(recur (class-symbol-above class-symbol)
(cons class-symbol so-far)))))
(def lineage
(fn [class-symbol]
(lineage-1 class-symbol [])))
(lineage 'Point)
(def factorial
(fn [number]
(if (or (= number 1) (= number 0))
1
(* number (factorial (dec number))))))
(factorial 0)
(factorial 1)
(factorial 5)
(def factorial-tail-recursion
(fn [number so-far]
(if (or (= number 1) (= number 0))
so-far
(recur (dec number)
(* so-far number)))))
(def factorial
(fn [number]
(factorial-tail-recursion number 1)))
(factorial 5)
(factorial 0)
(factorial 1)
(def recursive-add
(fn [numbers so-far]
(if (empty? numbers)
so-far
(recur (rest numbers)
(+ so-far (first numbers))))))
(recursive-add [1 2 3 4 5 6] 0)
(def recursive-multiply
(fn [numbers so-far]
(if (empty? numbers)
so-far
(recur (rest numbers)
(* so-far (first numbers))))))
(recursive-multiply [1 2 3 4] 1)
(def recursive-function
(fn [operation numbers so-far]
(if (empty? numbers)
so-far
(recur operation
(rest numbers)
(operation so-far (first numbers))))))
(recursive-function + [1 2 3 4] 0)
(recursive-function * [1 2 3 4] 1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment