Tell me more ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

LISP's macros are extremely powerful constructs, and the inability to introspect and modify the program itself beyond the method signature level has always struck me as a limitation. Yet I favour "complex" syntax because it tends to be closer to natural language.

So far I have failed to find a language which combines a powerful macro mechanism such as LISP's with a naturally looking syntax (1). Is anyone aware of such a language?

Footnote:

  1. I would consider python to have a naturally looking syntax as it allows constructs like this: if 0 < a < 5 and b in list. The avoidance of braces to structure blocks is irrelevant in this case, though.
share|improve this question
4  
I certainly do not want this to be an answer, but yes, there is a such language, and it is Perl6. Hygienic macros are part of the language, but no Perl6 compiler has yet implemented it. – Thaddee Tyl Jul 29 '11 at 16:37
You might check out C++ Boost Library Lambda expressions - boost.org/doc/libs/1_47_0/doc/html/lambda.html – David I Jul 30 '11 at 20:34
1  
Nemerle is such a language. – Paul Nathan Jul 31 '11 at 16:08
2  
And needless to mention that Lisp itself can be turned into such a language, with a help of one of numerous parsing libraries and reader macros. – SK-logic Aug 1 '11 at 7:45
And another one: convergepl.org – SK-logic Aug 1 '11 at 7:53

11 Answers

up vote 6 down vote accepted

Yes. You should look at David A. Wheeler's readable S-expressions proposal. It provides a more readable way to write Lisp programs, without making any semantics-specific syntax. Thus it's fully general and can be applied to any Lisp dialect or S-expression-based DSL.

Thus, using this new style in Scheme, your example would be written as (with list renamed to lst because list is a Scheme built-in):

if {{0 < a < 5} and {b member lst}}
  ...

The reader takes care of translating that automatically to

(if (and (< 0 a 5) (member b lst)) ...)

without having to know anything about if, and, <, etc.

For programmers from non-Lisp languages, they may still be surprised to learn that the curly brackets are not optional (and cannot be added or removed indiscriminately), but it's still a much smaller learning curve than prefix notation or "all those parentheses".

share|improve this answer
Is there an implementation of this already, say in Racket or perhaps Clojure? – Robert Harvey Jul 29 '11 at 17:24
@Robert: There's a reference implementation at sourceforge.net/projects/readable, but I don't know if it works with Racket. (Clojure, alas, already uses curly brackets for something else, so this syntax will conflict with that.) – Chris Jester-Young Jul 29 '11 at 17:52

I find Boo's macro system nearly as expressive as what you get in Lisp, coupled with a Python-like syntax. Because Boo is statically typed except for the duck-typing features, it's not 100% equivalent, but pretty close in practice, and you get a pretty familiar syntax as a starting point.

share|improve this answer
For the record, the macro system is described here: boo.codehaus.org/Syntactic+Macros – blubb Jul 29 '11 at 17:43
1  
That's one of the alternatives, although that doc is missing the newer happy-path quasi-quoted macro style, which is much more compact and readable. See lostechies.com/ryansvihla/2010/04/05/… for an example or two. – JasonTrue Jul 29 '11 at 17:49
You are still limited by Boo's syntax, while Nemerle allows you to come up with new syntax with the macros. – Jetti Aug 20 '12 at 14:59
Considering you can replace parts of the compiler pipeline (which is easier than it sounds) if that becomes an issue, I don't think that's much of a limitation. Though it's not quite clear what I can do with Nemerle's "syntax extensions" that can't be done with a Boo quasi-quoted macros. – JasonTrue Aug 20 '12 at 16:36

F# might fit the bill; although it doesn't have first-class macros, it does have quotations, and you can introspect with reflection.

share|improve this answer
1  
For the record, quotations are described here: msdn.microsoft.com/en-us/library/dd233212.aspx – blubb Jul 29 '11 at 17:49

My "readable" project has been working to solve this exact problem (making Lisp much more readable). You can see the specs, and the code, at http://readable.sourceforge.net. We've devised a set of additional abbreviations for Lisp readers; you don't need to use the additional abbreviations, but if you do, the resulting code is easier to read. The hope is that eventually readers will build them in, but you can also use our reader implementation (MIT license).

We'd love to get feedback, help, etc. Please check us out!

http://readable.sourceforge.net

share|improve this answer
As was noted in an earlier comment, the key thing about our "readable" approach is that it's general and homoiconic. Past efforts to make Lisps readable often weren't.. which is why they failed. They're backward-compatible abbreviations, too. For example, they add "curly-infix" lists, normal Lisp lists expressed in infix order. E.G., {n >= 2} is just an abbreviation for (>= n 2). They add "neoteric" expressions so you can say "f(a b)" as an abbreviation for (f a b). And finally, they add indentation as meaningful. – David A. Wheeler Aug 20 '12 at 4:31
btw., have you seen bit.ly/vqqvHU ? It is also general and fully homoiconic (e.g., any expression of any level can be wrapped into a quasiquotation, including the user-defined syntax). – SK-logic Aug 20 '12 at 8:49

Dylan is said to have a macro system that is comparable to the Common Lisp macro system, while having a "more traditional" surface syntax.

share|improve this answer

In Prolog you can create terms/clauses with =.., evaluate them by stating them, or add/remove them from the program using assera, assertz. Although no-one ever accused Prolog of having a natural looking syntax.

You might want to consider Io, as it's reflection capabilities enable you to introspect and rewrite code. I like an old article by why http://web.archive.org/web/20080212010904/http://hackety.org/2008/01/05/ioHasAVeryCleanMirror.html

share|improve this answer

I don't know for certain, but I'd place bets that the "multi-stage programming" in MetaOCaml is very closely related to Lisp macros.

There's also a metaprogramming variant of Haskell.

share|improve this answer
For the record, the Haskell variant is described here: haskell.org/haskellwiki/Template_Haskell – blubb Jul 29 '11 at 17:55
2  
Macro expansion is a kind of computation at compile time, but syntactic extension (which is what macros do) involves a lot more than just multi-stage programming. (The MacroML paper attempts to connect them, but it uses a severely crippled macro system.) – Ryan Culpepper Jul 29 '11 at 23:23
@Ryan - OK - neither my Lisp nor my MetaOCaml (nor even my ML) knowledge is up to scratch. I did read a bit more after posting this answer, and the three syntactic gizmos (bracketing, escaping and execution) didn't really seem macro-ish in themselves - but what about using them in combination with ordinary functions? A Lisp macro (if I remember correctly) is basically a function, except that it generates code instead of a return value. From that perspective, the multi-layer thing in combination with functions seems like maybe building blocks for Lisp macros. – Steve314 Jul 30 '11 at 1:35
2  
@Steve314 The problem is that multi-stage programming only lets you manipulate expressions, not variables-to-be-bound or match clauses or any other syntactic category. Only expressions. Furthermore, its type system is too vanilla to let you do things like compute the scope of an expression argument. Imagine trying to implement a new pattern matching syntax... what would the types look like? In contrast (IIUC), Template Haskell does let you represent things other than expressions, and it moves the type system out of the way enough to do useful transformations. – Ryan Culpepper Jul 30 '11 at 20:54
Template Haskell macro system is not as powerful as Lisp, unfortunately. And it enforces a distinctive macro application syntax, which won't allow truly seamless macros into a language. – SK-logic Mar 23 '12 at 11:02
show 2 more comments

http://www.shenlanguage.org/

Shen is a portable functional programming language that offers

  • pattern matching,
  • λ calculus consistency,
  • macros,
  • optional lazy evaluation,
  • static type checking,
  • an integrated fully functional Prolog,
  • and an inbuilt compiler-compiler.
share|improve this answer

I think Nememrle macros are great. They also allow you to change the syntax of the language, which I think more closely resembles macros in LISP than any other non-LISP language.

share|improve this answer

Scala has both macros and (much!) more complex syntax than any Lisp!

share|improve this answer

D has a mixin statement that combined with compile time function execution allows defining lisp-style macros. Unfortunately it's limited to complete statements.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.