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)

Reply via email to