[comp.emacs] `let' question

rar (Bob Riemenschneider) (10/10/90)

=>   From: reingold@emr.cs.uiuc.edu (Ed Reingold)
=>   Newsgroups: gnu.emacs
=>
=>   Does the let mechanism in GNU Emacs Lisp allow a function to be redefined
=>   in the same way a variable can be?  I want to do something like this:
=>
=>   (defun silly ()
=>     (forward-char 1))
=>
=>   (defun ridiculous ()
=>     (backward-char 1))
=>
=>   (defun idiotic ()
=>     (let (('silly 'ridiculous))
=>	(silly)));;  I want this to be a call to move backward one character

Short answer: No, because let handles changes to the value cell, but not
   the function cell.  (Take a look at specbind and let in src/eval.c.)

Longer answer: You can define a macro to do what you want.  Basically, you'd
like 

   (defun idiotic ()
     (rename-function-let ((silly ridiculous))
        (silly)))

to expand to something like

   (defun idiotic ()
     (let ((tmp (make-symbol "tmp")))
        (fset tmp (symbol-function 'silly))
        (fset 'silly (symbol-function 'ridiculous))
        (set tmp (silly))
        (fset 'silly (symbol-function tmp))
        (symbol-value tmp)))

or, if you're feeling really silly,

   (defun idiotic ()
     (let ((silly (make-symbol "silly")))
        (fset silly (symbol-function 'silly))
        (fset 'silly (symbol-function 'ridiculous))
        (set silly (silly))
        (fset 'silly (symbol-function silly))
        (symbol-value silly)))

More generally, you really want a defun-like syntax, with renaming as a
special case.  Thus, you'd define idiotic as follows

   (defun idiotic ()
     (flet ((silly () (ridiculous)))
        (silly)))

where

   (defun fname (fbinding)
     (car fbinding))

   (defun fvars (fbinding)
     (car (cdr fbinding)))

   (defun fbody (fbinding)
     (car (cdr (cdr fbinding))))

   (defmacro flet (fbindings body)
      (list 'let '((tmp (make-symbol "tmp")))
            (list 'fset 'tmp 
                  (list 'symbol-function (list 'quote (car (car fbindings)))))
            (list 'fset (list 'quote (fname (car fbindings)))
                  (list 'quote 
                        (list 'lambda 
                              (fvars (car fbindings))
                              (fbody (car fbindings)))))
            (list 'set 'tmp body)
            (list 'fset (list 'quote (fname (car fbindings))) 
                  '(symbol-function tmp))
            '(symbol-value tmp)))

(The generalization to flet-ing multiple symbols is left as an exercise.)

							-- rar

reingold@emr.cs.uiuc.edu (Ed Reingold) (10/10/90)

rar's solution to my problem is nice, but it needs to be expanded to
include unwind-protect'ion to prevent permanent destruction of the original
function in the case of an error or some other interuption.
--

Professor Edward M. Reingold                  reingold@cs.uiuc.edu
Department of Computer Science                (217) 333-6733
University of Illinois at Urbana-Champaign
1304 W. Springfield Ave.
Urbana, IL 61801-2987  USA

worley@compass.com (Dale Worley) (10/12/90)

   From: think!news@ux1.cso.uiuc.edu  (Ed Reingold)

   Does the let mechanism in GNU Emacs Lisp allow a function to be redefined
   in the same way a variable can be?  I want to do something like this:

No.  The "function" of a symbol is different from its "value", and let
only binds values.  Of course, you can do something like:

(let (temp)
  (setq temp (symbol-function 'silly))
  (fset 'silly (symbol-function 'ridiculous))
  ...
  (fset 'silly temp))

Dale Worley		Compass, Inc.			worley@compass.com
--
I don't even know what street Canada is on.  -- Al Capone