A major syntactic difference between Lisp and Forth is that Lisp explicitly indicates the lexical scope of every operator via a pair of parentheses. This results in a lot of syntactic noise, but does make it easy to cope with operators which take a variable number of arguments.
Forth, by contrast, almost never explicitly indicates the lexical scope of an operator, and in consequence almost all operators are forced to take a fixed number of arguments. This reduces syntactic clutter enormously, but the inability to deal with variable numbers of arguments can be almost crippling at times.
The tinymuck MUF coding community has evolved a workaround for this problem, which consists of passing a block of values on the stack, with a count of the number of values in the block sitting atop it.
Muq MUF systematizes this ad hoc practice by providing a consistent syntax for such operators, and by providing a general set of tools for manipulating such stack blocks. The result is that the MUF programmer can frequently operate very concisely on complete blocks of data without writing explicit loops, with a gain in notational conciseness vaguely similar to that achieved by APL, and much more closely related to that achieved by unix shell commands using pipes. In honor of the latter, the Muq MUF syntax is chosen to be somewhat suggestive of that used by unix shells for constructing pipes, although the underlying implementation mechanisms are very different.
The general syntactic MUF conventions for dealing with stack blocks are:
Names of functions depositing a block on the stack end with '['. Names of functions which transform a block on the stack start with '|'. Names of functions which pop a block off the stack start with ']'.
These conventions provide immediate, obvious warning to anyone reading the MUF code that block operations are taking place. In addition, given these conventions, a few simple syntactic code-writing rules make it easy to write reasonable block code, and to spot questionable block code at a glance:
Every '[' should be folloed by a matching ']'. Every ']' should be preceded by a matching '['. Every '|' should be between a '[' ... ']' pair.
Given appropriate functions, a variety of useful computations become quite simple to do interactively in a coding style reminiscient of unix filters. For example
.who vals[ "z*" |grep |length -> i ]pop i
is a plausible command to count the number of people currently logged in whose name starts with 'z'. We assume here that:
vals[pushes all keys on a given object on the stack in a block.
|grepremoves all keys not matching a regular expression from block.
|lengthcounts the number of items in a block.
]popremoves a block from the stack.
(At present, all the above operators are implemented exept
|grep; implementation of regular expressions is still
at an early stage.)
WARNING: Stack blocks are currently implemented as simply N args on the stack with an integer count atop, but code should not be written to depend on this. A future version of Muq is likely to use a special top-of-block indicator rather than just an integer. Use the provided functions to construct and manipulate blocks.
Go to the first, previous, next, last section, table of contents.