A complete list of the available functions can be found in the README.
Since Läsp is very similar to Clojure, you can get pretty decent syntax
highlighting by just setting your editor to treat .lasp files as .clj
In this document output is shown with ;; and normal comments with ;.
; Number types
1
1.5
; Booleans and nil
true
false
nil
; Text
"hello world!" ;; => "hello world!"
; Symbol-style text (not its own type)
:hey ;; => "hey"
; Lists
(list 1 2 3) ;; => (1 2 3)
(list) ;; => (); inc is a function that increments its argument, and 1 is the single argument
(inc 1) ;; => 2
; Outputting to the terminal
(println "hello world!")
;; hello world!
;; => nil
; Simple maths functions take any number of arguments
(/ 20 2) ;; => 10
(+ 1 3 5) ;; => 9
(* 2 5 6 10) ;; => 600
; Equality operators also do
(= 1 5) ;; => false
(= 3 3 3) ;; => true
(> 3 2 1 0) ;; => true
; Boolean inversion
(not true) ;; => false(head (list 1 2 3)) ;; => 1
(first (list 1 2 3)) ;; => 1
(tail (list 1 2 3)) ;; => (2 3)
(rest (list 1 2 3)) ;; => (2 3)
(cons 0 (list 1 2 3)) ;; => (0 1 2 3)
(nth 1 (list 1 2 3)) ;; => 2
(nth 3 (list 1 2 3)) ;; => nil
; get does the same as nth on lists (although implemented differently)
(get 1 (list 1 2 3)) ;; => 2
(get 3 (list 1 2 3)) ;; => nil
; assoc returns a new array with the specified index updated
(assoc (list 1 2 3) 0 "one") ;; => ("one" 2 3)
(last (list 1 2 3)) ;; => 3
(take 2 (list 1 2 3)) ;; => (1 2)
(drop 2 (list 1 2 3)) ;; => (3)
(max (list 1 3 2)) ;; => 3
(reverse (list 1 2 3)) ;; => (3 2 1)
; Ranges
(range 1 10) ;; => (1 2 3 4 5 6 7 8 9); Create a dict
(dict :one 1 :two 2) ;; => {"one" 1, "two" 2}
; get also works with dicts
(get :one (dict :one 1 :two 2)) ;; => 1
; assoc works with dicts too
(assoc (dict :one 1 :two 2) :three 3) ;; => {"one" 1, "two" 2, "three" 3}
; dissoc removes values
(dissoc (dict :one 1 :two 2) :one) ;; => {"two" 2}; Apply a function to all items in a list
(map inc (list 1 2 3)) ;; => (2 3 4)
; Accumulate a value with a function
; The function (here +) will receive a memo (the running total)
; and each item in the list in order. The 0 is the starting value
(reduce + 0 (list 1 2 3)) ;; => 6
; This is how sum is implemented
(sum (list 1 2 3)) ;; => 6
; The starting value is important.
(reduce * 1 (list 1 2 3)) ;; => 6
; Filtering
(filter odd? (list 1 2 3)) ;; => (1 3); Define and evaluate a variable
(def x (list 1 2 3))
x ;; => (1 2 3)
; Use it in a function
(sum x) ;; => 6(if (< 4.9 5)
"under"
"over")
;; => "under"
(if (< 5.1 5)
(println "yep!")
(println "nope!"))
;; nope!
;; => nil; A function has 2 forms, one with the parameters and one with the body.
; Here's a function that adds 10 to its argument
(fn (x) (+ 10 x))
; You can call it just like one of the named functions by placing the entire
; fn-form at the first position
((fn (x) (+ 10 x)) 50) ;; => 60
; You can give it a name by defining it
(def add-ten (fn (x) (+ 10 x)))
(add-ten 50) ;; => 60
(def square (fn (x) (* x x)))
(square 5) ;; => 25
; Arity is enforced when calling a function, this yields an error:
(square 5 2) ;; !> wrong number of arguments (2 for 1)
; Rest arguments are passed in as a list to the binding after the &
(def last-argument
(fn (& args)
(last args)))
(last-argument 1 2) ;; => 2
(last-argument 1 2 3) ;; => 3
; You can also have mandatory positional arguments and rest arguments at the same time
(def add-first-two
(fn (a b & args)
(+ a b)))
(add-first-two 1 2) ;; => 3
(add-first-two 1 2 3) ;; => 3
(add-first-two 1) ;; !> wrong number of arguments (1 for 2+)
; Defining a function is a very common thing to do, therefore there is a shorthand.
; This will do the same thing as the example above:
(defn add-first-two
(a b & args)
(+ a b)); The list we will operate on
(def fives (list 1 5 2 3 5 8 5)) ; 5 occurs 3 times.
(reduce ; Reduce takes a function(1), a starting value(2) and a list(3).
(fn (acc x) ; (1) The function in turn takes an accumulator and an item in the list.
(if (= x 5) ; If the item is five:
(inc acc) ; We increment the accumulator and move on to the next item.
acc)) ; Otherwise we return the total as is.
0 ; (2) We start counting from 0
fives) ; (3) We operate over the previously defined `fives` list.
;; => 3; Print one row in the pyramid
(defn print-row
(length)
(println (* "#" length))) ; We use the fact that the host platform (Ruby) can multiply text
; Print the entire pyramid
(defn print-pyramid
(height current-width)
(if (= current-width height)
nil
(do
(print-row current-width)
(print-pyramid height (inc current-width)))))
; Do it!
(print-pyramid 10 1)
;; #
;; ##
;; ###
;; ####
;; #####
;; ######
;; #######
;; ########
;; #########; Prepend a dot to the method name and pass the object as the first argument to
; call a Ruby method.
(.to_i "01011101" 2) ;; => 93
(def parse_binary (fn (bin) (.to_i bin 2)))
(parse_binary "01011101") ;; => 93Since Läsp code is just lists, it is quite easy to write code that restructures
those lists before they are executed - this is what macros do. If you would
like to make a function that takes a form that performs maths in a more natural
order like (1 + 2), then you can accomplish it with macros:
(def infix
(macro (form)
(list (second form) (first form) (last form))))
; This will be restructured to `(+ 4 5)` before it is run.
(infix (4 + 5)) ; => 9Refer to the macro section in the documentation for a more detailed explanation.