
- LISP Tutorial
- LISP - Home
- LISP - Overview
- LISP - Environment
- LISP - REPL
- LISP - Program Structure
- LISP - Basic Syntax
- LISP - Data Types
- Lisp Macros
- LISP - Macros
- LISP - Backquote and Comma
- LISP - Code Generation Using Macro
- LISP - Variable Capture and Hygienic macro
- LISP - Scope and Binding
- LISP - Macro Writing Style
- LISP - Macro Characters
- LISP - Read-Time Macros
- LISP - Compiler Macros
- LISP - Uses of Macros
- Lisp Functions
- LISP - Functions
- LISP - Functions vs Macros
- LISP - Calling Function using funcall
- LISP - Calling Function using apply
- LISP - Closures
- LISP - Functions as Arguments
- LISP - Functions as Return Values
- LISP - Recursion
- LISP - Built-in Functions
- Lisp Predicates
- LISP - Predicates
- LISP - Generic Data Type Predicates
- LISP - Specific Data Type Predicates
- LISP - Equality Predicates
- LISP - Numeric Predicates
- LISP - Comparison Predicates
- LISP - Logical Predicates
- LISP - List Predicates
- LISP - Custom Predicates
- LISP - Chaining Predicates
- Lisp Arrays
- LISP - Arrays
- LISP - Adjustable Arrays
- LISP - Fill Pointers in Arrays
- LISP - Specialized Arrays
- LISP - Arrays Properties
- LISP - Iterating over Arrays
- LISP - Multidimensional Arrays
- LISP - Row-Major Order
- Lisp Strings
- LISP - Strings
- LISP - String Concatenation
- LISP - String Comparison
- LISP - String Case Conversion
- LISP - String Trimmimg
- LISP - String Searching
- LISP - Getting Substring
- LISP - String Replacement
- LISP - Sorting Strings
- LISP - Merging Strings
- LISP - Accessing Characters of String
- LISP - String length
- LISP - Escape Sequences
- Lisp Sequences
- LISP - Sequences
- LISP - Accessing Element of Sequence
- LISP - Sequence length
- LISP - Getting Subsequence
- LISP - Search Element in Sequence
- LISP - Sequence Concatenation
- LISP - Reversing a Sequence
- LISP - Mapping Sequence Element
- LISP - position of Element
- LISP - Remove an Element
- LISP - Sort Sequence
- LISP - Merge Sequences
- LISP - every function
- LISP - some function
- LISP - notany function
- LISP - notevery function
- Lisp Lists
- LISP - Lists
- LISP - Accessing Elements of Lists
- LISP - Modifications to Lists
- LISP - Using mapcar on List
- LISP - Using mapc on List
- LISP - Using reduce on List
- LISP - Removing elements from List
- LISP - Reversing a List
- LISP - Sorting a List
- LISP - Searching a List
- LISP - List vs Vectors
- LISP - Matrix Multiplication
- Lisp Vectors
- LISP - Vectors
- LISP - Creating Vectors
- LISP - Accessing Elements of Vectors
- LISP - Modifications to Vectors
- LISP - Adjustable Vectors
- LISP - Specialized Vectors
- LISP - Vector Functions
- Lisp Set
- LISP - Set
- LISP - Adding elements to the Set
- LISP - Getting SubSet from a Set
- LISP - Set Difference
- LISP - Set Exclusive OR
- LISP - Set Intersection
- LISP - Set Union
- LISP - Representing Set with HashTable
- LISP - List as Set vs HashTable as Set
- Lisp Tree
- LISP - Tree
- LISP - Recursive Traversal
- LISP - Inorder Traversal
- LISP - Preorder Traversal
- LISP - Postorder Traversal
- LISP - Depth First Traversal
- LISP - Modifying Tree
- LISP - Search Tree
- LISP - Binary Tree
- Lisp Hash Table
- LISP - Hash Table
- Adding Values to Hash Table
- Removing Values from Hash Table
- Updating Values of Hash Table
- Iterating Hash Table Entries
- Searching key in HashTable
- Checking Size of HashTable
- Using Custom Equality Check
- Lisp - Input − Output
- LISP - Input − Output
- LISP - Streams
- LISP - Reading Data from Streams
- LISP - Writing Data to Streams
- LISP - File I/O
- LISP - String I/O
- LISP - Formatting with Format
- LISP - Interactive I/O
- LISP - Error Handling
- LISP - Binary I/O
- Lisp - Structures
- LISP - Structures
- LISP - Accessors and Mutators
- LISP - Structure Options
- LISP - Structure Types
- LISP - Applications and Best Practices
- Lisp - CLOS
- LISP - CLOS
- Lisp - Objects
- LISP - Class
- LISP - Slots and Accessors
- LISP - Generic Functions
- LISP - Class Precedence
- LISP - Metaobject Protocol
- LISP - Multimethods
- LISP - Multiple Inheritance
- LISP - Method Combinations
- LISP - Method Combinations
- LISP - :before Method Combination
- LISP - :primary Method Combination
- LISP - :after Method Combination
- LISP - :around Method Combination
- LISP - + Method Combination
- LISP - and Method Combination
- LISP - append Method Combination
- LISP Useful Resources
- Lisp - Quick Guide
- Lisp - Useful Resources
- Lisp - Discussion
Lisp - Set
Common Lisp does not provide a set data type. However, it provides number of functions that allows set operations to be performed on a list.
You can add, remove, and search for items in a list, based on various criteria. You can also perform various set operations like: union, intersection, and set difference.
Implementing Sets in LISP
Sets, like lists are generally implemented in terms of cons cells. However, for this very reason, the set operations get less and less efficient the bigger the sets get.
The adjoin function allows you to build up a set. It takes an item and a list representing a set and returns a list representing the set containing the item and all the items in the original set.
The adjoin function first looks for the item in the given list, if it is found, then it returns the original list; otherwise it creates a new cons cell with its car as the item and cdr pointing to the original list and returns this new list.
The adjoin function also takes :key and :test keyword arguments. These arguments are used for checking whether the item is present in the original list.
Since, the adjoin function does not modify the original list, to make a change in the list itself, you must either assign the value returned by adjoin to the original list or, you may use the macro pushnew to add an item to the set.
Example
Create a new source code file named main.lisp and type the following code in it.
main.lisp
; creating myset as an empty list (defparameter *myset* ()) (adjoin 1 *myset*) (adjoin 2 *myset*) ; adjoin did not change the original set ; so it remains same (write *myset*) ; print the set ; terminate printing (terpri) ; update the set (setf *myset* (adjoin 1 *myset*)) ; update the set (setf *myset* (adjoin 2 *myset*)) ; now the original set is changed ; print the updated set (write *myset*) ; terminate printing (terpri) ;adding an existing value (pushnew 2 *myset*) ;no duplicate allowed ; print the set (write *myset*) ; terminate printing (terpri) ;pushing a new value (pushnew 3 *myset*) ; print the set (write *myset*) ; terminate printing (terpri)
Output
When you execute the code, it returns the following result −
NIL (2 1) (2 1) (3 2 1)
Checking Membership
The member group of functions allows you to check whether an element is member of a set or not.
The following are the syntaxes of these functions −
member item list &key :test :test-not :key member-if predicate list &key :key member-if-not predicate list &key :key
These functions search the given list for a given item that satisfies the test. If no such item is found, then the functions returns nil. Otherwise, the tail of the list with the element as the first element is returned.
The search is conducted at the top level only.
These functions could be used as predicates.
Example
Update the source code file named main.lisp and type the following code in it.
main.lisp
; print if zara is part of the list (write (member 'zara '(ayan abdul zara riyan nuha))) ; terminate printing (terpri) ; print the even numbers (write (member-if #'evenp '(3 7 2 5/3 'a))) (terpri) ; print if not the numbers (write (member-if-not #'numberp '(3 7 2 5/3 'a 'b 'c)))
Output
When you execute the code, it returns the following result −
(ZARA RIYAN NUHA) (2 5/3 'A) ('A 'B 'C)
Set Union
The union group of functions allows you to perform set union on two lists provided as arguments to these functions on the basis of a test.
The following are the syntaxes of these functions −
union list1 list2 &key :test :test-not :key nunion list1 list2 &key :test :test-not :key
The union function takes two lists and returns a new list containing all the elements present in either of the lists. If there are duplications, then only one copy of the member is retained in the returned list.
The nunion function performs the same operation but may destroy the argument lists.
Example
Update the source code file named main.lisp and type the following code in it.
main.lisp
; calculate union and assign to set1 variable (setq set1 (union '(a b c) '(c d e))) ; calculate union and assign to set2 variable (setq set2 (union '(#(a b) #(5 6 7) #(f h)) '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch) ) ; calculate union and assign to set3 variable (setq set3 (union '(#(a b) #(5 6 7) #(f h)) '(#(5 6 7) #(a b) #(g h))) ) ; print set1 (write set1) ; terminate printing (terpri) ; print set2 (write set2) ; terminate printing (terpri) ; print set3 (write set3)
Output
When you execute the code, it returns the following result −
(A B C D E) (#(F H) #(5 6 7) #(A B) #(G H)) (#(A B) #(5 6 7) #(F H) #(5 6 7) #(A B) #(G H))
Please Note
The union function does not work as expected without :test-not #'mismatch arguments for a list of three vectors. This is because, the lists are made of cons cells and although the values look same to us apparently, the cdr part of cells does not match, so they are not exactly same to LISP interpreter/compiler. This is the reason; implementing big sets are not advised using lists. It works fine for small sets though.
Set Intersection
The intersection group of functions allows you to perform intersection on two lists provided as arguments to these functions on the basis of a test.
The following are the syntaxes of these functions −
intersection list1 list2 &key :test :test-not :key nintersection list1 list2 &key :test :test-not :key
These functions take two lists and return a new list containing all the elements present in both argument lists. If either list has duplicate entries, the redundant entries may or may not appear in the result.
Example
Update the source code file named main.lisp and type the following code in it.
main.lisp
; compute intersection and assign to set1 variable (setq set1 (intersection '(a b c) '(c d e))) ; compute intersection and assign to set2 variable (setq set2 (intersection '(#(a b) #(5 6 7) #(f h)) '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch) ) ; compute intersection and assign to set3 variable (setq set3 (intersection '(#(a b) #(5 6 7) #(f h)) '(#(5 6 7) #(a b) #(g h))) ) ; print set1 (write set1) ; terminate printing (terpri) ; print set2 (write set2) ; terminate printing (terpri) ; print set3 (write set3)
Output
When you execute the code, it returns the following result −
(C) (#(A B) #(5 6 7)) NIL
The intersection function is the destructive version of intersection, i.e., it may destroy the original lists.
Set Difference
The set-difference group of functions allows you to perform set difference on two lists provided as arguments to these functions on the basis of a test.
The following are the syntaxes of these functions −
set-difference list1 list2 &key :test :test-not :key nset-difference list1 list2 &key :test :test-not :key
The set-difference function returns a list of elements of the first list that do not appear in the second list.
Example
Update the source code file named main.lisp and type the following code in it.
main.lisp
; compute difference and assign to set1 variable (setq set1 (set-difference '(a b c) '(c d e))) ; compute difference and assign to set2 variable (setq set2 (set-difference '(#(a b) #(5 6 7) #(f h)) '(#(5 6 7) #(a b) #(g h)) :test-not #'mismatch) ) ; compute difference and assign to set3 variable (setq set3 (set-difference '(#(a b) #(5 6 7) #(f h)) '(#(5 6 7) #(a b) #(g h))) ) ; print set1 (write set1) ; terminate printing (terpri) ; print set2 (write set2) ; terminate printing (terpri) ; print set3 (write set3)
Output
When you execute the code, it returns the following result −
(A B) (#(F H)) (#(A B) #(5 6 7) #(F H))