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: difficulty of writing translators


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