Arc Forumnew | comments | leaders | submitlogin
1 point by icemaze 6172 days ago | link | parent

Ah, ok! Now I get your point. Yes, it would be really useful to be able to extend syntax like that. However I believe readtable access should be limited. Let me explain.

I don't mean "limited" as in "dumbed down" but as in "predictable". It's nice to extend syntax, but it's even nicer when your editor can indent and colorize your program without a hitch. You are right: macros don't alter syntax significantly. And that's what makes them so nice: parens are still balanced, editors don't barf and, if you use with-gensyms and once-only, referential transparency is broken only where necessary.

A good place to start, IMHO, would be the ability to define operators: infix (like ':'), suffix ('~'), postfix and "wrapping" (like '[...]'). Operators would satisfy all of Arc's syntax-extension needs (unless I'm missing something). For example:

  (operator wrapping #\[ #\] body
    `(fn (_) ,@body))

  (operator prefix #\~ symbol
    `(fn args (not (apply ,symbol args))))
...or something like that.

Simonb: do you think this solution would fill the gap? Can you point out some situation where you would like even more control over the read-table?



1 point by simonb 6172 days ago | link

The problem with giving only a limited support for something is that people will invariably want more and start to abuse the system. For instance with operators you risk ending up with a slew of little languages full of glyphs rich with semantic meaning (think Perl).

Macros allow you to build "up", to add new [abstraction] layers to your language but sometimes it would be nice to be able to go "down" as well and add new semantics that non-trivially interacts with the host language. Re-entrant continuations or proper tail recursion for CL come to mind. Another example of such friction is Qi [http://www.lambdassociates.org/aboutqi.htm] where all sorts of hacks (case sensitivity etc.) are needed instead of it simply being a library.

Theoretically one could design a language powerful enough that this would never be necessary but even then you would want code-walkers for optimisations. CL with it's compiler macros is a step in the right direction but it soon runs aground when you want to do things such CPS optimisations. Say you want to merge nested map-operations in CL:

  (map 'vector #'^2 (map 'vector #'+ a b))
=> (map (lambda (:g1 :g2) (^2 (+ :g1:g2))) a b)

This is something compiler macros are great for, but as soon as the inner map is wrapped in a function we have a problem. What our compiler macro sees is something like:

  (map 'vector #^2 (vector+ a b))
and at that point we have no idea what vector+ looks like.

In terms of a compromise, access to the environment at compile-time would go a long way (CL has provisions for this, but the standard doesn't say anything about how the environment should look like) and maybe a facility to get function definitions (forced inlining if you will).

-----