change examples to use defn macro

This commit is contained in:
Pekka Laiho 2020-12-06 11:04:04 +07:00
parent 82c8f3b52b
commit 732b923552
3 changed files with 26 additions and 23 deletions

View File

@ -10,46 +10,49 @@
;;
;; Define commands
(def cmdAdd (fn (args) (apply + args)))
(def cmdDiv (fn (args) (apply / args)))
(def cmdMul (fn (args) (apply * args)))
(def cmdSub (fn (args) (apply - args)))
(def cmdHelp (fn (args) (str "Available commands: " (apply join ", " (keys cmdMap)))))
(defn cmdAdd (args) (apply + args))
(defn cmdDiv (args) (apply / args))
(defn cmdMod (args) (apply % args))
(defn cmdMul (args) (apply * args))
(defn cmdSub (args) (apply - args))
(defn cmdHelp (args) (str "Available commands: " (apply join ", " (keys cmdMap))))
;; And we define a hash-map for command lookups with minimum number of arguments
(def cmdMap {
"add": [cmdAdd 2]
"div": [cmdDiv 2]
"mod": [cmdMod 2]
"mul": [cmdMul 2]
"sub": [cmdSub 2]
"help": [cmdHelp 0]
})
;; Find the first command which starts with the given name, or null
(def findCmd (fn (name)
(defn findCmd (name)
(if (empty? name) null
(let (matches (filterh (fn (v k) (prefix? k name)) cmdMap))
(if (empty? matches) null
(get matches (first (keys matches))))))))
(get matches (first (keys matches)))))))
;; Split input by spaces, find command that matches the first word
;; and call it, giving the rest of the words as arguments.
(def parseInput (fn (inp)
(defn parseInput (inp)
(let (words (split " " inp) cname (first words) args (tail words) cmd (findCmd cname))
(if (null? cmd) (print "Unknown command, try 'help'.")
(if (< (len args) (second cmd)) (print (str "Give at least 2 arguments to " cname "."))
((first cmd) args))))))
((first cmd) args)))))
;; Define a file for readline and load it
(def readlineFile (str HOME "calc_history"))
(readline-load readlineFile)
;; Main loop: Read input from user, add it to readline, and parse it
(def mainLoop (fn () (let (inp (readline "> "))
(do (readline-add inp)
(readline-save readlineFile)
(print (str (parseInput inp) EOL))
true))))
(defn mainLoop ()
(let (inp (readline "[calc] "))
(do (readline-add inp)
(readline-save readlineFile)
(print (str (parseInput inp) EOL))
true)))
;; Run it
(loop mainLoop)

View File

@ -1,11 +1,11 @@
;; Functions to calculate factorial
;; Recursive version, not tail call optimized
(def recFact (fn (n) (if (< n 2) 1 (* n (recFact (dec n))))))
(defn recFact (n) (if (< n 2) 1 (* n (recFact (dec n)))))
;; Apply version
(def applyFact (fn (n) (if (< n 2) 1 (apply * (range 1 (inc n))))))
(defn applyFact (n) (if (< n 2) 1 (apply * (range 1 (inc n)))))
;; Add documentation
;; Add docstrings
(doc recFact "Calculate the factor of n recursively.")
(doc applyFact "Calculate the factor of n iteratively using apply.")

View File

@ -1,16 +1,16 @@
;; Functions to calculate Fibonacci numbers
;; Slow recursive version
(def slowFib (fn (n) (if (< n 2) n (+ (slowFib (- n 1)) (slowFib (- n 2))))))
(defn slowFib (n) (if (< n 2) n (+ (slowFib (- n 1)) (slowFib (- n 2)))))
;; Return the sum of the last 2 numbers in a sequence
(def sumOfLast (fn (l) (+ (last l) (penult l))))
(defn sumOfLast (l) (+ (last l) (penult l)))
;; Faster version, return vector of n numbers, tail call optimized
(def fibListRec (fn (n l) (if (< (len l) n) (fibListRec n (push l (sumOfLast l))) l)))
(def fibList (fn (n) (fibListRec n [0 1])))
(def fastFib (fn (n) (sumOfLast (fibList n))))
(defn fibListRec (n l) (if (< (len l) n) (fibListRec n (push l (sumOfLast l))) l))
(defn fibList (n) (fibListRec n [0 1]))
(defn fastFib (n) (sumOfLast (fibList n)))
;; Add documentation
;; Add docstrings
(doc slowFib "Return the nth number from the Fibonacci sequence recursively.")
(doc fastFib "Return the nth number from the Fibonacci sequence iteratively.")