From: budden on 27 Dec 2009 10:25 Hi List! http://paste.lisp.org/display/92680 ? (macroexpand-1 '(with-conc-name x symbol x.name)) (PROGN (SYMBOL-NAME X)) ? (defstruct long-structure-name fld1 fld2) ? (macroexpand-1 '(with-conc-name x long-structure-name (list x.fld1 x.fld2))) (PROGN (LIST (VERY-LONG-STRUCTURE-TYPE-NAME-FLD1 X) (VERY-LONG-STRUCTURE-TYPE-NAME-FLD2 X))) We really don't need to know accessor names to make this with- construct. Just look what user would enter and only then check if there exist appropriate accessor or not. I seldom use CLOS, but I think two extensions to with-conc-name might be useful. I might want to transform x->foo to (foo-of x) [Thanks, Lars], and maybe x-->foo to (slot-value x 'foo) Well, now CL is about to approaching a state where I can really start enjoy writing code in it and reading what I have written...
From: budden on 27 Dec 2009 10:31 Oops, docs were wrong. See http://paste.lisp.org/display/92680#1
From: budden on 29 Dec 2009 05:23 Hi Lars! I'll try to establish why my solution is better. 1. Readtables seem to increase complexity, if we're talking about portable solution. SLIME can switch package-associated readtable as you switch packages. I'm not sure Lispworks and Allegro can do so. 2. At one time, you can refer to one object only. With my macro, there is no such limitation. Also, you see, you're not bound to objects at all: (with-conc-name x symbol (with-conc-name y universe (setf y-->name x.name))) Also, it might be reasonable to combine several things and approach static typing. E.g. (with-typed-object (x (make-instance 'universe) universe) (x.some-method x-->half-truth-a)) Which would expand as (let ((x (make-instance 'universe))) (declare (type universe x)) (universe-some-method (slot-value x 'half-truth-a))) The question is if mapping a code tree is a reliable technique to find all instances of x.y symbols. How would it interact with macroexpansion? It seems all should be ok, but still I'm not sure.
From: budden on 29 Dec 2009 07:32 >(with-typed-object (x (make-instance 'universe) universe) > (let ((x (make-instance 'cow))) > (x.run x-->size))) This is general problem of lexical binding, not that of suggested macro. One can just write without any macros: (let ((x (make-instance 'universe))) (let ((x (make-instance 'cow))) (cow-run x (slot-value x 'size))))
From: budden on 29 Dec 2009 13:03
> Yes, but this is a case your code walker in your macro will have to > deal with. I see. Well, for now I'd prefer just not to bind x inside (with-typed-object (x ...)) I have already mentioned in a docs that I have no code walker, I just replace symbols by their names. Strictly speaking, this is an incorrect behaviour, but I don't care... Documented bug is a feature :) It took me an hour to write and debue my macro, and I believe it is useful. Writing a code walker would take couple of days. Why bother myself with it? When you look at SLIME, there is rather similar with-struct*, it is implemented with macrolet and would suffer from the same problem. Then, why should I care? Well, ok, I mean patches are welcome :) |