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


Per Bothner <bothner@cygnus.com> writes:

> > I oppose "dynamic" setf! because I don't like the combination of being
> > an elementary operation (storing a value in a location) and being hard
> > to compile to efficient code.
> 
> It is quite easy to compile extended set! to efficient code.
> You just have an slot associated with each procedure, and
> generate code to extract and call the setter procedure in that slot.
> One extra indirection for a setter call is quite reasonable in the
> scheme of Scheme.
> 
> Also, I don't see that "storing a value in a location" is an
> "elementary operation".  Storing a value in a data structure
> (the main use of extended set!) can be quite complicated.
> Even storing a value in a simple variable can be rather
> complicated when you have to deal with closure analysis,
> or thread-local (fluid) variable.

While "the scheme of Scheme" means dog slow right now, I don't see why
Scheme code couldn't be compiled into near-C-speed in the future.

One indirection isn't much in itself, but if it means a barrier which
prevents inlining it could mean a lot.

However, I realize that excluding the mutator for the setter-binding,
instead using your suggestion to create a new object:

> (define foo
>   (bind-settable-pair
>     (lambda (args ...) ...) 
>     (lambda (rhs args ...) ...)))
> 
> where bind-settable-pair creates a new procedure object containing
> the specified getter and setter actions.

and combining this with read-only bindings in the module system will
allow the compiler to do inlining.

This means that there only remains two of my arguments against a
dynamic setf! (which may be called set! if it is included in the
core):

1. Are the benefits worth the extra complexity added to the language?

   Before, we only had bindings from syntactic keywords to macros and
   bindings from variables to locations (I here assume that we'll
   remove the current variable objects when we switch module system).

   I objected to introduce a new type of binding between procedures.

But if we skip the mutator and use your construction above, we no
longer have such a binding between arbitrary procedure objects, but
rather a new type of procedure object.  To me, that is OK.  Is it OK
for everybody else?  Should we extend Guile Scheme in this way?

2. Are the added constraints when writing new interpreters and
   compilers acceptable?

Again, since we no longer need to look upon it as a new type of
binding, for me it is OK.


Look!

You've convinced me.

I now support the idea of a dynamic setf!.

Note, however, that in order for this to work, car and friends needs
to be of this procedure type.  This means slowing down the interpreter
slightly until we have got a special protocol built into the module
system which allows inlining.

Maybe, for that reason, we can introduce the mechanism now, letting
people redefine their car if they want to, but postpone turning car
and friends into settable pairs until we get this protocol in the
module system.


I suggest using different names:

constructor: (make-procedure-with-setter GETTER SETTER)
selector:    (procedure-getter PROCEDURE-WITH-SETTER)
selector:    (procedure-setter PROCEDURE-WITH-SETTER)


If our `define-class' macro binds accessors, there now occurs the
question whether we should let the method of the getter generic
function be a procedure-with-setter or if the getter should be a
procedure-with-setter consisting of a generic function getter and
setter.

The former alternative (method is p-w-s) requires that set! does the
method lookup.  The second requires that define-generic and
define-method knows about procedure-with-setters.

I think the former alternative is most natural.

/mdj