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] |
Chris.Bitmead@misys.com.au writes:
> dispatch_table[scm->type]->display(scm);
>
> I can't see that it could be inlined beyond this because we don't know the
> run-time type.
Let's say that we're compiling module B which imports bindings
read-only from module A, among them the variable x.
In our program we have the expression
(display x)
Let's now assume that x is a free variable, i.e., it is not shadowed
by any local binding, but refers to the imported, read-only, x.
Then we can trust x always to be of type T, so that we can compile
(display x)
to
display_T (x);
If x is the string "Hello World!\n", we can go further:
printf ("Hello World\n");
Note how this depends on the compiler's ability to determine a
constant bond between x and "Hello World\n". If this binding was
dynamic, we couldn't compile it to the last statement above.
> Similarly, I would have thought a set! could be inlined as
> dispatch_table[scm->type]->set(scm, value);
I don't understand how the above expression relates to the current
discussion. What is `scm'? Note that what set! needs to do is to
find the setter which is associated with the getter being used in the
expression. It is not a question of type dispatch.
> It's not obvious to me how the idea of instead changing the procedure
> object is "more local". A "plain dynamic dispatch set!" would be re-using
> an idea already in the language.
I have not talked about "changing" the procedure. The proposal means
making a new procedure from the getter and the setter.
With "plain dynamic dispatch set!" I thought you were referring to the
old proposal which meant associating the getter with setter by use of
a procedure property (which, BTW, is not a standard Scheme feature).
Did you refer to something else?
The new proposal is more local because instead of relying on a
mechanism which can associate setters to *any* procedure, we restrict
this bond to procedures constructed with make-procedure-with-setter.
> But what I don't get is why we want to map procedures to setters at
> all. Surely what we want to do is map types to setters. After all
> it is going to be the type of the object we are trying to set a
> member of which determines which setter to use.
>
> I must be missing something big here.
Yes, this is probably the main cause of the confusion.
The "generalized" set! idea is exactly about mapping getters to a
setters. Here are two examples of how set! expressions are
transformed:
(set! (car x) y) --> ((setter car) x y)
(set! (cdr x) y) --> ((setter cdr) x y)
Obviously, we want (setter cxr) to return set-cxr!.
Note that both setters work on the same type: a pair.
What determines which setter to use is the *getter* we're using.
> > We also avoid associating a setter slot with each procedure.
>
> But who really wants to associate setter slots with procedures?
The old proposal did this (using set-procedure-property!).
> >It's a bit sad that I'm the only one that previously tried to protect
> >the simplicity of the language.
>
> I think it's more a case of everyone having a different idea of what
> protecting the simplicity of the language actually means.
In my case it meant advocating for not extending the set! form, but
require that the first argument is a variable name.
But now I've changed opinion: The new solution doesn't do anything
strange. It basically adds a constructor (an ordinary procedure)
which takes standard Scheme types (procedures) and return a standard
Scheme type (procedure). There's no need of a table, and the
extended set! form can be compiled to efficient code.
> My concern is not that your idea is or isn't efficient. It is that
> the whole design seems to rely on being able to modify the guts of
> the system in order to be able to implement efficiently. If I were
> to take some arbitrary R5RS Scheme, and without modifying it try to
> implement this scheme, I would need some ugly form of table lookup
> or something (I think).
Here's a plain (untested) R5RS implementation:
(define make-procedure-with-setter #f)
(define getter #f)
(define setter #f)
(let ((getter-cookie '(cookie))
(setter-cookie '(cookie)))
(set! make-procedure-with-setter
(lambda (getter setter)
(lambda args
(cond ((eq? (car args) getter-cookie) getter)
((eq? (car args) setter-cookie) setter)
(else (apply getter args))))))
(set! getter
(lambda (proc)
(proc getter-cookie)))
(set! setter
(lambda (proc)
(proc setter-cookie))))
The set! form in the prototype implementation is already R5RS (except
for the way to write macros).
If anyone can find a better design, which still can be compiled to
efficient code, I'd be very happy to see it.
/mdj