Hashes are one of the most common and useful MUF datastructures: They are comparable to Perl's hashes. A MUF hash maps arbitrary keys to values. Internally it is organized as a hashed b-tree, so it can efficiently handle half a dozen keys or half a million keys.
Use makeHash
to create a hash:
root: makeHash --> phone root: phone root: #<Hash _ 4e9c915>
We normally use bracket notation to add and retrieve values from a hash:
root: "234-5555" --> phone["pat"] root: "324-6666" --> phone["kim"] root: phone["pat"] root: "234-5555" pop phone["kim"] root: "324-6666"
If you want to check for the presence or absence of a key without
risking an error condition, use the get?
primitive. The
top return value is the stored value, if any, and the bottom return
value is a t/nil flag indicating whether the key was found:
root: phone["sam"] Sorry: No such property: "sam" root: phone "sam" get? root: nil nil pop pop root: phone "kim" get? root: t "324-6666"
Use ls
to list the contents of an hash:
root: phone ls "kim" "324-6666" "pat" "234-5555" root:
Use foreach
to iterate over the contents of
a hash:
root: phone foreach key do{ key , "\n" , } kim pat root: phone foreach key val do{ key , " " , val , "\n" , } kim 324-6666 pat 234-5555 root:
By default, values in a hash are visible to anyone who can access the hash. You may also store hidden values on a hash, in a space separate from the public one:
root: "666-6666" --> phone$hidden["nsa"] root: "777-7777" --> phone$hidden["cia"] root: phone$hidden["nsa"] root: "666-6666" pop phone$hidden["cia"] root: "777-7777"
Use lsh
to list hidden properties:
root: phone lsh "cia" "777-7777" "nsa" "666-6666" root:
Use foreachHidden
to iterate over the hidden contents of
an hash:
phone foreachHidden key val do{ key , " " , val , "\n" , } cia 777-7777 nsa 666-6666 root:
Use delete:
to remove values from an hash:
root: phone lsh "cia" "777-7777" "nsa" "666-6666" root: delete: phone$hidden["cia"] root: phone lsh "nsa" "666-6666" root: phone ls "kim" "324-6666" "pat" "234-5555" root: delete: phone["kim"] root: phone ls "pat" "234-5555" root:
In addition to the public and private values on a hash, each
hash has system values which are visible to the owner but are
(often) settable only by root. Use lss
to list these system
values:
root: phone lss :dbname "ROOTDB" :isA #<MosClass Object 209fa15> :myclass "obj" :owner #<Root root 2c015> :name "_" root: me lss :dbname "ROOTDB" :isA #<MosClass Root 3a9d015> :myclass "rot" :owner #<Root root 2c015> :hashName 1263705246727446217 :lib #<Object .u.roo%s.lib 91e915> :name "root" :ip3 82 :ip2 182 :ip1 179 :ip0 205 :breakOnSignal 0 :breakEnable 0 :breakDisable 0 :doSignal 0 :debugger 'debug:mufDebugger :doBreak 0 :group 0 :runQueue1 #<JobQueue 1 1020215> :runQueue0 #<JobQueue 0 20115> :psQueue #<JobQueue ps f20415> :pgpKeyprint 0 :pauseQueue #<JobQueue poz ea0515> :objectsOwned 9660 :objectQuota 268435456 :configFns #<Object _ 211fb0000b81de15> :loginHints #<Object _ 211fb0000359cc15> :homepage 0 :haltQueue #<JobQueue hlt e20615> :email 0 :doing 0 :doNotDisturb 0 :defaultPackage #<Package root 422a15> :dbrefConvertErrors 0 :bytes-owned 20714832 :byte-quota 268435456 :packetPreprocessor 0 :dateAtWhichWeLastQueriedUserServers 0 :userServer4NeedsUpdating 0 :userServer3NeedsUpdating 0 :userServer2NeedsUpdating 0 :userServer1NeedsUpdating 0 :userServer4 0 :userServer3 0 :userServer2 0 :userServer1 0 :userServer0 1511201586247629963 :userVersion 8 :hasUnknownUserServer 0 :port 30000 :ioStream 0 :dateOfLastNameChange 0 :originalNickName "root" :lastSharedSecrets nil :lastHashName 0 :lastTrueName nil :lastLongName 0 :sharedSecrets nil :trueName nil :longName 21785844818505190280484762160577916926604332233153169514740797048102153525671947608990996953242732183859349004057149371159606487467804054198140106344292159054364973335175134573886793277186528940143238208826532169922986204369431519881943212123282907303118638555788690891574541957756718153188906349437557021918 :nickName "root" :gagged 0 :rank 100 :timeSlice 125983 :textEditor 'edit:editString :telnetDaemon #<c-fn start> :shell 0 :runQueue2 #<JobQueue 2 fa0315> :timesUsedByMuqnet 0 :lastUsedByMuqnet 0 :firstUsedByMuqnet 0 :packetPostprocessor 0 root:
A package is implemented by a specialized hash object.
Hashes also have an administrative namespace visible and settable only by root,
useful for systems programming. It uses such syntax as obj$admins.val
,
obj$admins["key"]
lsa
and foreachAdmins
.
Use makeIndex
to create Index objects. They have an
interface identical to Hash objects, but internally the keys
are stored in a sorted btree instead of a hashed btree: This saves a
little space (no separate hash value to store) but slows down access
and retrieval a bit (comparing keys is slower than comparing
integer hash values). Indices are especially useful when you
want to list keys in order for display to the user.
Almost everything in Muq is also an index. This makes it easy
to hang random values off of objects without having to redefine
their class every time. The User object me
which represents your
account on the Muq server is an object which is also an index,
for example:
root: me root: #<Root root 2c015> ls :doBreak 'muf:]doBreak :www 0 root: 12 --> me["twelve"] root: me["twelve"] root: 12 pop delete: me["twelve"] root: me["twelve"] Sorry: No such property: "twelve" root:
The backbone of
the internal Muq "file system hierarchy" (actually an object graph)
consists of indices of various kinds. Use a leading "." to explore
it, just as you use a leading "/" to explore the Unix filesystem. Points
of interest include .u
(indexes local users by name),
.etc
(much like unix /etc
), and .folkBy.nickName
(lists known muqnet users by name, both local and remote).
Use makeSet
to create a Set, which is like a SortedIndex whose
value field is alway t
-- this cuts the space needs in half:
root: makeSet --> _x root: t --> _x["b"] root: t --> _x["c"] root: _x ls "b" t "c" t root:
Here is a more compact way of creating Sets, along with an illustration
of set union and intersection operations and the vals[
operator
for extracting an object's set of keys as a stackblock (stackblocks
will be discussed shortly):
root: [ 'a' 'b' 'c' | ]set [ 'b' 'c' 'd' | ]set union keys[ root: [ 'a' 'b' 'c' 'd' | ]pop root: [ 'a' 'b' 'c' | ]set [ 'b' 'c' 'd' | ]set intersection keys[ root: [ 'b' 'c' |
Much the same shortcut and operations are available for Index objects:
root: [ "a" 'a' "b" 'b' "c" 'c' | ]index [ "b" 'b' "c" 'c' "d" 'd' | ]index union ls "a" 'a' "b" 'b' "c" 'c' "d" 'd' root: [ "a" 'a' "b" 'b' "c" 'c' | ]index [ "b" 'b' "c" 'c' "d" 'd' | ]index intersection ls "b" 'b' "c" 'c' root:
Go to the first, previous, next, last section, table of contents.