Arc Forumnew | comments | leaders | submitlogin
Name to Variable Bindings
3 points by nlavine 6148 days ago | 2 comments
I was just looking at some of the old posts about name bindings, and I think I have a solution.

First, my summary of the arguments:

Names should always be bound to the lexically obvious variable, because it makes programs easier to read and understand. For instance,

  (let tab (table)
    ...
    (tab 5))
should not print html.

However, doing this would mess up some macros:

  (withs (do 1 re 2 mi 3) ; thanks almkglor!
    (+ do re mi))
expands to

  (let do 1
    (let re 2
      (let mi 3
        (do     ; problem here!
          (+ do re mi)))))
Which doesn't work very well if do always evaluates to 1, which means as almkglor pointed out in http://arclanguage.org/item?id=2556 that every macro would have to publish every symbol it used in functional position, and the programmer would have to be aware of it and work around it every time they used a macro (and nested macros would just suck).

My proposed solution is to let all names be black-box abstractions, completely hygienic macros that you can treat like functions, BUT add the ,@ syntax that someone suggested earlier. For example:

  (let tab (table)
    ...
    (tab 5))
would work, because the name tab would be bound to the table at that point (assuming no lets in the ...).

  (withs (do 1 re 2 mi 3)
    (+ do re mi))
would also work, because withs would be a hygienic macro.

However, aif would still work too:

  ,@(aif (tab x) (frob it) (alist-ref alist x) (foo it) (bar x))
In this case, however, aif is just a normal function that returns a list - doesn't even have to be tagged as a macro - and the ,@ operator expands it in place before evaluating the rest of the code.

This means that the programmer has to be aware of, and mark, all unhygienic macros. However, this is completely fine, because the programmer has to be aware of them anyway. If you don't realize that aif is an unhygienic macro, then you're going to be pretty surprised when you try to use your old binding of it. Or try to map aif over a list.

In fact, this syntax also has the advantage of giving you anonymous macros for free! Just make a normal function that returns a list, and use ,@ to macro-ize it.

This also lets you write one function whose output you can either run immediately, or save as a list until you want it later (of course, ,@ would also work with variables whose values were lists).

At the same time, any name you use in functional position is guaranteed to work as you expected it to. This would actually simplify the way you think about programs, because there would only be one rule to remember. Functions work correctly using perfect lexical scoping. If those functions happen to return lists, you can choose to do cool things with those lists, but it's up to you.

I can see some issues with this uglying-up code, but I think the anonymous function bracket syntax should solve a lot of that by letting you write things functionally instead of with macros, and the rest might be worth the tradeoff.

What do you guys think?



3 points by nex3 6147 days ago | link

I'd rather see this as a prefix operator:

  (@if (tab x) (frob it) (alist-ref alist x) (foo it) (bar x))
Also, what if the explicitly-unhygienic macros want to have some hygiene? By this I mean that, for example, if you make "aif" totally unhygienic, more than just "it" gets exposed. "@if" is in no way a black box - you also need to be concerned about shadowing "let", "car", etc.

-----

1 point by almkglor 6146 days ago | link

Nitpick: Just to give the proper credit where it's due, the "do re mi" example is from andreuri2000: http://arclanguage.com/item?id=1913

-----