Lisp - Custom Predicates



In Lisp, we can define a custom predicate using defun macro using following syntax −

Syntax for defun is −

(defun predicate-name (parameter-list) 
   "Optional documentation string." 
 body)

Where

  • predicate-name− Name of the predicate

  • parameter-list− Parameters of the predicate

  • Optional documentation string− A string to describe the behavior of the predicate. Useful for maintainability and enhance readability.

  • body− Body of the predicate. It should evaluate to either t(true) or nil(false).

Let's now check few examples of useful custom predicates to illustrate the concept of custom predicate better.

Example - Checking a number being positive

main.lisp

; predicate to check a number to be a positive number
(defun positivep (num)
   "if num is a positive number."
   (> num 0))

(write(positivep 5))  ; T
(terpri)
(write(positivep -5)) ; NIL
(terpri)
(write(positivep 0))  ; NIL

Output

When you execute the code, it returns the following result −

T
NIL
NIL

Example - Checking empty list

main.lisp

; predicate to check an empty list
(defun emptylistp (lst)
   "if list is empty"
   (null lst))

(write(emptylistp '()))  ; T
(terpri)
(write(emptylistp '(a b))) ; NIL

Output

When you execute the code, it returns the following result −

T
NIL

Example - Checking number in a range

main.lisp

; predicate to check if a number is in range of given upper and lower limit
(defun withinrangep (num lower upper)
   "if num is within range [lower, upper] (both included)"
   (and (>= num lower) (<= num upper)))

(write(withinrangep 5 3 9))  ; T
(terpri)
(write(withinrangep 5 6 9))  ; NIL
(terpri)
(write(withinrangep 5 1 5))  ; T

Output

When you execute the code, it returns the following result −

T
NIL
T

Best Practices

Following are the best practices while defining a custom predicate.

  • Descriptive Name− Name of the predicate should be clear and descriptive to clearly indicate the purpose of the predicate. For example, evenp, emotylistp etc.

  • Documentation− Putting a documentation string is always better to show predicate purpose and parameters details.

  • Return t or nil− Predicate should always return a t or nil explicitly.

  • Use Existing Functions− Use built-in Lisp functions whenever feasible like null, numberp, search etc.

  • Test− Test predicate with all edge cases, different types of inputs to ensure its correct behavior in multiple scenarios.

Advertisements