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

Re: Monkey-patching $quasi-value$



Per Bothner scripsit:

> The question is: Do we want there to be a default implementation of
> ($quasi-value-transformer$:foo ...) as (foo ...)?  

And what is the default implementation of (foo ...)?  We seem
to be on an infinite regress, and I'd rather just stop at
$quasi-value-transformer$:foo.  And start there too.

> (1) The reader returns ($quasi-value-transformer$:foo ...).  If there
> is no binding for $quasi-value-transformer$:foo, the implementation
> looks for ($quasi-value$ foo ...) which has a predefined binding
> equivalent to (foo ...).
> 
> (2) The reader returns ($quasi-value$ foo ...).  The prefined binding
> for $quasi-value$ is to see if $quasi-value-transformer$:foo has a
> binding, and otherwise evaluate (foo ...).

I propose this:

(1') The reader returns ($quasi-value-transformer$:foo ...).  If it
was called from `read`, that's what the program gets.  If it was called
from a compiler or interpreter, it applies its normal rules to determine
if $quasi-value-transformer$:foo is bound, and if not, takes its normal
error recovery action, whatever that is.

> Variant (1) has the advantage in that it can be useful even in a
> "partial" implementation that doesn't support the more "magic"
> concepts for looking for bindings and transforming symbols.
> I.e. one can easily and portably define a macro or function for
> $quasi-value-transformer$:foo, and that's the more important use case.

It is indeed, and (1') has the same advantage.

> An implementation can then *optionally* provide a default
> implementation and/or a mechanism to override the default.

By the same token, a compiler or interpreter can have some default
mechanism that recognizes symbols of this type and provides them with
some default value or behavior.  I once wrote a Lisp interpreter that, if
it found an undefined symbol in function position, checked it to see if
it matched the regex /^c[ad]+r/, and if so, it performed the appropriate
operation on the spot.  You could not, however, funcall or apply such
a function.

> There is some question as to what "a binding exists" means: Clearly one
> has to check for a macro at macro-expansion time.  If a binding isn't
> found at compile-time, do we check check for a run-time (function)
> binding?  That matches normal behavior for (foo ...). but it makes it
> difficult to also support a default macro binding, though a default
> function binding is easy enough.

An advantage of (1') is that it doesn't require us to work out the Right
Way of doing these things.  Scheme's normal mechanisms do the job for us,
and if we use a lexical syntax in our code without bothering to define a
corresponding macro or procedure, we get exactly what we deserve to get.
I do not think this is user-hostile, any more than it's user-hostile
not to provide the /^c[ad]+r$/ hack I mentioned above.

> I prefer the colon form as it keeps "foo" more distinct.  

Very well.

-- 
A: "Spiro conjectures Ex-Lax."                  John Cowan
Q: "What does Pat Nixon frost her cakes with?"  cowan@xxxxxxxx
  --"Jeopardy" for generative semanticists      http://www.ccil.org/~cowan