[Date Prev] [Date Next] [Thread Prev] [Thread Next] Date Index Thread Index Search archive:
Date:Mon Jul 20 14:28:00 1993 
Subject:get_results and & 
From:jonr (Jonathan Rowe) 
Volume-ID:930720.04 


In case it slipped your memory, what I've been trying to do is define an
infix operator & such that:

    (f & g)(...)
means:
    g gets its arguments, f gets its arguments, f runs, g runs

And to do this I wanted a function get_results such that

    get_results( p )

returns a list of the results of running p.

The problem centred around not knowing how many arguments p would take off the
stack at any one time, and pdnargs is not to be trusted. Here at last is a
solution.

The gist is as follows. Move the stack into a list "thestack". Then one by one
put things from this list back on to the stack. At each stage, try running p.
If it throws a STACK EMPTY mishap, then you need to try more arguments. If
not, then you've done it. Make a new list out of the results on the stack and
throw the remnant of "thestack" back on to the stack. (The word "elegant" does
not exactly leap to mind...)

So first we have a function try(p) which returns false if p throws a STACK
EMPTY error when run, otherwise p is run and true is returned.


;;; returns false if stack empty error, true if successful
define try( p );
    define prmishap(s, l);
        if issubstring('STACK EMPTY', 1, s ) then
            false;
            exitfrom( try );
        else
            sysprmishap( s, l );
        endif
    enddefine;
    p(); true;
enddefine;

Now we can do get_results, using "thestack" to store all potential arguments
and iteratively putting them onto the stack in the correct order:


define get_results( p ) -> list;
    lvars p list thestack item n flag i j;

    stacklength() -> n;
    conslist( n ) -> thestack;      ;;; store the stack somewhere

    true -> flag;
    for i from 0 to n do            ;;; i is number of args to try
        clearstack();
        for j from n-i+1 to n do    ;;; j indexes the top i args
            thestack(j);
        endfor;
        try(p) -> flag;
        quitif(flag);
    endfor;
    unless flag then                        ;;; it's a genuine underflow
        mishap('STACK UNDERFLOW', [^p]);
    endunless;

    conslist( stacklength() ) -> list;      ;;; this is the answer
    explode( allbutlast(i, thestack) );     ;;; throw remnant back
enddefine;


And finally we can do the & operator with ridiculous ease:


define 5 &( f, g );
    lvars f g;
    procedure();
        lvars g_results;
        get_results(g) -> g_results;
        f();
        explode( g_results );
    endprocedure;
enddefine;


And now you can use & at your leisure and convenience!

Jon Rowe