This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: setf.scm


Maciej Stachowiak <mstachow@mit.edu> writes:

> A setf! implementation in the form of setf.scm has been added to
> guile.

Yes!  setf helps a lot as the size of a program grows.

> This differs most markedly from code I posted a while back (with a
> similar interface but rather different implementation) in that setter
> is a macro, and setf! attempts to determine the setter of the passed
> procedure at macro-expansion time, not run-time. I think this is a bad
> idea because it _appears_ to be dynamic, by being based on the
> procedure object rather than the symbol, unlike Common Lisp, but it
> actually isn't because of the macro-expansion property described
> above.

I'm a big fan of setf doing it's work at compile time.  Why?  Because
it's relatively easy for programmers to whip up some generic closures,
or wrap 'setf' forms in lambdas, but relatively difficult to implement
a macro-based 'setf' facility.  It gives Scheme programmers access to
a previously inaccessible point on the speed/dynamism tradeoff curve,
and we've already got access to the completely dynamic end of the
spectrum.

Just wondering: why not follow the Common Lisp implementation
strategy, and use the symbol to look up the setter?  Would this solve
the problem you describe (there must be some other cost)?

> For instance, code like this:
> 
> (define (mutate-cons-cell accessor cell new-value)
>   (setf! (accessor cell) new-value))
> 
> (define my-cell (cons 3 4))
> (define my-cell (cons 3 4))
> 
> (mutate-cons-cell car my-cell 'x)
> 
> (mutate-cons-cell cdr my-cell 'y)
> 
> Will silently do the shockingly unexpected wrong thing and leave
> my-cell with a value of (y . 4), whereas a fully Common Lisp-like setf
> would have complained, and my code would have done the right thing. I
> think the current code is thus the worst of all possible worlds,
> semantics-wise. (I predicted this on reading the code, but testing
> confirms).

I would expect the above code to complain at macro expansion time that
there is no setf method for "accessor".  I basically agree that this
in-between behavior is the worst of both worlds.  Either guile should
have a dynamic setf, or it should have one that forces the computation
to be determined at macro-expansion time.  Therefore, I would be happy
with a setf facility that made it impossible to write
"mutate-cons-cell".

> Performance-wise it may be a bit better than what I posted but I don't
> think that's a good enough justification for the misfeature described
> above.

Well I have to agree that the above code does violate the principle of
least surprise.

> I also don't think it is useful to allow getters and setters to be
> macros (and obviously that can't be done with the non-memoizing
> version where setter is a procedure since code written to use that
> with macros would be utterly uncompilable). Is there a particular
> purpose that was envisioned for?

Getters and setters should be macros for speed.  If you need dynamism
the you can create lambdas around them.  It sounds like there is some
reason that this is impossible in guile; could you explain why?

-russ

--
"There are only two industries that refer to their customers 
as 'users'." 
             -- Edward Tufte