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] |
mdj@nada.kth.se writes: > This mechanism wasn't based on your code, but was, what was supposed > to be, an improvement on the mechanism in STk which also is Common > Lispish. > I hardly take responsibility for the interface, it has been reinvented many times. I was just referring to my code by way of contrast. > > 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 agree. I think it should complain. > > I made a thought error (Christian's code was OK, but I added the > strange stuff) when implementing this. I must have thought about > dynamic properties one second and static in the other. Sorry. :( > > > 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? > > It was supposed to be an implementation of Common Lisp's generalized > locations, where getters and setters can be special forms. > Scheme does not have any standard getters or setters that are special forms. I don't believe such a thing should happen either. Getters or setters that are macros _may_ be useful but I don't think they are more useful than dynamic behavior. > On the other hand I don't see a strong need to have dynamic > behaviour. There is a reason why `set' wasn't included in RnRS. > E.g., in your example above I think it would be more natural to write > > (mutate-cons-cell set-car! my-cell 'x) > > or > > (mutate-cons-cell (setter car) my-cell 'x) > > and > > (define (mutate-cons-cell setter cell new-value) > (setter cell new-value)) > > (I'm aware that you wrote the code above to demonstrate my bug, which > it excellently did, not to show a typical usage of dynamic setf!.) > > In fact, the point of doing a thing like > > (set! (car x) 3) > > is to get better syntax. It's supposed to be "syntactic sugar". > If you let the cadar be a variable, it seems to defeat the purpose to > yield clearer code. > > I'll change the implementation to a purely static one. I think a purely dynamic one would be more in the spirit of Scheme. I realize my example of dynamic use of setf! is not a truly useful example, but I believe such examples exist. For instance, some procedures may have anonymous setters. Suppose I defined `first' through `tenth' as well as having `cadr' and `cdddr' and such things, and all of these had setters associated, but none of those setters had names. (set-tenth! and set-cdddr! would certainly be bloat, and not having to have such things is part of the problem setf! is supposed to solve). Now suppose I do (define (swap-list-structure-locations! list-structure accessor1 accessor2) (let ((value1 (accessor1 list-structure)) (value2 (accessor2 list-structure))) (setf! (accessor2 list-structure) Yes, I realize a generic swapf! macro would be a more general solution, I am just suggesting that dynamically passing around procedures is a much more common paradigm in Scheme than Common Lisp and so people will attempt to apply that to setters and lose. I also realized that the above code is somewhat broken, since if the first setf! changes the list in such a way that the other accessor no longer accesses the same location, the result will be totally wrong. I was going to suggest that the complexity in Common Lisp's setf was there to make swapf and psetf work right, but this is not the case Common Lisp psetf is subject to the same bug as the above code. Another case where dynamism would be useful: suppose I do (define (make-point x y) (list x y)) (define point-x car) (define point-y cadr) It sure would be nice to have setters for point-x and point-y for free. It also seems to me that deriving the mutator from the accessor could be useful in the context of records or object systems. Yet another case where I think dynamic setf is useful (again a vague prototypical example, not meant to be real code): (define (make-toggling-cell initial-state value1 value2) (cons initial-state (cons value1 value2))) (define (toggling-cell-toggle! tcell) (set-car! tcell (not (car tcell)))) (define (toggling-cell-ref tcell) ((if (car tcell) car cdr) (cdr tcell))) (define (toggling-cell-set! tcell value) (setf! ((if (car tcell) car cdr) (cdr tcell)) value)) Note the informative parallelism between the last two definitions. And as a final note, Common Lisp does not allow macros to have setf methods defined - it macroexpands the place form if the first position of the form refers to a macro - and it appears to require setf-methods to be functions as well, at least as I read the relevant section of CLtL2 (http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node80.html). I don't believe that adding this capability is a useful extension. All in all, I think dynamic setf without macro getters or setters would be much better. - Maciej