This module provides non-mutating insert and delete operations as well as common operations such as walking the tree. It also features "nested" versions of insert, delete, and search functions, that allow operations on nested trees.
guile-aa-tree.html - documentation file for guile-aa-tree
Copyright (C) 2017 Christopher Howard
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
(use-modules (aa-tree))
The empty tree is represented by a #nil value. For example, to create a tree with one node, you could call this expression:
(aa-insert #nil 'animals 'moose)
In the unextended operation of the module, it is necessary that every key in a tree must be either a number, string, identifier, or keyword. Furthermore, every key of every node in a tree must be the same type.
If you wish to use other key types or have multiple keys types in a tree, it is possible to do this by defining an appropriate goops comparison methods for the type(s) you wish to use. More specifically, you must define an appropriate equal? method and < method.
Some functions will also take a list of multiple keys instead of a single key, which signals that a nested operation is intended.
A "nested" tree refers to a tree which is the value of a node in another tree. For convenience, aa-delete, aa-insert, and aa-search can operate on a set of nested trees, by receiving a list of keys instead of a single key. aa-insert can even create nested trees in this way. For example, in a game you might want to store data like so:
(aa-insert world-tree (list 'rooms 'kitchen 'object-descriptions 'knife) "A sharp cutting tool.")
Scheme procedure: aa-delete tree key
Performs a non-mutating delete on tree. Deletes the node in tree which has key key. If there is no such node, it simply returns tree. O(log n) worst case efficiency.
If a list of keys is provided instead of a single key, aa-delete will attempt a nested tree delete, starting the search with the first key in the list. If a nested tree of some required level does not exist, it will simply return the original tree unmodified.
Scheme procedure: aa-for-each proc tree
Calls proc for each of the key-value pairs in tree. proc must accept an argument of the form (key . value). The calls will be made in order of least to greatest keys. aa-for-each does not return the results of these calls.
Scheme procedure: aa-for-each-reverse proc tree
aa-for-each-reverse operates the same as aa-for-each except that it applies the pairs in reverse order, from greatest key to least key.
Scheme procedure: aa-insert tree key #:optional value)
Performs a non-mutating insert on tree, inserting a node having key key and value value. O(log n) worst case efficiency.
If a list of keys is provided instead of a single key, aa-insert will attempt a nested tree insert, starting the search with the first key in the list. If a nested tree of some required level does not exist, that tree will be created and inserted into the the previous level tree.
Scheme procedure: aa-map fn tree
Maps fn over the key-value pairs in tree, ordered from smallest to greatest key, returning the list of results. So, fn must take an argument of the form (key . value). Unlike aa-for-each, the actual functional calls will not necessarily be executed in the same order as the key-value pairs. O(n) efficiency.
Scheme procedure: aa-map-keys fn tree
The same operation as aa-map, except only the key of each node is presented to fn. O(n) efficiency.
Scheme procedure: aa-map-reverse fn tree
The equivalent of aa-map, but the ordering is from greatest to smallest key. O(n) efficiency.
Scheme procedure: aa-map-values fn tree
The same operation as aa-map, except only the value of each node is presented to fn. O(n) efficiency.
Scheme procedure: aa-search tree key
Searches for the node in the tree with key key, and returns the value of that node. If such a node is found, the value will be returned wrapped in a single element list. If no such node is found, a #nil value will be returned. So, to determine whether or not a node was found, you can simply do a nil? test on the result. This approach is helpful, as it is always possible that a node with the correct key might be storing a value such as #nil or #f. O(log n) worst case efficiency.
If a list of keys is provided instead of a single key, aa-search will attempt a nested tree search, starting the search with the first key in the list. If a nested tree of some required level does not exist, the function will simply return #nil.
Scheme procedure: aa-to-list tree
Returns the key value pairs of tree in list form, ordering from smallest to greatest key. O(n) efficiency.
Scheme procedure: list-to-aa-tree init-tree lst
Takes keys and values from lst and inserts them into tree init-tree. If init-tree is #nil (empty tree) then this is the same as converting lst into a tree. Argument lst must be a list of the form (KEY VALUE KEY VALUE ...) with zero or more sets of keys and values.
KEYs may be any type accepted by aa-insert. Note that using another list in place of a single key will still signal a nested insert operation.
If a VALUE is itself a list, then VALUE will be processed by list-to-aa-tree, creating another tree stored as the value of that node (a nested tree). If you wish simply to use a list as a node value, then use the identifer _ as the first element of the list. That first _ will be removed before the node is added.
Example:
(read-set! keywords 'prefix) (define game-data (list-to-aa-tree #nil '(:troops (:infantry (:speed medium :armor weak) :heavy-infantry (:speed slow :armor strong)) :city-names (_ Aberdeen Brighton Cambridge Exeter Glasgow))))
It is not necessary to use the keyword type for keys, but it does make the data structure more readable.