[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: macros expanding into definitions



As an alternative to "unassigned" or "undefined" for the state of
a variable bound by the (define x) or (let ((x)) ...) syntax, Rozas
asks 

    What about "uninitialized"?

Sounds good to me.

                             * * *

In a different message, Rozas said something that I think is
incorrect:

    The analog of

         (define (foo)
           (set! x 1)
           (define x 2))
         (foo)
    is
         (set! x 1)
         (define x 2)

    which clearly is not legal at top-level either.

Rozas himself stated that the definition above would be equivalent to

    (define (foo)
      (let ((x))
        (set! x 1)
        (set! x 2)))
    (foo)

for which the top-level analogue is the eminently legal (in R5RS!)

    (define x)
    (set! x 1)
    (set! x 2)

So I don't understand something here.

                             * * *

Aubrey Jaffer writes:

    ....I would
    still prefer that (if a variable is DEFINEd) a DEFINE of a variable be
    required to precede SET!s of that variable....

I also think that allowing a SET! to precede a DEFINE that binds the
variable it assigns will be confusing, but I think Jaffer's suggestion
would be confusing also.  Does Jaffer mean to suggest that the DEFINE
must precede the SET! statically or dynamically?  Both are confusing:

    (define (foo)
      ; "statically precedes"
      (cond ((read) (define x) (foo))
            ((read) => (lambda (y) (set! x y) (foo)))
            (else x)))

    (define (foo)
      ; "dynamically precedes"
      (cond ((read) => (lambda (y) (set! x y) (foo)))
            ((read) (define x) (foo))
            (else x)))

So I think any generalization of internal definitions is going to
make people more confused, not less confused, regardless of whether
we:

    *  allow internal DEFINE anywhere, with no restriction; or
    *  require internal DEFINE to precede references and assignments
       statically; or
    *  require internal DEFINE to precede references and assignments
       dynamically.

Please note that I have assumed that any restrictions placed on the
relationship between DEFINE and SET! would apply equally to references.

                             * * *

Finally, I want to respond to Feeley:

    ....I don't view
    the one-to-one correspondence between letrec and internal defines as
    being very useful to the user or the implementor.

I do.  Like Dybvig, I find the correspondence useful as a teacher, as a
user, and as an implementor.

As a teacher, I would probably be happiest if internal definitions didn't
exist.  But since they are ubiquitous, I have to explain them to students,
and it is easiest to explain them in terms of letrec, which I have to
explain to students anyway when I am talking about block structure and
scope.  By the way, the syntactic similarity of Scheme's let, let*, and
letrec is extremely helpful when teaching students about scope rules.

As a user, I use letrec and internal definitions interchangeably.  Letrec
seems more general, because I can put a letrec anywhere an expression can
appear, but I suppose the same could be said for (let () ...).  Define is
useful when I rearrange a program by making global variables local and
vice versa.

As an implementor, I turn internal definitions into letrec, which in turn
becomes an ugly mix of calls, lambda expressions, and assignments.  Good
code can be recovered from this mess using single assignment analysis,
which seems to be no more difficult than the assignment analysis that
must be performed when either letrec or internal definitions are taken
as primitive.  Both the MacScheme and Twobit compilers use single
assignment analysis, although the Twobit compiler does a much better
job with the information gained thereby.

    By adopting the proposed extension to internal defines (and loosing
    the one-to-one correspondence with letrec) it would become more
    attractive to clean up letrec (by only allowing letrec's of lambdas).

I don't see the point of this, since internal definitions would still
be dirty.  Cleaning up letrec while leaving internal definitions dirty
just makes the language more complicated, because it adds one more kind
of expression to the language.

What would I actually like to see?  The minimal relaxation of the rules
for internal definitions that would solve the original problem pointed
out by Rees.

Will