Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What can you do with Lisp macros that you can't do with first-class functions?

I think I understand Lisp macros and their role in the compilation phase.

But in Python, you can pass a function into another function

def f(filename, g):   try:                                      fh = open(filename, "rb")       g(fh)   finally:      close(fh)  

So, we get lazy evaluation here. What can I do with macros and not with functions as first class objects?

like image 545
Joshua Fox Avatar asked Feb 12 '11 20:02

Joshua Fox


People also ask

What are Lisp macros good for?

The special power that Lisp macros have is that they can control evaluation (as seen by evaluating the input expression via ~expr and do arbitrary source-to-source transformations with the full power of the language available.

Is a macro not a function Lisp?

Macros do code transformations at compile time or runtime. That's different from functions. Just look into the Common Lisp standard for many different pre-defined macros and their different syntax. Now think about, why these are macros and not functions.

How do Lisp macros work?

The Common Lisp macro facility allows the user to define arbitrary functions that convert certain Lisp forms into different forms before evaluating or compiling them. This is done at the expression level, not at the character-string level as in most other languages.

Are rust macros like Lisp macros?

Rust's macros are very good. They act like Lisp's macros, unlike Haskell's. The fact that Rust has type-classes (“traits”) and sum types (“enums”) and pattern matching is very attractive.


1 Answers

First of all Lisp has first-class functions too, so you could as well ask: "Why do I need macros in Lisp if I already have first-class functions". The answer to that is that first-class functions don't allow you to play with syntax.

On a cosmetic level, first-class functions allow you to write f(filename, some_function) or f(filename, lambda fh: fh.whatever(x)), but not f(filename, fh, fh.whatever(x)). Though arguably that's a good thing because in that last case it is a lot less clear where fh suddenly comes from.

More importantly functions can only contain code that is valid. So you can't write a higher-order function reverse_function that takes a function as an argument and executes it "in reverse", so that reverse_function(lambda: "hello world" print) would execute print "hello world". With a macro you can do this. Of course this particular example is quite silly, but this ability is enormously useful when embedding domain specific languages.

For example you couldn't implement common lisp's loop construct in python. Hell, you couldn't even implement python's for ... in construct in python if it wasn't really built-in - at least not with that syntax. Sure you could implement something like for(collection, function), but that's a lot less pretty.

like image 171
sepp2k Avatar answered Oct 02 '22 17:10

sepp2k