Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

It's hard to imagine what real lisp-like macros look like with other, non-homoiconic langauges. Anyone have an example?


Nimrod has strong metaprogramming capabilities.

    template htmlTag(tag: expr) {.immediate.} =
      proc tag(): string = "<" & astToStr(tag) & ">"
    
    htmlTag(br)
    htmlTag(html)
    
    echo br()
produces:

    <br>
http://nimrod-lang.org/talk01/slides.html

https://news.ycombinator.com/item?id=7071429


Nemerle is non-homoiconic, but has full-on macros. Here you can see some examples from my Nextem library (a bunch of niceties I built up over the years): http://trac.assembla.com/nextem/browser/trunk/Examples/Strin... along with the macros behind it http://trac.assembla.com/nextem/browser/trunk/Macros/StringF... http://trac.assembla.com/nextem/browser/trunk/Macros/Regex.n

The macros run at compile-time, and emit code by use of the <[ ]> blocks -- those get turned into ASTs at compile-time and get filled with the proper data.


Julia is not lisp like, and has macros [1]. The way it works is that your code is first interpreted to get the AST that looks like LISP code (`a+bc+1` becomes `+(a,(b,c),1)`) and your macro operates on that. So basically it works like a lisp macro (until you want to create a macro that creates macro, which is something I haven't done but heard about).

http://docs.julialang.org/en/release-0.2/manual/metaprogramm...


CORRECTION: `+(a,*(b,c),1)` is NOT like LISP code. However, Julia helps you to get the head of an expression (in this case, +) and it's args.


Sweet.js (http://sweetjs.org) and MacroPy (https://github.com/lihaoyi/macropy) come to mind. Actually "real macros" are just macros which operate on AST instead of on strings, they are hard to do if you have to re-implement language parser, but rather easy if the language exposes its AST api, like in Python case.


Haskell's "Template Haskell" system is pretty sophisticated... And challenging enough to be some deep black magic.

You end up being able to reify the entire Haskell syntax tree from "quoted" fragments, manipulate and generate a modified tree, and then "print" it back into program flow.

Totally capable, but not terrifically fun. It also has some compilation restrictions which are annoying if necessary.


I just (last night) dug into some TH hackery. I put together a quasiquoter for testing/debugging that would walk a do block and decorate every statement with (`onException` ...) set up to print the source location when an exception is thrown. I actually had to first parse with haskell-src-exts to get the location info, and currently I'm turning it into an ExpQ by pretty-printing and reparsing - which I don't love, but gets the job done.

https://github.com/dlthomas/snowdrift/compare/5094b1ca0e5002...


TH also ruins Haskell by inserting inivisble code with spooky action at a distance, where you have to pre-import symbols that TH will insert later, and compiler errors refer to code defined somewhere else but print line numbers of where the generated code is inserted. TH needs a compiler!


Check out Elixir's metaprogramming guide: http://elixir-lang.org/getting_started/meta/1.html


Besides those already mentioned, there's Dylan, which was originally S-expression based before switching to it's Wirth-style syntax.


Metalua is a good example of a macros with an Algol-like syntax. It's built on top of Lua - as you might guess from the name.

http://metalua.luaforge.net/quicktour.html




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: