(def VAT "value added tax rate in percent"8.1)
(defn hypot
"Calculates the hypothenuse given the rectangular triangle's legs a and b." [a b]
(Math/sqrt (+ (Math/pow a 2) (Math/pow b 2))))
(hypot34) ; 5.0
Retrieve a docstring programmatically:
(doc VAT) ; value added tax rate in percent(doc hypot)
;; Calculates the hypothenuse given the rectangular triangle's legs a and b.
Provide validations of arguments and the return value using pre and post
conditions, respectively:
(defn hypot [a b]
{:pre [(> a 0) (> b 0)]
:post [(> % a) (> % b)]}
(Math/sqrt (+ (Math/pow a 2) (Math/pow b 2))))
(hypot34) ; 5.0(hypot30) ; Assert failed: (> b 0)
The return value is available as % in the post condition.
Exercises
Acceleration and Speed
Write a multi-arity function end-speed to compute the speed given an
acceleration a in m/s², a time indication t in s, and—optionally—a
starting speed v0 in m/s. Document the function with the formula in a
docstring.
Hint: Use the formula v=v0+at. The lower-arity function shall call the
higher-arity function.
Write a multimethod bonus that calculates each employee’s bonus based on the
following rules:
Engineers earning more than 100000 get a bonus of 10% of their salary.
Engineers earning up to 100000 get a bonus of 15% of their salary.
Sales people get a bonus of 10% of their salary and 1% of their revenue.
Interns get a fixed bonus of 2000.
All other employees get a bonus of 0.
Hint: The dispatch function shall differentiate between low- and high-earning
engineers. Do not explicitly return :default from the dispatch method for all
other employees.
Write a tail-recursive function (fib [n]) that computes the nth Fibonacci
number.
Hint: The nth Fibonacci number is defined as the sum of its two predecessors.
The first two Fibonacci numbers are 1 and 1. Use loop and recur to
implement the function.
Test: (fib 0) and (fib 1) shall return 1, (fib 10) shall return 89,
and (fib 45) shall return 1836311903—and finish within within milliseconds
(use (time (fib 45)) to check).
Solution
(defn fib [n]
(loop [a 1 b 1 i n]
(if (= i 0)
a
(recur b (+ a b) (- i 1)))))
Blob Eats Blob
Given the following data:
(def red {:weight80:strength50})
(def blue {:weight90:strength40})
(def green {:weight70:strength35})
(def black {:weight0:strength0})
Write a function (merge-blobs [a b]) which simulates a fight between the two
blobs a and b. The blob with the higher strength eats up the blog with the
lower strength, thereby gaining the defeated blob’s weight and 10% of its
strength. Test for the following conditions:
Preconditions: Both blobs have a positive weight and strength.
Postcondition: The returned weight is higher than the weight of any given
blob.
Hint: Use :pre and :post to enforce the conditions.
Test: (merge-blobs red blue) shall return {:weight 170 :strength 54}, and
(merge-blobs green black) shall throw an assertion error.
Solution
(def red {:weight80:strength50})
(def blue {:weight90:strength40})
(def green {:weight70:strength35})
(def black {:weight0:strength0})
(defn merge-blobs [a b]
{:pre [(> (:weight a) 0)
(> (:weight b) 0)
(> (:strength a) 0)
(> (:strength b) 0)]
:post [(> (:weight %) (:weight a))
(> (:weight %) (:weight b))]}
(if (> (:strength a) (:strength b))
{:weight (+ (:weight a) (:weight b))
:strength (+ (:strength a) (* 0.1 (:strength b)))}
{:weight (+ (:weight a) (:weight b))
:strength (+ (* 0.1 (:strength b)) (:strength a))}))