We all know that
(f <> g) (x)
is equivalent to
g( f(x) )
but how about combining functions with more than one argument?
Let's have
(( f & g ) <> h)( x, y )
equivalent to
h( f(x), g(y) )
We can do this as follows (as long as pdnargs is not a fictitious quantity):
define 6 &( f1, f2 ) -> p;
lvars f1 f2 p n1 n2;
pdnargs( f1 ) -> n1;
pdnargs( f2 ) -> n2;
procedure();
lvars a1 a2;
conslist( n2 ) -> a2;
conslist( n1 ) -> a1;
explode( a1 ); f1();
explode( a2 ); f2();
endprocedure(%%) -> p; ;;; see note below
n1 + n2 -> pdnargs( p );
enddefine;
and then we can do nice things like:
: vars foo = [ [1 a] [2 b] [3 c] ];
: syssort( foo, hd & hd <> nonop > ) =>
** [[3 c] [2 b] [1 a]]
Note on bizarre use of closure:
If you set up a procedure which makes use of a lexical variable from an
enclosing scope, you can't update the pdnargs of it.
define foo(a) -> p;
lvars a p;
procedure();
lvars x;
-> x;
[^x ^a];
endprocedure -> p;
1 -> pdnargs(p);
enddefine;
: foo(1) -> baz;
;;; MISHAP - CAN'T ALTER PDNARGS
;;; INVOLVING: <procedure>
;;; DOING : pdnargs foo compile pop_setpop_compiler runproc runproc
compile pop_setpop_compiler
Making it a closure cures this. I'll submit a bug report on this unless
someone quickly comes up with a very good reason for this behaviour.
( While I'm whinging, I also consider it highly undesireable for the error
trace to include the list "compile pop_setpop_compiler runproc runproc
compile pop_setpop_compiler" ).
Jon Rowe.
|