----------------------------
$biglist is a collection of routines for maintaining huge persistent (sorted) lists in a format that is less likely to spam the server (which runs into a certain amount of trouble dealing with long ordinary lists --- btw we use `biglist' to refer to the huge data structure we're about to describe and `list' to refer to ordinary MOO lists {...}). The biglist in question lives on a particular object, to which we will refer in the discussion below as the `home' object, and its various elements appear as leaves of a tree whose nodes are kept in properties of the home object. It should be noted that the home object does not need to be (and in fact should *not* be) a descendant of $biglist one; $biglist merely provides utilities for manipulating the properties on the home object that are used in a particular biglist manipulation.
All of the utilities below refer to `caller' to locate the home object. Thus verbs to manipulate a given biglist must be located on or inherited by its home object itself. The home object needs to define the following verbs
:_make(@args) => new property on home object with value args
:_kill(prop) delete a given property that was created by :_make
:_get(prop) => home.prop
:_put(prop,@args) set home.prop = args
:_ord(element) given something that is of the form of a biglist element
return the corresponding ordinal (for sorting purposes).
If you never intend to use :find_ord, then this can be a
routine that always returns 0 or some other random value.
See $generic_biglist_home or $big_mail_recipient for examples.
Those of the following routines that take a biglist argument are expecting
either {} (empty biglist) or some biglist returned by one of the other routines
:length(biglist) => length(biglist) (i.e., number of elements)
:find_nth(biglist,n) => biglist[n]
:find_ord(biglist,k,comp) => n where n is
the largest such that home:(comp)(k,home:_ord(biglist[n])) is false, or
the smallest such that home:(comp)(k,home:_ord(biglist[n+1])) is true.
Always returns a value between 0 and length(biglist) inclusive.
This assumes biglist to be sorted in order of increasing :_ord values
with respect to home:(comp)().
Standard situation is :_ord returns a number and comp is a < verb.
:start(biglist,s,e) => {biglist[s..?],@handle} or {}
:next(@handle) => {biglist[?+1..??],@newhandle} or {}
These two are used for iterating over a range of elements of a biglist
The canonical incantation for doing
for elt in (biglist[first..last])
...
endfor
is
handle = :start(biglist,first,last);
while(handle)
for elt in (handle[1])
...
endfor
handle = :next(@listdelete(handle,1));
endwhile
The following all destructively modify their biglist argument(s) L (and M).
:set_nth(L,n,value) => L[n] = value
replaces the indicated element
:insert_before(L,M,n) => {@L[1..n-1],@M,@L[n..length(L)]}
:insert_after (L,M,n) => {@L[1..n], @M,@L[n+1..length(L)]}
takes two distinct biglists, inserts one into the other at the given point
returns the resulting consolidated biglist
:extract_range(L,m,n) => {{@L[1..m-1],@L[n+1..]}, L[m..n]}
breaks the given biglist into two distinct biglists.
:delete_range(L,m,n[,leafkiller]) => {@L[1..m-1],@L[n+1..]}
:keep_range (L,m,n[,leafkiller]) => L[m..n]
like extract_range only we destroy what we don't want.
:insertlast(L,value) => {@L,value}
inserts a new element at the end of biglist.
If find_ord is to continue to work properly, it is assumed that the
home:_ord(elt) is greater (comp-wise) than all of the :_ord values
of elements currently in the biglist.
:kill(L[,leafkiller])
destroys all nodes used by biglist.
Calls home:leafkiller on each element.