(defun plus (a b)
(+ a b))
;; => PLUS
(plus 2 5)
;; => 7
- functions are defined with the macro
defun
- the name of a function is a symbol that's the second form in the list
- the arguments to the function are a list that is the third form in the list
- everything afterwards is the body of the function
(defun another-plus (a b)
(setf a 1337)
(+ a b))
;; => ANOTHER-PLUS
(another-plus 2 5)
;; => 1342
- you can have multiple forms within the function body - there's implicitly a block around them all.
- the final form in the function body is what the function evaluates to.
(defun plus (a b c)
(+ a b c))
;; => PLUS
(plus 2 5 11)
;; => 18
(plus 2 5)
;; ERROR!!!
- there is no function overload. If we define a function with the same name, we just redefine existing function.
- there is no currying so if don't pass enough arguments to a function, it will just blow up
(defun plus (a b &optional c)
(if c (+ a b c)
(+ a b)))
;; => PLUS
(plus 3 2 1)
;; => 6
(plus 3 2)
;; => 5
- Functions can have optional arguments denoted by a
&optional
prefix.
- If you want to call the function without the optional parameter implicitly, just pass the nil
(defun plus (a b &optional (c 0))
(+ a b c))
;; => PLUS
(plus 3 2)
;; => 5
(plus 3 2 1)
;; => 6
- You can provide default value for the optional argument by wrapping it in the list where the second form is the default value
(defun say-hello (&optional (name "anon" name-supplied-p))
(format nil "Hello ~a (~a)" name name-supplied-p))
;; => SAY-HELLO
(say-hello)
;; => "Hello anon (NIL)"
(say-hello "DAVE")
;; => "Hello DAVE (T)"
(say-hello "anon")
;; => "Hello anon (T)"
- a third item in the
&optional
argument list is a flag to tell you whether an optional argument was actually passed
- this is good to distinguish between the default argument being used and the same value being passed in.
(defun plus (&optional (a 0 a-p) (b 0 b-p))
(princ a-p)
(princ b-p)
(+ a b))
;; => PLUS
(plus)
;; => NILNIL
;;
;; 0
(plus 2)
;; => TNIL
;;
;; 2
(plus 2 2)
;; => TT
;;
;; 4
- You can have multiple optional arguments with the supplied flag bindings
- All the arguments after
&optional
become optional
(defun plus (a b &rest rest)
(+ a b (length rest)))
;; => PLUS
(plus 1 2)
;; => 3
(plus 1 2 "a" "b" "c")
;; => 6
- there is
&rest
prefix which collects all other arguments and puts them into a list
(defun hello-world (name &key shouty rude)
(let* ((basic (format nil "Hello ~a" name))
(postfix (if rude ", you pie!" "."))
(greeting (format nil "~a~a" basic postfix)))
(if shouty
(string-upcase greeting)
greeting)))
;; => HELLO-WORLD
(hello-world "bob")
;; => "Hello bob."
(hello-world "bob" :shouty t)
;; => "HELLO BOB."
(hello-world "bob" :rude t)
;; => "Hello bob, you pie!"
(hello-world "bob" :rude t :shouty t)
;; => "HELLO BOB, YOU PIE!"
- keyword arguments are introduced by using
&key
- they are a way of providing named arguments in any order
- keywords have to be used if it is a keyword argument
- the
&key
appears only once - everything afterwards is a keyword argument
- they default to
nil
but can have a default supplied in the same manner as &optional
arguments
(defun hello-everyone (&rest names &key shouty rude)
(let* ((basic (format nil "Hello ~a" names))
(postfix (if rude ", you pie!" "."))
(greeting (format nil "~a~a" basic postfix)))
(if shouty
(string-upcase greeting)
greeting)))
;; => HELLO-EVERYONE
(hello-everyone :rude t :shouty t)
;; => "HELLO (RUDE T SHOUTY T), YOU PIE!"
- You can't combine
rest
arguments with named arguments. You can see here that :rest
is "slurping" our keywords and the keywords are still being used.
(defun plus (a b)
"Plus some numbers"
(+ a b))
;; => PLUS
(documentation 'plus 'function)
;; => "Plus some numbers"
- You can add handy documentation to your functions