On Wed, 13 Oct 2004, Gerhard Schellhorn wrote:
As far as I understand your approach, the idea behind it is clever, that for sure, but you are nevertheless trying to abuse your Lisp here. I haven't had a look at the standard, but trying to let a named function change its own definition feels a lot like bad hacks in C where you try to squeeze more than one side effect into an expression that does not contain a sequence point (such as a^=b^=a^=b); if I got you right, you are essentially talking about self-modifying code here (only that you also use the compiler at run-time). This is almost bound to violate guarantees that every system at least implicitly assumes to be given, even if this may not be spelled out in detail in the docs. (I nevertheless strongly presume it is somewhere.) Plus: it can be avoided without giving up more than a few per-cent of performance. > Now the implementation of rewriting is as follows: > Generate a Lisp function f for every function > symbol f. Calling f with a term t as argument > rewrites the term "f(t)". If the only rewrite > rule that has f as the toplevel function symbol on the > left side is f(g(y)) => h(y) then this function does > the following: Check if the argument x has the form '(g u) > with some term u. If not just return '(f t) otherwise How do you do that check? Please do not tell me you stack such checks one onto another to generate essentially a compiled linear search if you add more and more rewrite rules. > call Lisp function h on u to simplify the term '(h u). > So the generated code for f is > > (lambda (x) > (if (eq (car x) 'g) (g (cadr x)) `(h ,(cadr x)))) You use symbols as rendez-vous points to name and identify rewrite rules in your program. Fine with me, but if you want the compiler to generate code that explicitly calls SYMBOL-FUNCTION for global variables at run time, why don't you write your code in such a way as to make this explicit. (funcall (symbol-function ...)). As this is machine-generated code anyway, you will not have to type it every time. > '(lambda (x) (comp f (generate rewrite-rules-of-f)) (f x)) > > to avoid generating the (usually complex) lambda expression at all, if f > is never called (I typically have specifications with some hundred function > symbols and several thousand rewrite rules). What you want here is laziness. Do not use SYMBOL-FUNCTION, use SYMBOL-VALUE instead, and use some "lazy" container type. See e.g. http://www.cip.physik.uni-muenchen.de/~tf/misc/lisp/lisp7.txt > Function generate > is rather complex (around 5000 lines of code) since actually > terms of a higher-order logic are rewritten modulo associativity > and commutativity, so I don't want to do a complete reimplementation. Sometimes, the best way to write it is to re-write it. One of the major advantages of Lisp over C and other bare-metal-only languages is that it is very easy to throw away bad code. Once a C programmer got something that works, he would rather bite off his hand than throwing it away and replace it by something better, stingier. Very bad habit. Don't worry. I've been writing ~ 40 000 lines of lisp code for my PhD work, and I've perhaps thrown away twice that amount over the years. > Changing a rewrite rule for f causes recompilation of f, > so I need to dynamically change the function definition. > > To debug the rewriting I can simply call the appropriate > function on toplevel, trace the function calls etc. which > is very convenient. That seems impossible to me if I use > local functions. How about doing it along the lines[sic!] of (defun f (funcall (symbol-value 'f))) (with some more support for laziness sprinkled in) so that you never have to change this function definition? -- regards, [EMAIL PROTECTED] (o_ Dr. Thomas Fischbacher - http://www.cip.physik.uni-muenchen.de/~tf //\ (lambda (n) ((lambda (p q r) (p p q r)) (lambda (g x y) V_/_ (if (= x 0) y (g g (- x 1) (* x y)))) n 1)) (Debian GNU)
