It's great the metaprogramming support seems to be a requirement for new languages these days.
Unfortunately, this one combines the inconvenience of Template Haskell (explicit invocation of macros with @) and the bugs of Common Lisp (the section on hygiene says, basically, "we have gensym"). Fortunately, the language is young, and I hope they can improve this story.
I find that the @ syntax is amazing, since the reader (programmer) knows exactly which form is a macro (and can look it up), as opposed to introducing arbitrary, often very confusing syntax.
Thanks. We've considered doing other things — like function call syntax for macros (which is essentially what Lisp/Scheme have), but decided against it. It just causes confusion. Can you pass a macro around like you can a function? Can functions shadow macros and vice versa? What happens if a macro introduces a local variable that shadows the macro itself? Basically it comes down to fact that macros are syntactic and as such behave very differently from functions, which are not syntactic. With the @ syntax, there's no confusion.
Someone already mentioned PLOT. This would be a good thing to lookup when designing your hygienic macro system, http://users.rcn.com/david-moon/PLOT/index.html. The author was also involved in Dylan, which is another infix language with hygienic macros.
Seems like there have been a variety of attempts to introduce lisp-style macros into non-lisp languages that use traditional syntax rather than s-expressions. I can see how this can succeed for simple macros without sacrificing much. However, complex macros done this way tend to be much more complicated than the equivalent lisp code. Do you believe that Julia solves this problem, or is it also subject to some of the same tradeoffs?
Constructing and manipulating code in Julia is a bit more complicated than Lisp — because Lisp lists are so damned simple. However, not by much. I think most of the complexity of code that generates code is inherent. Sometimes being that meta just makes your brain hurt. Our printf implementation (https://github.com/JuliaLang/julia/blob/master/j/printf.j) is about as bad as it gets and it's still pretty understandable — aside from the inherent complexity of implementing printf and the separation of what's computed at compile time and what's computed at run time.
Just a comment/suggestion: could someone with GitHub write access go over your wiki and fix code samples where multiple lines have been concatenated into a single line? E.g. https://github.com/JuliaLang/julia/wiki/Types-and-their-repr..., heading `Built-in types`.
Oh, also I believe the link was probably too stale docs. They're gone now. What's on the website is mostly up-to-date, but a few things have changed and will need fixing.
The problem with this is that it limits the options of library writers. For example, I can't replace some function with a macro that does something smart, such as check format strings for printf at compile time, because that breaks all callers. It also fundamentally limits what you can build with macros, because you can't build language features that are basic -- they always appear tacked-on.
That is very true — and it's precisely why we have considered making macros callable with function syntax. But I feel like having something that looks like a function and is actually a macro is a bit of a dangerous lie, no matter how handy it sometimes is. One of our design goals is not to be too tricky — if something looks like a function call, it should be a function call. The @foo syntax for macro calls means that you know exactly what's going on. It also means you can't do stuff like try to pass a macro as an argument to a higher-order function — what does that even do? I.e. what does map(m,vec) mean where m is a macro?
If macros are marked as different to functions at the callsite, then do they need to be marked different at the definition site? Most functions return a non-Expr value, but could return a Expr if the program's job is manipulating them. Most macros return a Expr, but could return a literal for insertion into the code.
So I'm wondering does a programming language which marks macro expansions different to function calls (as Julia does with the @ prefix) really need to distinguish functions from macros in the definition (as Julia does with the 'function' and 'macro' keywords) ?
Unfortunately, this one combines the inconvenience of Template Haskell (explicit invocation of macros with @) and the bugs of Common Lisp (the section on hygiene says, basically, "we have gensym"). Fortunately, the language is young, and I hope they can improve this story.