(require "stdmacros.lasp") ; Aliases (def first head) (def rest tail) ; Increment a number by one (defn inc (x) (+ x 1)) ; Decrement a number by one (defn dec (x) (- x 1)) ; Is it nil? (defn nil? (arg) (= nil arg)) ; If a list is empty (defn empty? (coll) (nil? (head coll))) ; If all arguments are not equal (defn not= (& args) (not (apply = args))) ; The second item in a list (defn second (coll) (head (tail coll))) ; Modulus (defn mod (x y) (- x (* (/ x y) y))) ; Returns a function that does the opposite of the given function (defn complement (f) (fn (x) (not (f x)))) ; If a number is even (defn even? (x) (zero? (mod x 2))) ; If a number is odd (def odd? (complement even?)) ; If a number is zero (defn zero? (x) (= 0 x)) ; Length of a list (defn len (coll) (if (empty? coll) 0 (inc (len (tail coll))))) ; Gets an item in a list by index (defn nth (index coll) (if (zero? index) (head coll) (nth (dec index) (tail coll)))) ; Last item in list (defn last (coll) (nth (dec (len coll)) coll)) ; Reverses a list (defn reverse (coll) (reduce (fn (acc item) (cons item acc)) (list) coll)) ; Apply f to all items in list (defn map (f coll) (if (nil? (head coll)) coll (cons (f (head coll)) (map f (tail coll))))) ; Go through a list passing an accumulator and each item of the list through f ; f has the signature (acc item) (defn reduce (f acc coll) (if (empty? coll) acc (reduce f (f acc (head coll)) (tail coll)))) ; Filter a list of items based on a function (defn filter (f coll) (reduce (fn (acc item) (if (f item) (cons item acc) acc)) (list) (reverse coll))) ; Sum of all items in a list (defn sum (coll) (reduce + 0 coll)) ; Take n items from list (defn take (n coll) (if (zero? n) (list) (cons (head coll) (take (dec n) (tail coll))))) ; Drop x items from list (defn drop (num coll) (if (zero? num) coll (drop (dec num) (tail coll)))) ; Exclusive range (defn range (from to) (if (>= from to) (list) (cons from (range (inc from) to)))) ; Highest value in list (defn max (coll) (reduce (fn (acc item) (if (< acc item) item acc)) (head coll) (tail coll))) ; Lowest value in list (defn min (coll) (reduce (fn (acc item) (if (> acc item) item acc)) (head coll) (tail coll))) ; The naming suggests that it is an implementation detail of `every`, that ; needs to be named to allow recursion. If it has value in itself, it should be ; renamed and documented. (defn every* (n coll acc) (if (empty? coll) acc (every* n (drop n coll) (cons (first coll) acc)))) ; Every Nth item in list (defn every (n coll) (reverse (every* n coll (list)))) ; Takes a method from Ruby-land and returns a Lasp function (defn ruby-method (meth) (fn (arg) (. arg meth))) ; Conversion functions (def text->list (ruby-method :chars)) ; Convert text to list (def list->text (ruby-method :join)) ; Convert list to text (def ->text (ruby-method :to_s)) ; Convert to text (def ->integer (ruby-method :to_i)) ; Convert to int (def ->decimal (ruby-method :to_f)) ; Convert to decimal ; Create a string by concatenating all arguments (defn text (& args) (list->text args)) ; Pass a value in order through a list of functions (defn pipe (item & fns) (if (empty? fns) item ; Note that you need to take special care when recursing with rest ; arguments, hence the use of apply. (apply pipe (cons ((head fns) item) (tail fns))))) ; Reverses text (defn reverse-text (text) (pipe text text->list reverse list->text)) ; Reads an answer to a question (defn prompt (question) (print question) (readln)) ; Print with a newline (defn println (& args) (print (+ (list->text args) "\n")))