[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


    Date: Tue, 27 Sep 88 15:12:02 BST
    From: Jeff Dalton <jeff%aiai.edinburgh.ac.uk@NSS.Cs.Ucl.AC.UK>

    How about something like this:

       (defun f (z)
	 (local-type-declare ((z fixnum))
	   #'(lambda () (typed-var z))))

    If I then evaluate (F 10), I may get something like this:

       #<%closure ((z 10)) ... more envs ... () (typed-var z)>

    (TYPED-VAR Z) won't be expanded until I finally call this closure,
    but by then the COMPILER-LET bindings have long since gone.

    I think it was Cris Perdue who brought up this case in one of the
    CL-Compiler meetings.

Only happens in interpreted-only implementations which have no
semantic pre-pass. Why am I not surprised? Sigh...
This case is certainly interesting, but I have a different reading
on what should be done about it.

A very major failing of COMPILER-LET is that it was described operationally
not intentionally, and no good examples of an intended use were given. My
reading of the mail recently is that different people have focussed on
different aspects of its operational definition and regard the aspects they
don't care about as peculiar. If I agreed with the purposes which some have
inferred, I too would be lobbying to have it flushed.

Instead, however, I think we should examine it for its purpose -- which is
to provide convenient cooperation between macros. Given that purpose, I think
it would be interesting to look at how we might fix the operational description
in order to let the example work. One way would be to require such
implementations to close over COMPILER-LET bindings which are lexically visible
to the closure [other COMPILER-LET bindings may be dynamically visible, but are
spurious]. I haven't done a detailed study of that to see if it would work
in complex recursive situations, and I also don't know how hard it would be
to implement that in practice.

    > You can do the same thing with MACROLET, but it feels quite awkward.

    But it works. ...

If you can think of it. I guess I think it's such a radical trick that
average programmers will never think of. 

Issues of caching and side-effects aside, it's like telling programmers they
don't need lexical variables because they can always use FLET....

 (let ((x (cons 3 x))) ...x...) => (flet ((x () (cons 3 (x)))) ...(x)...)

It's yucky because it doesn't let you say what you really mean. You get so 
caught up in mechanism that you lose the expressional abstraction a variable
provides. Further, it's harder than this example because of the need to use
explicit MACROEXPAND and an ENV argument.

It's not that I think average programming problems should need this facility,
but I do think that an average programmer given an unusual programming problem
requiring it should be able to come up with the solution. Assuming COMPILER-LET
was made to work reliably (including the situation described above) and a
reasonable example was provided, I think that an avarage programmer could
think it out. Perhaps I have a dim view of programmers, but in my experience
the average programmer has a hard time with &ENVIRONMENT even in
straightforward situations, much less obscure ones like the example I provided.

Also, the MACROLET version doesn't deal with the issue of side-effects. Offhand
I see now way to use MACROLET to simulate a situation which uses COMPILER-LET
and where a compiler-let variable is re-assigned (by SETQ) in a contained macro
call. The kind of macro where you'd do that would be 


where MY-THE might be like THE, but it could push onto a list of declarations
maintained by WITH-MY-STICKY-DECLARATIONS so that MY-SQRT could be a macro that
knew X was a FIXNUM.