Arc Forumnew | comments | leaders | submitlogin
1 point by aw 4876 days ago | link | parent

Yeah... what 'latemac made me face up to is that my trick means that macros aren't transforming code to code any more. I'm not sure I know why, but I feel uneasy.

One question is can we come up with something better than making symbols qualified by namespace (such as how e.g. Clojure does it). It seems to me that making symbols namespace qualified is less convoluted than needing to use 'latemac with my function value trick, unless there's a problem I'm not realizing about namespace qualified symbols. What do you think?



2 points by rocketnia 4874 days ago | link

"[...]unless there's a problem I'm not realizing about namespace qualified symbols. What do you think?"

Well, my opinion on namespaces is that they don't really fix anything if they're human-guessable prefixes; the prefixes themselves can collide, in which case I'd want the namespaces themselves to be in namespaces to resolve the collision. :-p That can be a vicious cycle (where do the namespace namespaces get resolved?), but there are a few decisive ways to resolve it:

- Name the namespace after a GUID or cryptographic signature, rather than something prone to human over-abbreviation.

- Name the namespace after an entry in some directory people already have to keep collision-free, like a file system path or a domain name.

- Don't plan on serializing or unserializing the namespace at all, and "name" it using something which has a unique identity at run time, such as an uninterned symbol.

At any rate, keep in mind that if all symbols are namespaced, then things like ssyntax will need to be able to handle that, and anaphoric variables will get either more complicated to make, more complicated to use, or both.

Doesn't have to be that complicated. I think it would be cool to let 'awhen be defined like this:

  (mac awhen (test . then)
    `(let ,leak!it ,test
       (when ,leak!it
         ,@then)))
Here, 'mac and 'leak can be two macros which share information using an anaphoric variable of their own, say 'caller-namespace. They could expand to this:

  ; overly verbose for clarity :-p
  (low-level-mac awhen caller-namespace (test . then)
    `(let ,(tag-with-namespace caller-namespace 'it) ,test
       (when ,(tag-with-namespace caller-namespace 'it)
         ,@then)))
takes a breath

Another thing to keep in mind is that just because symbols in different namespaces are distinct doesn't mean they need to refer to different variables. If I import 'foo, I'd like for the 'foo in my namespace and the 'foo in the library's namespace are both aliases for the same variable. That way I can just say (extend foo ...) to affect things in the library which use 'foo, instead of having to drill into the namespace using something like (extend the-ns/foo ...).

-----

1 point by aw 4874 days ago | link

If I import 'foo, I'd like for the 'foo in my namespace and the 'foo in the library's namespace are both aliases for the same variable.

I like that.

leak!it

yes, there will need to be some mechanism to say that when my macro expands into a "bar", do I mean my bar or your bar? (Scheme's hygienic macros cleverly chooses which one you want most of the time, but makes it far too awkward to override the choice when it gets it wrong).

namespaces [...] don't really fix anything if they're human-guessable prefixes

Yeah.

-----

1 point by aw 4873 days ago | link

> let ,leak!it ,test

How does the caller's symbols such as passed in through "test" end up in the caller's namespace? I suppose all symbols would need to be tagged with a namespace? For example, if I said:

  (awhen x (prn x))
"x" would need to end up in my namespace after awhen was expanded.

-----

1 point by rocketnia 4870 days ago | link

Oh, I guess there's a couple of things I left out when I wrote that example.

To answer your question, the parameters to 'awhen would be wrapped up such that they were automatically associated with the place they came from. (Hmm, I guess that's a bit troublesome in itself, since it means they're essentially like Racket syntax objects, which need to be unwrapped to get at their original structure.)

More difficult to resolve: Somehow, the output of 'awhen oughta be wrapped up so that it's associated with the envioronment where 'awhen was defined. (And maybe this should be done more explicitly than it is in that example. Actually, while I was writing the example, I didn't remember this at all.)

In my current design for Penknife macros (toward the top of https://github.com/rocketnia/penknife/blob/1e5f3dd6cd86a2450..., a file in my Penknife draft[1]), both qq and leak are quasiquotes that anaphorically use lexical parameters of the macro call. They both use plainqq, and leak annotates the result so that it corresponds with the caller's namespace, while qq annotates it so it corresponds with the namespace surrounding the macro.

The hard part is that for qq to have a namespace to refer to, Penknife macros capture the local namespace they're defined in. That's not straightforward to translate to Racket; I basically end up making a shadowing namespace data structure at the start of each function call. On the other hand, it's probably sufficient to capture the global namespace. I was kinda just doing this for elegance's sake, since I kinda consider even a file-global namespace to be a local one, with imports as the local variables.

Got all that? I think I may have overexplained minutia this time around. ^^;

[1] There it is, my Penknife draft. :) I committed it to a branch a while ago, but I haven't really made a big deal out of that fact. Note that it doesn't work--it's not tested at all--and also note that the link's likely to break if and when I get back to it, finish it up, and treat it as the master branch.

-----