Skip to content

Instantly share code, notes, and snippets.

@mveytsman
Last active November 24, 2015 12:45
Show Gist options
  • Save mveytsman/9d77ab50a92e9a592d29 to your computer and use it in GitHub Desktop.
Save mveytsman/9d77ab50a92e9a592d29 to your computer and use it in GitHub Desktop.
expression problem in clojure
(ns expression-problem)
;; Shapes have area
(defprotocol Areable
(area [this]))
;; We have circles
(defrecord Circle [radius])
;; Circles have area
(extend-type Circle
Areable
(area [{radius :radius}] (* Math/PI radius radius)))
(def my-circle (Circle. 5))
(assert (== (area my-circle) (* Math/PI 25)))
;; We have squares
(defrecord Square [side])
;; Squares have area
(extend-type Square
Areable
(area [{side :side}] (* side side)))
(def my-square (Square. 5))
(assert (== (area my-square)) 25)
;; Now we want to add perimeters
(defprotocol Perimeterable
(perimeter [this]))
;; Circles and Squares have perimeters
(extend-protocol Perimeterable
Circle
(perimeter [{radius :radius}] (* 2 Math/PI radius))
Square
(perimeter [{side :side}] (* 4 side)))
(assert (== (perimeter my-circle) (* 10 Math/PI)))
(assert (== (perimeter my-square) 20))
;; Now we want to add triangles
(defrecord Triangle [a b c])
;; Triangles have areas and perimeters
(extend-type Triangle
Areable
;; The hardest part of solving the expression problem in Clojure is looking up highschool geometry
;; Heron's formula
(area [{:keys [a b c]}]
(let [s (/ (+ a b c) 2)]
(Math/sqrt (* s (- s a) (- s b) (- s c)))))
Perimeterable
(perimeter [{:keys [a b c]}] (+ a b c)))
(def my-triangle (Triangle. 3 4 5))
(assert (== (area my-triangle) 6.
(assert (== (perimeter my-triangle) 12))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment