LISP - Functions
Lisp - Functions
Section titled “Lisp - Functions”Functions are the fundamental building blocks of any Lisp program. They are self-contained units of code that perform a specific task. In Lisp, functions are first-class citizens, meaning they can be stored in variables, passed as arguments to other functions, and returned as values, just like any other data type like numbers or strings.
Defining Functions with defun
Section titled “Defining Functions with defun”The defun macro is used to define a named function. Its basic syntax is:
(defun function-name (parameter-list) "Optional documentation string." function-body)function-name: A symbol that names the function.parameter-list: A list of symbols for the function’s arguments.documentation string: An optional string describing what the function does. This is a best practice and can be retrieved with(documentation 'function-name 'function).function-body: One or more Lisp expressions. The value of the last expression evaluated is implicitly returned as the function’s result.
Example: Area of a Circle
Section titled “Example: Area of a Circle”Let’s define a function to calculate the area of a circle. Note the use of the built-in constant pi.
(defun circle-area (radius) "Calculates the area of a circle given its radius." (* pi radius radius))
;; Call the function and print the result(format t "Area of a circle with radius 10: ~f~%" (circle-area 10))Output
Section titled “Output”Area of a circle with radius 10: 314.15927Advanced Parameter Lists
Section titled “Advanced Parameter Lists”Lisp functions support highly flexible parameter lists using lambda list keywords.
&optional: For optional arguments that can have default values.&rest: For variadic functions that can accept any number of additional arguments.&key: For arguments that are specified by name, not position.
Example: Flexible Greeting Function
Section titled “Example: Flexible Greeting Function”(defun greet (name &key (greeting "Hello") (punctuation "!")) "Greets a person with customizable options." (format nil "~a, ~a~a" greeting name punctuation))
;; --- Usage ---
;; Default arguments(print (greet "Alice"))
;; Override one keyword argument(print (greet "Bob" :greeting "Hi"))
;; Override all keyword arguments (order doesn't matter)(print (greet "Charlie" :punctuation "." :greeting "Good morning"))Output
Section titled “Output”"Hello, Alice!""Hi, Bob!""Good morning, Charlie."Return Values
Section titled “Return Values”As mentioned, a function implicitly returns the value of its last evaluated expression. For early returns from inside a block (like a loop), you can use return-from.
Example: Explicit Return with return-from
Section titled “Example: Explicit Return with return-from”(defun find-first-odd (numbers) "Returns the first odd number in a list, or NIL if none are found." (dolist (num numbers) ; dolist implicitly creates a block named nil (when (oddp num) (return-from find-first-odd num))) ;; This part is only reached if the loop completes without finding an odd number. nil)
(print (find-first-odd '(2 4 5 6 7)))(print (find-first-odd '(2 4 6 8)))Output
Section titled “Output”5NILExplanation
Section titled “Explanation”The defun macro automatically wraps the function body in a block with the same name as the function. (return-from find-first-odd num) immediately exits the find-first-odd function and returns the value of num.
Higher-Order Functions and Lambda
Section titled “Higher-Order Functions and Lambda”A higher-order function is a function that either takes another function as an argument or returns a function. This is a cornerstone of functional programming.
Anonymous (unnamed) functions can be created on the fly using the lambda special form.
Example: Using mapcar and lambda
Section titled “Example: Using mapcar and lambda”mapcar is a classic higher-order function. It applies a given function to each element of a list and returns a new list with the results.
;; Define a list of numbers(defparameter *numbers* '(1 2 3 4 5))
;; Use mapcar with a named function (sqrt)(print (mapcar #'sqrt *numbers*))
;; Use mapcar with an anonymous lambda function to square each number(print (mapcar (lambda (x) (* x x)) *numbers*))Output
Section titled “Output”(1.0 1.4142135 1.7320508 2.0 2.236068)(1 4 9 16 25)Explanation
Section titled “Explanation”#'sqrt: The#'(sharp-quote) syntax is shorthand for(function sqrt). It retrieves the function object associated with the symbolsqrt.(lambda (x) (* x x)): Creates a function that takes one argumentxand returns its square. This function object is passed directly tomapcar.