[racket] variables within macros

From: Tim Brown (tim.brown at timb.net)
Date: Sun Jan 20 06:35:45 EST 2013

Matthias,

Thank you very much for your response.

First, in the interests of full disclosure; I found a bug in my code --
there was a missing #` from one of my templates, which I found through
luck rather than judgement. It'd be easy to claim that "all them
parentheses in Racket just confuse me", but I won't [because they
don't, really].

Anyway, I say "luck rather than judgement", since I used no recipe for
development and testing rather than "write code, scream when it doesn't
work". So I am most grateful for this framework.

On 19/01/2013 19:01, Tim Brown wrote:
> Excuse me everyone, I'm sending this so I can pin responses from
> another, recently-subscribed-to-the-list account.

So everything is quoted at one depth too many.

> On 01/19/2013 06:31 PM, Matthias Felleisen wrote:
>>
>> Let's take a step at a time. Don't lose patience. It will help
>> you get where you want to be, and it may help us figure out how
>> to do better with this aspect of Racket, which is by far its most
>> innovative part and unrivaled in the world of PLs.

Indeed. Part of the frustration is that I want to explore the full
power of Racket's syntax system. Probably leaping too far ahead. One
other thing w.r.t. this: I'll call Racket a PL playground later. This
is not a disparagement, it is only possible because of the work put into
Racket in this area.

>> Like Scheme, Racket supports hygienic syntax extensions. What this
>> means is that -- in principle -- you should rarely, if ever, worry
>> about binding issues. Most of the time, they should just work.

Below, you use define-syntax-rule. Which, I notice, doesn't use (in an
obvious way) syntax objects. The syntax API gives choice, and I chose
syntax/parse (thinking master this, and you've got somewhere!). My
specific stumbling block was probably to muck the hygiene up by losing
track of what my s-exps represented.

I've also just read your response to Rudiger w.r.t. (IMOW) Racket being
a derivative of Scheme, and not Scheme. Unfortunately for me, I came to
plt-scheme when it was still a Scheme (with no real idea of your plans
for it), and the literature that I have access to is mostly Scheme.

define-syntax-rule looks nothing "like what a proper Scheme macro"
should from this literature; all of the "native" macro systems in RnRS
(including R. Kent Dybvig[?]'s system) that I've seen use templates and
#` syntaxes.

define-syntax-rule is obviously an evolution of and probably
improvement on the traditional (and underlying?) Scheme syntax extension
mechanism. It is, also, what the Racket Guide starts with. But the
message never really sank in that this is REALLY where to start,
especially with all that (define-syntax (syntax-match ...)) carp
polluting my head.

>> On Jan 18, 2013, at 12:36 PM, Tim Brown wrote:
>>> A concrete example is that I am trying to write a #lang language.
>>
>> Honestly, I would never ever try to write a #lang first.
>> That's more than most people want.

This "project" was prompted by plt-games.com, where the challenge is
to "design a language to ..."; I thought I'd best at least introduce
a #lang tag even though, on inspection, all I was doing was probably
providing a macro library. I also wanted to explore how to write a new
language. (And, apparently, kick off a debate about languages and the
macro system).

>> 2. create entirely new languages. To so so, Racket enables you
>> to start from an existing language and
>>   -- to subtract constructs

I planned to (energy permitting) subtract define from the language;
forcing all definitions to be define/tested. A perverse curiosity wanted
to see what the fall-out of that would be; even if it wasn't practical.

>>   -- to expand an existing module for further analysis

Again, I had plans for my define/tested... functions. But those were
pipe-dreams at best.

>> You seem to want to extend Racket with a define/test construct.
>> I propose to think of this as as syntactic extension of Racket.
>> Let me start by arguing against thinking of this as a new language.

>> Listening to you helps us. Thanks for speaking up. -- Matthias

This is only a weekend hobby project for me; and I am grateful that you
too not only the time, but "On 01/19/2013 06:31 PM" this kind of time to
answer me.

>> GOAL: Let's say we wish to be able to write
>> ...
>> because we believe in self-documentation of functions via tests.
>> Viva la design recipe.

Are you applauding my desire to build tests into my definitions (in
which case, thanks - but it's not my idea)?

Or are you starting a "design recipe" yourself with the "GOAL", "STEP
1"...?

The reason I ask is this: before I received your answer this evening, I
was going to re-attack the problem; either by taking the opportunity to
look at the design recipe in HTDP (which I haven't done much more than
skim read a long time ago) or to "TDD as if you (I) mean it".

In either case, I considered a problem; how do you unit-test macros?
I'm not sure quite how to express this, but I'll have a go. There are a
lot of complex macros in Racket; can you unit test them? I.e. would
you be able to approach this problem by saying:

   I want to write:
   (define/test (add-one x)
      (tests (check-equal? (add-one 1) 2)
             ; other tests skipped for brevity...
             ;(check-equal? (add-one -1) 0)
             ;(check-equal? (add-one 2) 3)
             ;(check-equal? (add-one 2) 4))
      ;; -- IN --
      (+ x 1))

   And I want it to expand to:
   (begin
    (module+ test (check-equal? (add-one 1) 2))
    (define (add-one x) (+ x 1))

And then, by stating that, do you write yourself a unit test (and this
is where I go all pseudo-code):

("check-syntax-expands-to"
   (define/test (add-one x)
    (tests (check-equal? (add-one 1) 2))
    ;; -- IN --
    (+ x 1))
   (begin
     (module+ test (check-equal? (add-one 1) 2))
     (define (add-one x) (+ x 1)))

Is there any means to do this?

If there is a means to write a syntax-rule/transformer/whatever,
and establish that I get the expected form from it, then this may help
me keep things together when I go for something proper adventurous.

>> STEP 1: write a syntax rule
>> STEP 2: write a syntax rule and bind check-equal? in the source
>> STEP 3: write a syntax rule in a separate library, provide it
>> STEP 4: write a syntax rule in a separate library, provide it

Are these the steps you, personally, tend to take when developing macros
yourself.

>> (require "test-define.rkt")
>>
>> (define/test ...)

I have to ask... define/test is a syntax-rule. It has always confused
me slightly that (after hearing about a syntax phase and runtime phase)
I can use define/test after a simple "require" of the library. The
syntax rule isn't even provided from the library as "something special".
I *think* I can see how this is consistent, but is there a one-line
statement you can make that helps make this clear?

>> Now this one is even more charming:
>>
>>   1. we have a syntax library
>>   2. we have no pattern left;
>>     the library takes care of it all
>>
>> Is there an objection left? I could see that you may wish to
>> argue that the all-from-out pollutes the entire module scope
>> with the bindings from rackunit. You really just waned those
>> in the test submodule.
>>
>> Here is my reply: I think the objection is not well-founded.
>> When I see software engineering problems with this "pollution",
>> I will believe it and I will work out a solution.
>>
>> PRINCIPLE: stick to syntactic extensions until you really really
>> need new languages. Keep new languages rare.

Good principle.

>> IF I found such a software engineering reason, I would try to
>> figure out how to solve it w/o resorting to a new language.

I think there needs to be a certain distinguish made between software
engineering and computer science / PL investigation. I do the former
for a living and, with that hat on, I agree with you 100%ly that we
should avoid new languages (in this sense).

However, the computer scientist in me takes great joy at contemplating
esolangs, and what they can teach us. I'll restate that one of the
things that (I think that) Racket promises is a PL playground, and I
want to know that, if the urge takes me, I have the means (the tools
and the skills) to implement 4DL(*).

>> Let us know what you think up to this point.

I hope I have :-)

The exercise of writing this email has been helpful to me; and I thank
you in advance of any answers you may provide to the outstanding
queries.

Tim

* 
http://web.archive.org/web/20081222011210/http://www.cliff.biffle.org/esoterica/4dl.html 
; I'm pretty sure this is PL fun, and not s/w
engineering -- it's not my favourite esolang, just the result of a
Random Page search on the wiki.

Posted on the users mailing list.