General:. So far I don't see
User Defined Operators (UDOs)as being particularly useful but time will
tell. These examples begin with the basics and then proceed to some of the more
subtle aspects of named blocks. Keep in mind that UDOs are just named blocks in
which zero, one, or two arguments are implicitly supplied to the operator's
namespace.
Simple Dyadic Operators: In
the spirit of Glee, if you are not trying to do anything fancy
Glee doesn't expect much of you. This example shows the use of
the implicit "L__" and "R__" argument
names used in a dyadic sense. But this example is deceptively simple. A dyadic
UDO will fail to produce an intuitive result if not used in the dyadic sense.
Multivalent Operators:
Also in the spirit of Glee, if you need more control and know how
to use it, the functionality is provided. In this example, we create a minus
operator that can behave dyadically, monadically, or niladically. The technique
is to check for arguments. If an "r__" argument exists it
must be dyadic. If and "l__" argument exists it must be
monadic or dyadic (but in the example we already know it's not dyadic when this
test is made). And if neither a right or left argument exists, it is niladic.
But there is an issue. Glee blocks have state. After this
operator runs dyadically, its "r__" and
"l__"arguments are retained. So a subsequent run will be
taken dyadically. To mitigate this situation, I clear the namespace #ns
=> @; and then load the arguments ( #args;)(Note: 030914: This is broken with update 89 and on the todo
list). This clears the state. Note: you can also selectively
prune the namespace with @ ~(.r__ .l__) => @. The operator
definition checks scope with the scope( * ) operator. If the referant
doesn't exist, a _1 is returned. If it is not local a value greater than 0 is
returned. We are only interested in local scope so we make tests like r__
* =0 to be sure we have a value we can use.