Message from discussion
What's the point of flet?
Newsgroups: comp.lang.lisp
Path: archiver1.google.com!news1.google.com!newsfeed.stanford.edu!newsfeeds.belnet.be!news.belnet.be!news2.euro.net!news.euro.net!uunet!ash.uu.net!world!pitman
From: Kent M Pitman <pit...@world.std.com>
Subject: Re: What's the point of flet?
Sender: pit...@world.std.com (Kent M Pitman)
Message-ID: <sfwk7xb4s4g.fsf@world.std.com>
Date: Wed, 31 Oct 2001 17:49:19 GMT
References: <3BDF119D.A51C178B@yale.edu>
<m2vggwlk84.fsf@mycroft.actrix.gen.nz> <sfwpu74hban.fsf@world.std.com>
<mt30utk9sppidrbss4fh9d0n52s3lipq2b@4ax.com>
Organization: The World Public Access UNIX, Brookline, MA
X-Newsreader: Gnus v5.3/Emacs 19.34
Lines: 89
Francis Leboutte <f.lebou...@algo.be> writes:
> Kent M Pitman <pit...@world.std.com> wrote:
>
> >Paul Foley <mycr...@actrix.gen.nz> writes:
> >
> >> But that's illegal -- you're not allowed to redefine names exported
> >> from the COMMON-LISP package.
> >
> >Believe it or not, some functions that exist and require overriding are
> >your own.
> >
> >(defun square (x) (* x x))
> >
> >(flet ((square (x)
> > (make-instance 'square :area (square x))))
> > ...)
> >
>
> It would be nice to have the possibility to make the new binding of square have
> dynamic scope. I think an equivalent of the dynamic variable notion for a
> function defined locally would be useful in CL.
The language doesn't actually need this functionality. It would
mostly be abused.
In the case that someone besides yourself wrote the function you wanted
to locally clobber with dynamic-flet, you're really violating all normal
modularity ethics. You aren't responsible for their code, you can't know
with certainty who their clients are, and you're just asking for trouble.
(It's fine for users to write it if they have to, since
then they can take moral responsibility for the consequences, but absent an
example of a legitimate use of this, I think we made the right decision
in excluding this. In most cases where you know you need this, it suffices
to simply bind a special variable and have a function call another function
indirect through the special.)
If you really wanted to patckage it up, it would look something like this:
(eval-when (:execute :compile-toplevel :load-toplevel)
(defvar *dynamic-flet-package*
(or (find-package "FLET INDIRECTION")
(make-package "FLET INDIRECTION")))
(defun make-flet-indirection (symbol)
(intern (let ((*package* (load-time-value (find-package "CL"))))
(format nil "*DYNAMIC-FLET ~S Indirection*" symbol))
*dynamic-flet-package*))
);nehw-lave
(defmacro make-dynamically-flettable (name)
(let ((indirection (make-flet-indirection name)))
`(progn
(defvar ,indirection (symbol-function ',name))
(defun ,name (&rest args)
(declare (dynamic-extent args))
(apply ,indirection args))
',name)))
(defmacro dynamic-flet (fbindings &body forms)
`(let ,(mapcar #'(lambda (fbinding)
(destructuring-bind (op &rest lambda-exp-tail) fbinding
`(,(make-flet-indirection op)
#'(lambda ,@lambda-exp-tail))))
fbindings)
,@forms))
;; Sample use
(defun foo (x) (+ x 3))
(make-dynamically-flettable foo)
(defun bar (x) (foo x))
(bar 4) => 7
(dynamic-flet ((foo (x) (+ x 4)))
(bar 7)) => 8
Note that there are some tricky issues here if you end up needing to
redefine the original FOO, but if FOO is a function you yourself maintain,
such that you hae the right to be doing this operation at all, you can usually
control those cases.