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

Well, the short answer is that composing functions allows you to build algebraic abstractions but not syntactic abstractions.

I would never use squaring things as an example of macros: as you properly point out, this does not illustrate anything that cannot be done at least as easily with functions.

The examples I would trot out are things like let, which adds block scoping to languages that don't have it built in, or things like cond/case/switch. If you have a languge that doesn't have a case-like statement, you can use a macro to make one.

Your current language probably has these things built in, but such macors at least demonstrate a kind of abstraction that cannot be done with functions.

For example, you could build a function that looks like a case statement, but because most languages these days employ eager evaluation, your case function would evaluate all of its outcomes rather than only evaluating the one you want.

To make it work as a pure function, you would have to roll your own thunks by passing anonymous functions in for each case to be evaluated and each outcome. That works, but all that boilerplate becomes tedious.

The macro merely automates that kind of boilerplate for you in places where eager evaluation is harmful.

Time for me to stop, but I'll leave with a suggestion: syntactic abstraction is most useful when there's something unusual about the way you want to evaluate things.



> you would have to roll your own thunks by passing anonymous functions... all that boilerplate becomes tedious.

In many cases you could just define plain functions and have a way to denote what parts of the input should be converted to lambdas. I proposed something like this on the Arc forum, but it just got brushed aside. I still think it's a decent idea.

http://arclanguage.org/item?id=7216


To make [case] work as a pure function, you would have to roll your own thunks by passing anonymous functions in for each case to be evaluated and each outcome. That works, but all that boilerplate becomes tedious.

I like Ruby's block syntax for doing this without macros, but unfortunately you only get to pass in one block per function.


It's a worse-is-better thing: it makes some forms of abstraction awkward, you have to fool around chaining methods. But it does take the most common case and make it simple.

It seems like a legitimate design choice, even if I don't always like the resuls.




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

Search: