assoc-list/recursive-assoc-list [ Classes ]
[ Top ] [ assoc-list ] [ Classes ]
NAME
recursive-assoc-list File: recursive-assoc-list.lsp Class Hierarchy: named-object -> linked-named-object -> sclist -> circular-sclist -> assoc-list -> recursive-assoc-list Version: 1.1.0 Project: slippery chicken (algorithmic composition) Purpose: Extension of the assoc-list class to allow and automatically instantiate association lists inside of association lists to any level of nesting. E.g. (setf x '((1 one) (2 two) (3 ((cat "cat") (dog ((mickey mouse) (donald duck) (daffy duck) (uncle ((james dean) (dean martin) (fred astaire) (ginger ((wolfgang mozart) (johann bach) (george gershwin))))))) (mouse "mouse"))) (4 four))) Author: Michael Edwards: m@michael-edwards.org Creation date: March 18th 2001 $$ Last modified: 19:28:13 Tue Feb 6 2024 CET SVN ID: $Id$
recursive-assoc-list/add [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Add a new element (key/data pair) to the given recursive-assoc-list object. If no value is specified for the optional argument, the new element is added at the end of the top level. The optional argument allows for the FULL-REF to be specified, i.e. a recursive path of keys down to the nested level where the new element is to be placed. N.B. All new items are added to the end of the data list, unlike in assoc-list where that is the default but can be changed. Here it cannot be changed.
ARGUMENTS
- A key/data pair. - A recursive-assoc-list object.
OPTIONAL ARGUMENTS
- A list that is the FULL-REF, i.e. a recursive path of keys, down to the nested level where the new element is to be placed.
RETURN VALUE
Returns T if the specified named-object is successfully added to the given recursive-assoc-list. Returns an error if an attempt is made to add NIL to the given recursive-assoc-list or if the given named-object is already present at the same level within the given recursive-assoc-list.
EXAMPLE
;; Adding an element while specifying no optional argument results in the new ;; element being placed at the end of the top level by default (evident here by ;; the fact that the ref for (MAKERS) is a single-item list) (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (add '(makers mark) ral) (get-all-refs ral)) => ((JIM) (WILD) (FOUR ROSES) (FOUR VIOLETS BLUE) (FOUR VIOLETS RED DRAGON) (FOUR VIOLETS RED VIPER) (FOUR VIOLETS RED FOX) (FOUR VIOLETS WHITE) (MAKERS)) ;; A list that is a path of keys (FULL-REF) to the desired recursive level must ;; be given as the optional argument in order to place the specified element ;; deeper in the given recursive-assoc-list object (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (add '(yellow sky) ral '(four violets)) (get-all-refs ral)) => ((JIM) (WILD) (FOUR ROSES) (FOUR VIOLETS BLUE) (FOUR VIOLETS RED DRAGON) (FOUR VIOLETS RED VIPER) (FOUR VIOLETS RED FOX) (FOUR VIOLETS WHITE) (FOUR VIOLETS YELLOW)) ;; Attempting to add an element that is already present at the given level of ;; the given recursive-assoc-list object results in an error (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (add '(makers mark) ral) (add '(makers mark) ral)) => assoc-list::add: Can't add MAKERS to assoc-list with id MIXED-BAG because key already exists! [Condition of type SIMPLE-ERROR] ;; Attempting to add NIL also results in an error (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (add '() ral)) => assoc-list::add: named-object is NIL! [Condition of type SIMPLE-ERROR]
SYNOPSIS
(defmethod add (named-object (ral recursive-assoc-list) &optional ref)
recursive-assoc-list/add-empty-parcel [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Add a recursive-assoc-list object with NIL data (an empty level of recursion) to the end of the top-level of a given recursive-assoc-list object. NB: Adding an empty parcel to a given recursive-assoc-list object will cause the method get-all-refs to fail on that recursive-assoc-list object.
ARGUMENTS
- A recursive-assoc-list object. - A symbol that will be the ID of the new, empty recursive-assoc-list object that is to be added.
OPTIONAL ARGUMENTS
- <new-class> The name of an existing subclass of recursive-assoc-list that the parcel should be promoted to.
RETURN VALUE
A recursive-assoc-list object with DATA of NIL (the "empty parcel")
EXAMPLE
;; Add two new empty parcels (the first a recursive-assoc-list, by default, the ;; second a rthm-seq-palette) and return the new list of REFS: (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (add-empty-parcel ral 'bricolage) (add-empty-parcel ral 'rsp 'rthm-seq-palette) (get-all-refs ral)) Mark set => ((JIM) (WILD) (FOUR ROSES) (FOUR VIOLETS BLUE) (FOUR VIOLETS RED DRAGON) (FOUR VIOLETS RED VIPER) (FOUR VIOLETS RED FOX) (FOUR VIOLETS WHITE) (BRICOLAGE) (RSP))
SYNOPSIS
(defmethod add-empty-parcel ((ral recursive-assoc-list) id &optional new-class)
recursive-assoc-list/assoc-list-id-list [ Functions ]
[ Top ] [ recursive-assoc-list ] [ Functions ]
DESCRIPTION
Determine whether a given list contains only atoms which could be used as assoc-list IDs. To pass the test, a given atom must be either a symbol, a number or a string.
ARGUMENTS
A list.
RETURN VALUE
T or NIL indicating whether the atoms of the given list are all capable of being used as assoc-list IDs. T = all can be used as assoc-list IDs.
EXAMPLE
;; All of the elements in this list are either a symbol, a number or a ;; string. The list therefore returns a T when tested. (let ((alil '(jim beam 3 "Allegro" 5 flute))) (assoc-list-id-list alil)) => T ;; This list fails, as the last element is a list (and therefore not of type ;; string, number or symbol) (let ((alil '(jim beam 3 "Allegro" 5 (flute)))) (assoc-list-id-list alil)) => NIL
SYNOPSIS
(defun assoc-list-id-list (id-list)
recursive-assoc-list/get-all-refs [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Return a list of all the keys (REFS) in a given recursive-assoc-list object. Nested keys are given in FULL-REF form, i.e. a list that is the path of keys to the specific key. Keys that are not part of nesting-path are also returned as lists (single-item lists) by default. An optional argument allows these to be returned as individual symbols rather than lists. NB This will only work on the top-level object due to the creation of references when linking. If you're interested in the full refs of a sub-ral, try ths get-this-refs method.
ARGUMENTS
- A recursive-assoc-list object.
OPTIONAL ARGUMENTS
- T or NIL to indicate whether to return single REFS (non-nested keys) as lists or as individual symbols. T = as list. Default = T.
RETURN VALUE
A list.
EXAMPLE
;; By default all keys are returned as lists, even single (non-nested) keys (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-all-refs ral)) => ((JIM) (WILD) (FOUR ROSES) (FOUR VIOLETS BLUE) (FOUR VIOLETS RED DRAGON) (FOUR VIOLETS RED VIPER) (FOUR VIOLETS RED FOX) (FOUR VIOLETS WHITE)) ;; Setting the optional argument to NIL returns non-nested keys as symbols ;; rather than lists (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-all-refs ral nil)) => (JIM WILD (FOUR ROSES) (FOUR VIOLETS BLUE) (FOUR VIOLETS RED DRAGON) (FOUR VIOLETS RED VIPER) (FOUR VIOLETS RED FOX) (FOUR VIOLETS WHITE))
SYNOPSIS
(defmethod get-all-refs ((ral recursive-assoc-list) &optional (single-ref-as-list t))
recursive-assoc-list/get-data [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Return the named-object (or linked-named-object) that is identified by a specified key within a given recursive-assoc-list object. NB: This method returns the named object itself, not just the data associated with the key (use assoc-list::get-data-data for that).
ARGUMENTS
- A symbol that is the key (id) of the named-object sought, or a list of symbols that are the path to the desired named-object within the given recursive-assoc-list. - The recursive-assoc-list object in which it is sought.
OPTIONAL ARGUMENTS
- T or NIL to indicate whether a warning is printed if the specified key cannot be found within the given assoc-list. T = print. Default = T.
RETURN VALUE
A named-object is returned if the specified key is found within the given recursive-assoc-list object. NIL is returned and a warning is printed if the specified key is not found in the given recursive-assoc-list object. This applies, too, when a nested key is specified without including the other keys that are the path to that key (see example).
EXAMPLE
;; Get a named-object from the top-level of the recursive-assoc-list object (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-data 'wild ral)) => NAMED-OBJECT: id: WILD, tag: NIL, data: TURKEY ;; A list including all keys that are the path to the specified key is required ;; to get nested named-objects (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-data '(four violets white) ral)) => NAMED-OBJECT: id: WHITE, tag: NIL, data: RIBBON ;; Searching for a key that is not present in the given recursive-assoc-list ;; object returns NIL and a warning (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-data 'johnnie ral)) => NIL WARNING: assoc-list::get-data: Could not find data with key JOHNNIE in assoc-list with id MIXED-BAG ;; Searching for a nested key without specifying the path to that key within a ;; list also returns a NIL and a warning (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-data 'fox ral)) => NIL WARNING: assoc-list::get-data: Could not find data with key FOX in assoc-list with id MIXED-BAG
SYNOPSIS
(defmethod get-data :around (ids (ral recursive-assoc-list) &optional (warn t))
recursive-assoc-list/get-first [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Returns the first named-object in the DATA slot of the given recursive-assoc-list object.
ARGUMENTS
- A recursive-assoc-list object.
RETURN VALUE
A named-object that is the first object in the DATA slot of the given recursive-assoc-list object.
EXAMPLE
(let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-first ral)) => NAMED-OBJECT: id: JIM, tag: NIL, data: BEAM
SYNOPSIS
(defmethod get-first ((ral recursive-assoc-list))
recursive-assoc-list/get-first-ref [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Get the full reference into the given recursive-assoc-list object of the first named-object in the given recursive-assoc-list object. NB: If the <ral> argument happens to be a recursive-assoc-list object that is contained within another recursive-assoc-list object (i.e. is a nested recursive-assoc-list object), then the result is the reference into the top-level recursive-assoc-list object, not the argument.
ARGUMENTS
- A recursive-assoc-list object.
RETURN VALUE
EXAMPLE
;; A simple call returns the first top-level named-object (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-first-ref ral)) => (JIM) ;; Return the first ref of a nested recursive-assoc-list object (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-first-ref (get-data-data '(four violets) ral))) => (FOUR VIOLETS BLUE)
SYNOPSIS
(defmethod get-first-ref ((ral recursive-assoc-list))
recursive-assoc-list/get-last [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Get the last named-object in a given recursive-assoc-list object. NB: This method functions linearly, not hierarchically. The last named object is therefore not necessarily the deepest of a nest, but the last listed.
ARGUMENTS
- A recursive-assoc-list object.
RETURN VALUE
A named-object (or linked-named-object).
EXAMPLE
;; This returns '(white ribbon), not '(fox hole) (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-last ral)) => NAMED-OBJECT: id: WHITE, tag: NIL, data: RIBBON
SYNOPSIS
(defmethod get-last ((ral recursive-assoc-list))
recursive-assoc-list/get-last-ref [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Get the last REF (path of nested keys) of the given recursive-assoc-list object. NB: This method functions linearly, not hierarchically. The last-ref may not be the deepest nested.
ARGUMENTS
- A recursive-assoc-list object.
RETURN VALUE
Returns a list that is the last REF of the given recursive-assoc-list object.
EXAMPLE
;; Typical usage with nesting (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-last-ref ral)) => (FOUR VIOLETS WHITE) ;; Returns the last-ref as a list even if the given recursive-assoc-list object ;; contains no nesting (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four roses))))) (get-last-ref ral)) => (FOUR)
SYNOPSIS
(defmethod get-last-ref ((ral recursive-assoc-list))
recursive-assoc-list/get-previous [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Get the previous named-object in the given recursive-assoc-list object by specifying the ID of a named-object contained within that given recursive-assoc-list object. An optional argument allows for the retrieval of a previous named-object that is more than one step back in the given recursive-assoc-list object (i.e., not the named-object that immediately precedes the specified key). If the number given for the optional <how-many> argument is greater than the number of items in the given recursive-assoc-list object, the value returned will be a negative number. The method proceeds linearly, not hierarchically, when getting previous named-objects from further down into nested assoc-lists. In other words, the named-object immediately previous to (white ribbon) in this nested list is (fox hole), which is at a deeper level, not (red ...) or (blue velvet), which are at the same level: ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon) In order to retrieve objects that are nested more deeply, the list that is the <keys> argument must consist of the consecutive path of keys leading to that object. If only the key of a named object that is deeper in the list is given, and not the path of keys to that object, a warning will be printed that the given key cannot be found in the list. NB: When this method is applied to keys that contain further assoc-list objects, the method will drop into the debugger with an error.
ARGUMENTS
- A recursive-assoc-list object. - A list containing one or more symbols that are either the ID of the specified named object or the path of keys to that object within the given recursive-assoc-list object.
OPTIONAL ARGUMENTS
- An integer indicating how many steps back in the given recursive-assoc-list from the specified named-object to look when retrieving the desired object (e.g. 1 = immediately previous object, 2 = the one before that etc.)
RETURN VALUE
A linked-named-object.
EXAMPLE
;; Get the object immediately previous to that with the key WILD returns the ;; object with key JIM and data BEAM (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-previous ral '(wild))) => LINKED-NAMED-OBJECT: previous: NIL, this: (JIM), next: (WILD) NAMED-OBJECT: id: JIM, tag: NIL, data: BEAM ;; Attempting to get the previous object from the key FOUR, which contains a ;; nested list, returns an error unless the first key in the nested list is ;; also included (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-previous ral '(four))) => There is no applicable method for the generic function #<STANDARD-GENERIC-FUNCTION PREVIOUS (1)> when called with arguments ( NAMED-OBJECT: id: FOUR, tag: NIL, (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-previous ral '(four roses))) => LINKED-NAMED-OBJECT: previous: (JIM), this: (WILD), next: (FOUR ROSES) NAMED-OBJECT: id: WILD, tag: NIL, data: TURKEY ;; The method defines the previous object linearly, not hierarchically; i.e., ;; the previous object to (white ribbon) here is (fox hole) and not (red ...) (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-previous ral '(four violets white))) => LINKED-NAMED-OBJECT: previous: (FOUR VIOLETS RED VIPER), this: (FOUR VIOLETS RED FOX), next: (FOUR VIOLETS WHITE) NAMED-OBJECT: id: FOX, tag: NIL, data: HOLE ;; Use the <how-many> argument to retrieve previous objects further back than ;; the immediate predecessor (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-previous ral '(four violets white) 4)) => LINKED-NAMED-OBJECT: previous: (FOUR ROSES), this: (FOUR VIOLETS BLUE), next: (FOUR VIOLETS RED DRAGON) NAMED-OBJECT: id: BLUE, tag: NIL, data: VELVET ;; Using a <how-many> value greater than the number of items in the given ;; recursive-assoc-list object returns a negative number (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (get-previous ral '(four violets white) 14)) => -7
SYNOPSIS
(defmethod get-previous ((ral recursive-assoc-list) keys &optional (how-many 1))
recursive-assoc-list/get-this-refs [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DATE
5th July 2019, Essen Werden
DESCRIPTION
Get the <this> slots of each named-object (or subclass) in a recursive-assoc-list (ral). This should work on top-level rals and sub-rals alike, though rals with only sub-rals probably won't return anything. Unlike get-all-refs, this doesn't traverse recursive objects.
ARGUMENTS
- the recursive-assoc-list object
RETURN VALUE
a list of references (most probably simple lists)
SYNOPSIS
(defmethod get-this-refs ((ral recursive-assoc-list))
recursive-assoc-list/link-named-objects [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Create linked-named-objects from the named-objects in the data slots of the given recursive-assoc-list object. The linked-named-objects created hold keys that serve as pointers to the previous and next objects in the given recursive-assoc-list object, whether recursive or not. The optional <previous> and <higher-next> arguments are only for internal recursive calls and so shouldn't be given by the user.
ARGUMENTS
- A recursive-assoc-list object.
OPTIONAL ARGUMENTS
- <previous> - <higher-next>
EXAMPLE
;;; The recursive-assoc-list may not be linked on creation, evident here ;;; through the value of the LINKED slot (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))) => RECURSIVE-ASSOC-LIST: recurse-simple-data: T num-data: 8 linked: NIL full-ref: NIL ASSOC-LIST: warn-not-found T CIRCULAR-SCLIST: current 0 SCLIST: sclist-length: 3, bounds-alert: T, copy: T LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL NAMED-OBJECT: id: MIXED-BAG, tag: NIL, data: ( NAMED-OBJECT: id: JIM, tag: NIL, data: BEAM NAMED-OBJECT: id: WILD, tag: NIL, data: TURKEY [...] ;; The recursive-assoc-list object and the named-objects it contains are linked ;; after applying the link-named-objects method (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (link-named-objects ral)) => RECURSIVE-ASSOC-LIST: recurse-simple-data: T num-data: 8 linked: T full-ref: NIL ASSOC-LIST: warn-not-found T CIRCULAR-SCLIST: current 0 SCLIST: sclist-length: 3, bounds-alert: T, copy: T LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL NAMED-OBJECT: id: MIXED-BAG, tag: NIL, data: ( LINKED-NAMED-OBJECT: previous: NIL, this: (JIM), next: (WILD) NAMED-OBJECT: id: JIM, tag: NIL, data: BEAM LINKED-NAMED-OBJECT: previous: (JIM), this: (WILD), next: (FOUR ROSES) NAMED-OBJECT: id: WILD, tag: NIL, data: TURKEY
RETURN VALUE
the recursive-assoc-list object
SYNOPSIS
(defmethod link-named-objects ((ral recursive-assoc-list) &optional previous higher-next)
recursive-assoc-list/lisp-assoc-listp [ Functions ]
[ Top ] [ recursive-assoc-list ] [ Functions ]
DESCRIPTION
Determine whether a given list can has the structure of a lisp assoc-list. This is assessed based on each of the elements being a 2-item list, of which the first is a symbol, number or string (qualifies as a key). The optional argument <recurse-simple-data> allows the data portion of key/data pairs to be viewed as flat lists rather than as recursive lists.
ARGUMENTS
- A list.
OPTIONAL ARGUMENTS
T or NIL to indicate whether to consider lists of 2-item lists in the data position of a given key/data pair to be a list or a recursive list. T = list. Default = T.
RETURN VALUE
T or NIL. T = the tested list can be considered a Lisp assoc-list.
EXAMPLE
;; A list of 2-item lists, each of whose item are all either a symbol, number, ;; or string, can be considered a Lisp assoc-list. (let ((lal '((roses red) (3 "allegro") (5 flute)))) (lisp-assoc-listp lal)) => T ;; By default, lists of 2-item lists in the DATA portion of a key/data pair ;; will be considered as a simple list, rather than a recursive list, resulting ;; in the tested list passing as T. (let ((lal '((1 2) (3 ((4 5) (6 7))) (8 9)))) (lisp-assoc-listp lal)) => T ;; Setting the optional argument to NIL will cause the same list to fail with (let ((lal '((1 2) (3 ((4 5) (6 7))) (8 9)))) (lisp-assoc-listp lal nil)) => NIL
SYNOPSIS
(defun lisp-assoc-listp (candidate &optional (recurse-simple-data t))
recursive-assoc-list/make-ral [ Functions ]
[ Top ] [ recursive-assoc-list ] [ Functions ]
DESCRIPTION
Create a recursive-assoc-list object, which allows and automatically instantiates association lists inside of association lists to any level of nesting.
ARGUMENTS
- A symbol that is the object's ID. - A list of nested lists, or a list.
OPTIONAL ARGUMENTS
keyword arguments: - :recurse-simple-data. T or NIL to indicate whether to recursively instantiate a recursive-assoc-list in place of data that appears to be a simple assoc-list (i.e. a 2-element list). If NIL, the data of 2-element lists whose second element is a number or a symbol will be ignored, therefore remaining as a list. For example, this data would normally result in a recursive call: (y ((2 23) (7 28) (18 2))). T = replace assoc-list data with recursive-assoc-lists. Default = T. - :full-ref. Nil or a list representing the path to a nested recursive-assoc-list object within the given recursive-assoc-list object, starting from the top level of the given object. When NIL, the given recursive-assoc-list object itself is the top level. Default = NIL. - :tag. A symbol that is another name, description etc. for the given recursive-assoc-list object. The tag may be used for identification but not for searching purposes. Default = NIL. - :warn-not-found. T or NIL to indicate whether a warning is printed when an index which doesn't exist is used for look-up. Default = T.
RETURN VALUE
Returns a recursive-assoc-list object.
EXAMPLE
;; Create a recursive-assoc-list object with default keyword argument values (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))) => RECURSIVE-ASSOC-LIST: recurse-simple-data: T num-data: 8 linked: NIL full-ref: NIL ASSOC-LIST: warn-not-found T CIRCULAR-SCLIST: current 0 SCLIST: sclist-length: 3, bounds-alert: T, copy: T LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL NAMED-OBJECT: id: MIXED-BAG, tag: NIL, data: ( [...] ;; Use the class's get-all-refs method to show that by default, simple data is ;; recursed. The sublists in the second list in this example are processed as ;; nested lists (let ((ral (make-ral 'ral-test '((1 one) (2 ((3 4) (5 6))) (3 three))))) (get-all-refs ral)) => ((1) (2 3) (2 5) (3)) ;; Using the same data, but setting the :recurse-simple-data argument to NIL ;; will cause the method to process simple data as a unit rather than nested ;; lists (let ((ral (make-ral 'ral-test '((1 one) (2 ((3 4) (5 6))) (3 three)) :recurse-simple-data nil))) (get-all-refs ral)) => ((1) (2) (3))
SYNOPSIS
(defun make-ral (id ral &key (recurse-simple-data t) (warn-not-found t) (tag nil) (full-ref nil))
recursive-assoc-list/parcel-and-combine-all [ Functions ]
[ Top ] [ recursive-assoc-list ] [ Functions ]
DATE
December 16th 2022
DESCRIPTION
combine a list of recursive-assoc-lists (ral) into a new ral but adding each ral itself into a new ral with a given ID (parcelling). This allows each of the rals in the list to have common ids but by parcelling them up we can achieve this at the expense of a further level of recursion.
ARGUMENTS
- a list of rals - a list of ids to be used for parcelling. This should be as long as the list of rals.
RETURN VALUE
a new ral
EXAMPLE
;;; this is a bit convoluted but was the original motivation to write this ;;; routine: say you have a bunch of rthm-seq-palettes made from fragments and ;;; organised according to the length in quarter notes of the sequences. You can ;;; parcel them all up into recursive palettes and then into a single palette ;;; thus: (let* ((fragments '((1 (q. q.)) (1a (+q. q.)) (2 (q h)) (3 (h h)) (4 (q h.)) (5 (q w)) (6 (q. q.+h)) (7 ({ 3 tq tq tq })) (8 ((e.) s - e e -)))) (rsps (mapcar #'(lambda (refs) (make-rsp-from-fragments fragments refs)) ;; each of these lists will become an rsp, the duration of ;; which is the same length (not checked) '(((((3 4) 1)) ; 3/4 (((3 4) 2))) ((((4 4) 3)) ; 4/4 (((4 4) 4))) ((((5 4) 5)) ; 5/4 (((5 4) 6))) ((((2 4) 7) (7) (7)) ; 6/4 (((2 4) 7) (7) (8))) ((((4 4) 4) ((3 4) 1a)))))) ; 7/4 ;; get the duration of the first rthm-seq in each palette and use that as ;; an id for the main palette below (durs (loop for rsp in rsps collect (round (duration (get-first rsp))))) (rsp (parcel-and-combine-all rsps durs 'rthm-seq-palette))) (get-data-data '(6 2) rsp)) -> ((((2 4) { 3 TQ TQ TQ }) ({ 3 TQ TQ TQ }) ((E.) S - E E -)))
SYNOPSIS
(defun parcel-and-combine-all (rals ids &optional new-class) (unless (= (length rals) (length ids)) (error "recursive-assoc-list::parcel-and-combine-all: there should be the ~ same number of rals as ids.")) (let ((result (parcel-data (clone (first rals)) (pop ids)))) (when new-class (setq result (sc-change-class result new-class))) (loop for ral in (cdr rals) do (setf result (combine result (parcel-data ral (pop ids))))) result)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; EOF recursive-assoc-list.lsp
recursive-assoc-list/parcel-data [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DATE
10 Apr 2010
DESCRIPTION
Put all the data of a given recursive-assoc-list object into a new named-object at the top level of that recursive-assoc-list object; i.e. add a level of recursion. This is a means of making a collection of data before perhaps adding more with potentially conflicting ids. Note that if you want to parcel some palette because of potentially conflicting IDs with another (main) palette then combine is the method to use rather than add, e.g. (combine orig-palette (parcel-data derived-palette 'filtered))
ARGUMENTS
- A recursive-assoc-list object. - A symbol that is new the top-level id for the current data
RETURN VALUE
The new recursive-assoc-list object.
EXAMPLE
;; Collect all the data contained within the object 'mixed-bag and store it at ;; the top-level of 'mixed-bag within a new named-object with the id 'potpourri (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (parcel-data ral 'potpourri)) => RECURSIVE-ASSOC-LIST: recurse-simple-data: T num-data: 8 linked: NIL full-ref: NIL ASSOC-LIST: warn-not-found T CIRCULAR-SCLIST: current 0 SCLIST: sclist-length: 1, bounds-alert: T, copy: T LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL NAMED-OBJECT: id: MIXED-BAG, tag: FROM-PARCEL-DATA, data: ( NAMED-OBJECT: id: POTPOURRI, tag: NIL, data: RECURSIVE-ASSOC-LIST: recurse-simple-data: T num-data: 8 linked: NIL full-ref: NIL ASSOC-LIST: warn-not-found T CIRCULAR-SCLIST: current 0 SCLIST: sclist-length: 3, bounds-alert: T, copy: T LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL NAMED-OBJECT: id: MIXED-BAG, tag: NIL, data: ( NAMED-OBJECT: id: JIM, tag: NIL, data: BEAM [...]
SYNOPSIS
(defmethod parcel-data ((ral recursive-assoc-list) new-id)
recursive-assoc-list/r-count-elements [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Return the total number of elements recursively (across all depths) of the given recursive-assoc-list object.
ARGUMENTS
- A recursive-assoc-list object.
RETURN VALUE
An integer.
EXAMPLE
(let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (r-count-elements ral)) => 8
SYNOPSIS
(defmethod r-count-elements ((ral recursive-assoc-list))
recursive-assoc-list/ral-econs [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Automatically create new recursive-assoc-list objects. This method assumes that any existing key that may be referenced will be associated with data that is already a list, to the end of which the new data will be added (an error will be signalled if this is not the case.)
ARGUMENTS
- The data which is to be added. - The key to which the data is to be added (see above note for cases where this key already exists). - The recursive-assoc-list object to which this data is to be added.
RETURN VALUE
The new data added.
EXAMPLE
;;; Make an empty recursive-assoc-list object and add key/data pairs to the top ;;; level. (let ((ral (make-ral nil nil))) (print (get-all-refs ral)) (ral-econs 'beam 'jim ral) (ral-econs 'turkey 'wild ral) (ral-econs 'roses 'four ral) (print (get-all-refs ral)) (print (get-data-data 'wild ral))) => NIL ((JIM) (WILD) (FOUR)) (TURKEY) ;;; Add data to existing keys within a given recursive-assoc-list object ;;; Note that the data VELVET must be a list for this to succeed (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue (velvet)) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (print (get-all-refs ral)) (ral-econs 'underground '(four violets blue) ral) (print (get-data-data '(four violets blue) ral))) => ((JIM) (WILD) (FOUR ROSES) (FOUR VIOLETS BLUE) (FOUR VIOLETS RED DRAGON) (FOUR VIOLETS RED VIPER) (FOUR VIOLETS RED FOX) (FOUR VIOLETS WHITE)) (VELVET UNDERGROUND)
SYNOPSIS
(defmethod ral-econs (data key (ral recursive-assoc-list))
recursive-assoc-list/recursivep [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Check whether the data in a recursive-assoc-list object is really recursive.
ARGUMENTS
- A recursive-assoc-list object.
RETURN VALUE
T or NIL to indicate whether or not the tested data is recursive. T = recursive.
EXAMPLE
;; The data in this recursive-assoc-list object is really recursive, and ;; the method therefore returns T (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (recursivep ral)) => T ;; The data in this recursive-assoc-list object is not actually recursive, and ;; the method therefore returns NIL (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four roses))))) (recursivep ral)) => NIL
SYNOPSIS
(defmethod recursivep ((ral recursive-assoc-list))
recursive-assoc-list/relink-named-objects [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
This method is essentially the same as the method link-named-objects, but resets the LINKED slot to NIL and forces the link-named-objects method to be applied again.
ARGUMENTS
- A recursive-alloc-list object.
RETURN VALUE
A recursive-alloc-list object.
EXAMPLE
;; Usage as presented here; see the documentation for method link-named-objects ;; for more detail (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (relink-named-objects ral)) => RECURSIVE-ASSOC-LIST: recurse-simple-data: T num-data: 8 linked: T full-ref: NIL ASSOC-LIST: warn-not-found T CIRCULAR-SCLIST: current 0 SCLIST: sclist-length: 3, bounds-alert: T, copy: T LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL NAMED-OBJECT: id: MIXED-BAG, tag: NIL, data: ( LINKED-NAMED-OBJECT: previous: NIL, this: (JIM), next: (WILD) NAMED-OBJECT: id: JIM, tag: NIL, data: BEAM [...]
SYNOPSIS
(defmethod relink-named-objects ((ral recursive-assoc-list))
recursive-assoc-list/remove-data [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DATE
February 1st 2016, Edinburgh
DESCRIPTION
Convenience function to allow objects to be removed from a recursive-assoc-list (and subclasses e.g. palettes and maps)
ARGUMENTS
- the recursive assoc-list object - as many keys as you like. If none are passed then all are removed.
RETURN VALUE
The recursive-assoc-list object's new data list, i.e. with elements removed. Could of course be NIL if you've not passed any keys.
SYNOPSIS
(defmethod remove-data ((ral recursive-assoc-list) &rest keys)
recursive-assoc-list/rmap [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Recurse over the objects in a recursive-assoc-list and call the given function for each each named-object. See also assoc-list's map-data method which does pretty much the same but acting on each named-object's data rather than the named-object itself.
ARGUMENTS
- the recursive-assoc-list object - the function to call (function object)
OPTIONAL ARGUMENTS
- &rest further arguments to be passed to the function after the named-object from the recursive-assoc-list.
RETURN VALUE
The recursive-assoc-list object
EXAMPLE
(let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (rmap ral #'print)) => NAMED-OBJECT: id: JIM, tag: NIL, data: BEAM ************** NAMED-OBJECT: id: WILD, tag: NIL, data: TURKEY ************** NAMED-OBJECT: id: ROSES, tag: NIL, data: RED ************** NAMED-OBJECT: id: BLUE, tag: NIL, data: VELVET ************** NAMED-OBJECT: id: DRAGON, tag: NIL, data: DEN ************** NAMED-OBJECT: id: VIPER, tag: NIL, data: NEST ************** NAMED-OBJECT: id: FOX, tag: NIL, data: HOLE ************** NAMED-OBJECT: id: WHITE, tag: NIL, data: RIBBON ************** T
SYNOPSIS
(defmethod rmap ((ral recursive-assoc-list) function &rest arguments)
recursive-assoc-list/set-data [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Replace the named-object associated with a specified key within a given recursive-assoc-list object. This method replaces the whole named-object, not just the data of that object.
ARGUMENTS
- A key present within the given recursive-assoc-list object. This must be a list that is the FULL-REF (path of keys) if replacing a nested named-object. If replacing a named-object at the top level, the key can be given either as a single-item list or an individual symbol. - A key/data pair as a list. - The recursive-assoc-list object in which to find and replace the named-object associated with the specified key.
RETURN VALUE
Returns the new named-object. Returns NIL when the specified key is not found within the given recursive-assoc-list object.
EXAMPLE
;;; Replace a named-object at the top level using a single symbol (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (set-data 'wild '(makers mark) ral)) => NAMED-OBJECT: id: MAKERS, tag: NIL, data: MARK ;; The same can be done stating the top-level key as a single-item list. Apply ;; the get-all-refs method in this example to see the change (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (set-data '(wild) '(makers mark) ral) (get-all-refs ral)) => ((JIM) (MAKERS) (FOUR ROSES) (FOUR VIOLETS BLUE) (FOUR VIOLETS RED DRAGON) (FOUR VIOLETS RED VIPER) (FOUR VIOLETS RED FOX) (FOUR VIOLETS WHITE)) ;; Replace a nested named-object using a list that is the FULL-REF to that ;; object. Print the application of the method as well as the results from ;; applying the get-all-refs method in this example to see the effects (let ((ral (make-ral 'mixed-bag '((jim beam) (wild turkey) (four ((roses red) (violets ((blue velvet) (red ((dragon den) (viper nest) (fox hole))) (white ribbon))))))))) (print (set-data '(four violets red fox) '(bee hive) ral)) (print (get-all-refs ral))) => NAMED-OBJECT: id: BEE, tag: NIL, data: HIVE ************** ((JIM) (WILD) (FOUR ROSES) (FOUR VIOLETS BLUE) (FOUR VIOLETS RED DRAGON) (FOUR VIOLETS RED VIPER) (FOUR VIOLETS RED BEE) (FOUR VIOLETS WHITE))
SYNOPSIS
(defmethod set-data (key new-value (ral recursive-assoc-list))
recursive-assoc-list/set-slot [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
Set the specified slot of an object with a recursive-assoc-list structure to the specified value. This is particularly useful for changing the parameters of instrument objects within an instrument palette, for example. NB Setting, for instance, the high-sounding slot of an instrument will do nothing to the highest-written slot so do take care to set all the slots you need to in order to effect pitch selection etc. Or better still use the set-standard-range function.
ARGUMENTS
- The name of the slot whose value is to be set. - The value to which that slot is to be set. - The key within the given recursive-assoc-list object for which the slot is to be set. - The recursive-assoc-list object in which the slot is to be changed.
RETURN VALUE
The value to which the slot has been set.
EXAMPLE
(set-slot 'largest-fast-leap 10 'oboe +slippery-chicken-standard-instrument-palette+) => 10
SYNOPSIS
(defmethod set-slot (slot value id (ral recursive-assoc-list))
recursive-assoc-list/set-standard-instrument-slot [ Methods ]
[ Top ] [ recursive-assoc-list ] [ Methods ]
DESCRIPTION
A convenience method to set slots of instruments in the +slippery-chicken-standard-instrument-palette+.
DATE
July 20th 2015
EXAMPLE
(set-standard-instrument-slot 'highest-written 'f4 'double-bass)
SYNOPSIS
(defmethod set-standard-instrument-slot (slot value id)