[racket] redefining #%top (and #%app) with conditions
Thank you. Is this behavior the result of a general rule of syntax transformation (that I have heretofore been unfamiliar with) or is it a special rule about the behavior of #%top (or should I say, the #%top family).
On Feb 7, 2014, at 8:33 AM, Matthew Flatt <mflatt at cs.utah.edu> wrote:
> They're different `#%top`s.
>
> In the the macro stepper, click on the first `#%top`, and the panel on
> the right tells you that it comes from "bound.rkt". When you click on
> the second `#%top`, though, the panel shows that it comes from
> '#%kernel via `racket`.
>
> At Fri, 7 Feb 2014 08:24:36 -0800, Matthew Butterick wrote:
>> Last thing. This solution seems to work, but I can't figure out WHY it works.
>>
>> If I look at these two lines in the macro expander, where bar is unbound:
>>
>> (bar "hello")
>> ((bound/c bar) "hello")))
>>
>> First step makes sense: bar is replaced with (#%top . bar).
>>
>> ((#%top . bar) "hello")
>> ((bound/c bar) "hello")))
>>
>> Second step makes sense: (#%top . bar) is replaced with my syntax-rule for
>> #%top to make an x-expression:
>>
>> ((λ x `(bar , at x)) "hello")
>> ((bound/c bar) "hello")))
>>
>> Third step makes sense: (bound/c bar) is replaced with (#%top . bar).
>>
>> ((λ x `(bar , at x)) "hello")
>> ((#%top . bar) "hello")))
>>
>> But in the fourth step, I get the "bar: unbound identifier in module" error.
>> This is what I want. But I don't understand is why this is so. Why wouldn't
>> the second (#%top . bar) get transformed by the syntax-rule attached to #%top?
>>
>>
>> On Feb 6, 2014, at 9:37 PM, Matthew Butterick <mb at mbtype.com> wrote:
>>
>>> Reflecting on it as an issue of detecting bound identifiers, I've come up
>> with a possible approach — could it be this simple, or am I overlooking some
>> complication?
>>>
>>> bound.rkt:
>>>
>>> #lang racket
>>>
>>> (provide bound/c (rename-out (top~ #%top)))
>>>
>>> (define-syntax-rule (top~ . id)
>>> (λ x `(id , at x)))
>>>
>>> (define-syntax (bound/c stx)
>>> (syntax-case stx ()
>>> [(_ x)
>>> (if (identifier-binding #'x )
>>> #'x
>>> #'(#%top . x))]))
>>>
>>>
>>> test.rkt:
>>>
>>> #lang racket
>>> (require "bound.rkt")
>>> (define foo displayln) ; foo is now bound
>>> (foo "hello")
>>> ((bound/c foo) "hello")
>>> (bar "hello") ; bar is unbound
>>> ;((bound/c bar) "hello")
>>>
>>> This does the right thing:
>>>
>>> hello
>>> hello
>>> '(bar "hello")
>>>
>>> And then when the last line is uncommented
>>>
>>> ((bound/c bar) "hello")
>>>
>>> It triggers the usual error on compile:
>>>
>>> bar: unbound identifier in module in: bar
>>>
>>>
>>>
>>> On Feb 6, 2014, at 8:38 PM, Matthew Butterick <mb at mbtype.com> wrote:
>>>
>>>> I'm trying to figure out how to make #%top change behavior based on
>> different kinds of function names, though my experiments keep leading to
>> infinite loops that blow up DrRacket. Oops.
>>>>
>>>> In my #lang project based on Scribble, I've been using this simple
>> redefinition of #%top for convenience:
>>>>
>>>> (define-syntax-rule (#%top . id)
>>>> (λ x `(id , at x)))
>>>>
>>>> IOW, if the thing in the function position is undefined, it's treated as
>> the opening tag of an x-expression. This makes it easy to mix undefined and
>> defined names.
>>>>
>>>> But it can make debugging difficult. Because if you expect a name to be
>> defined as a function and it isn't, then you don't get the syntax error you
>> ordinarily would. The function call silently gets converted an x-expression.
>> Spooky side effects follow.
>>>>
>>>> I'd like to improve this by making a syntactic prefix that suppresses this
>> behavior and that can be attached to any function name. For instance, def-*.
>> So if I write (def-foobar ..) in the code, this will mean:
>>>> 1) try to invoke a function called (foobar ...);
>>>> 2) if the function (foobar ...) isn't defined, raise the usual exception +
>> syntax error.
>>>> In other words, the standard #%top behavior.
>>>>
>>>> Whereas if I just write (foobar ...) without the def-* prefix, this will
>> mean:
>>>> 1) try to invoke the function (foobar ...);
>>>> 2) if the function (foobar ...) isn't defined, turn it into the
>> x-expression `(foobar ,@ ...).
>>>> In other words, my special #%top behavior shown above.
>>>>
>>>> Having explained the logic, I think the flaw in my experiments so far is
>> that this actually requires manipulation of #%app too, because once you hit
>> #%top, you've missed your chance to apply functions. (Right?) But even
>> supposing one creates two evaluation paths under #%app, it's not clear to me
>> how to preserve those paths on the way up to #%top.
>>>>
>>>>
>>>
>>
>>
>> ____________________
>> Racket Users list:
>> http://lists.racket-lang.org/users