General:. This page generally describes new functionality in the 86 series of revisions and uploads. This is Working Documentation that with maturity will be moved to the Master Documentation. Work on this release addressed the following areas:
Reshape of sequences:
Reshape of sequences was not working properly.
Ancillary Functions and namespace
persistence: There are three examples here. First, I define a function
"a" which in turn defines a function "b".
"b" tests for presence of variable "x"
(i.e. x* = _1 where monadic * means scope which is
_1 if "x" can't be seen.). In the first case,
"x" does not exist and "b" returns early.
In the second case, "x" is given as an argument;
"b" sees it and runs to its end. In the third case,
"x" persists in "a's" namespace and is
thus seen by "b" which again runs to its end.
Initialization using
#IX:
Define the run program. It contains three
ancillary programs: HW, GB, and NC. These are
initialized in the #IX block. The #IX block returns the
string 'Initialized' on returning ( :<- ). In this example I
display this message from initialization. In real life you would probably do
the initialization silently.
$$ == run vvv ============================
'run'#pgm{
$$ -- Initialization ---------------------
#ix{
'HW'#pgm{'Hello World'};
'GB'#pgm{'Good Bye'};
'NC'#pgm{'No Comprende'};
'Initialized' :<-;};
$$ -- program body -----------------------
This is one technique of cleaning up the namespace before running the function. I want to preserve only the ancillary functions in this example. I list them as (.HW .GB .NC). I take a reference to the existing namespace and remove these objects. This gives me a namespace containing everything but this objects. I then take the existing namespace without this conditioned namespace. The result is a namespace containing only the listed functions. I save this in a reference to the name space. I then bring in the arguments.
@ ~(@ ~ (.HW .GB .NC))
=> @; $$ clean up namespace
#args;
$$ fresh arguments
Here I do the actual work. If the argument is 'hello' I run the HW function; else if it's 'bye' I run GB; else I run NC.
:?(x='hello'){HW}::?(x='bye'){GB}::{NC}}; $$ work
$$ == run ^^^ ============================
'<1>'(run)$; Runs the initialization and displays
its message
'<2>'(run) $; Runs with no arguments
'<3>'('hello'[.x]run)$; With valid hello
value
'<4>'('adios'[.x]run)$; With invalid bye
value
'<5>'('bye' [.x]run)$; With valid bye
value
Default Values:. With
Glee's blocks having state, it becomes useful for undefined
variables to have assumed inital values. This eliminates the need for an
Initial Expression in many cases.
Recursion (using
#OP): This is the classical factorial example implemented
using recursion. factorial is implemented here as a monadic user
defined operator. The left argument l__ is tested to return (
:<- ) when it falls to one (or for safety, below 1). If it doesn't
return, it multiples l__ by l__ factorial (the recursive
call). With Glee you need to be careful using functions
recursively. This is because separate invocations of the same function don't
have separate namespaces. Further, in Glee, for safety, I limit
the recursive depth (right now to 40). This is an area I need to explore. In
practice, I don't use recursive functions often. If this restriction becomes an
issue, I'll devise a way to save state before making a recursive call and
restoring it on return ... kind of like I do with arguments using
#arg.