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] |
Maciej Stachowiak <mstachow@mit.edu> writes: > > jimb@red-bean.com writes: > > > > Yes, I'm opposed to adding variable tracing to Guile at the Scheme > > level. > > > > People need to have some sense of which code could be run in response > > to a particular action; if setting a variable causes new font metrics > > to be downloaded (for example), or some other huge and complicated > > action, then that principle is kind of broken. > > > > If an operation is going to do something weird and expensive, it > > should be syntactically apparent; it could look like a function call, > > for example. > > > > I don't see a major advantage to writing: > > > > (set! parameter value) and parameter > > > > instead of > > > > (set-parameter! value) and (parameter) > > > > especially since it's clear that the latter might do significant > > work. The payoff isn't worth the ugliness it adds to the language. > > Jim and I have had this exact same discussion before, and I doubt > either of us will ever convince the other, However, for the record, > here are the reasons I think the above _is_ a problem: > > * For a program with many configurable settings, the user should not > have to know, care or remember which parameters, when set, will > trigger extra processing immediately. It's often not even intuitively > obvious which will and which won't. Then let the program's entire public interface be through functions. > * Many configurable settings are done just plain wrong because it > would be more of a pain for the implementor as well as the user to > write to procedures rather than define one variable. > > For example, hooks are implemented as variables expected to contain > lists of procedures, in Guile as well as in Scwm (for consistency). > > As another example, paths "%load-path", e.g. are implemented as > variables that contain lists of strings, forcing any path-searching > code to scan the list twice on each path search, first to make sure it > really is a list of strings (and save their lenghts), and then to do > the real work. > > In both of these cases, it would be nice for the variables in question > to get typechecked when assigned, rather than on each use. Separate > setter and getter procedures might be better from a language > cleanliness point of view, but they are not really being used, even by > guile core, when they should be. > > * Macros exist which do interesting manipulations of variables; they > are unusable on getter-setter pairs (unless Guile gets a generic > setter facility like Common Lisp's setf and starts using it, which I > think is also a good idea. In fact, I wrote one in Guile Scheme a > while back, but I'm not sure if anyone is interested). I agree on the need for an encapsulation mechanism to separate impementations from interfaces. I think Scheme's austere syntax is a hurdle for programmers who Want to Do the Right Thing. Furthermore, I recoil at the notion of standardizing conventions that involve sticking prefixes on the string representation of a symbol to generate interface functions. I can live with Jim's earlier proposal (if it was that) of a convention whereby one procedure serves as both getter and setter: (my-prop 5) (my-prop) => 5 However, it would please me (if it's not too deadly to implement) to see functions allowed to return set!-able references: (set! (my-prop) 17) (my-prop) => 17 This has the (to my mind) intuitive benefit that the code "(my-prop)" acts just like a symbol as far as the public's concerned. (While I'm at it, I'd argue for (set! (array-ref a 6) 'zork) etc. as a clean alternative to setf.) This discussion reminds me of a rule I adopted early while learning C++: no self-respecting class should have any public data members. All access should be through functions. I don't see why the same shouldn't apply for Scheme packages. Of course, in C++ you can inline the functions and do things like the following quick fix of someone's unenlightened code: /* * Was: * struct foo { * int bar; * int baz; * }; */ class foo { private: int _bar, _baz; public: const int& bar() const { /* do stuff */; return _bar; } int& bar() { /* do more stuff */; return _bar; } const int& baz() const { return _baz; } int& baz() { /* have side effects */; return _baz; } }; #define bar bar() #define baz baz() ... b = f.bar; f.baz = 6; Scheme already has macros, which make it look as if functions can take arguments by reference. Why not extend this to returned values? One might even extend syntax-rules to accept a non-parenthesized symbol as a pattern, the equivalent of the above #define's. Just a suggestion. -John