Hot answers tagged

51

I think the main reason is that macros are lexical. This has several consequences: The compiler has no way of checking that a macro is semantically closed, i.e. that it represents a “unit of meaning” like a function does. (Consider #define TWO 1+1 — what does TWO*TWO equal? 3.) Macros are not typed like functions are. The compiler cannot check that the ...


39

Probably the biggest difference is that C macros are expanded in the preprocessing phase, before any other compiling is done, while C++ templates are part of compilation. This means that C++ templates are type-aware and scoped, among other things, and are not simple textual substitution. They can compile to real functions, and therefore avoid most of the ...


28

Many Lispers will tell you that what makes Lisp special is homoiconicity, which means that the code's syntax is represented using the same data structures as other data. For example, here's a simple function (using Scheme syntax) for calculating the hypotenuse of a right-angled triangle with the given side lengths: (define (hypot x y) (sqrt (+ (square x) (...


23

A dissenting opinion: Lisp's homoiconicity is far less of a useful thing than most Lisp fans would have you believe. To understand syntactic macros, it's important to understand compilers. The job of a compiler is to turn human-readable code into executable code. From a very high-level perspective, this has two overall phases: parsing and code generation....


21

The macro is (putatively) more efficient, as it doesn't involve a function call. It can be optimised more easily, as it just involves a pointer offset lookup. The function call allows linking against the same library even if the program was compiled without the macro definition - if it was compiled with a different header, or just with a rogue declaration ...


19

Scala makes this possible too (in fact it was consciously designed to support the definition of new language constructs and even complete DSLs). Apart from higher-order functions, lambdas and currying, which are common in functional languages, there are some special language features here to enable this*: no operators - everything is a function, but ...


15

I am of the opinion that if a language has macros, they should be a well planned out and integral part of the language and not of the compiler. Example, Lisp's macro system is a very powerful integrated language feature and is subject to all the rules and regulations of Lisp itself. Counter-example, C/C++ macro system is separate from the language and ...


14

I mostly use macros for adding time-saving new language constructs, that would otherwise require a bunch of boilerplate code. For example, I recently found myself wanting an imperative for-loop similar to C++/Java. However, being a functional language, Clojure didn't come with one out of the box. So I just implemented it as a macro: (defmacro for-loop [[...


13

Haskell Haskell has "Template Haskell" as well as "Quasiquotation": http://www.haskell.org/haskellwiki/Template_Haskell http://www.haskell.org/haskellwiki/Quasiquotation These features allow users to dramatically add to the syntax of the language outside of normal means. These are resolved at compile time as well, which I think is a big must (for ...


12

What sorts of things do people actually end up doing with macros? Writing language extensions or DSL's. To get a feel for this in Lisp-like languages, study Racket, which has several language variants: Typed Racket, R6RS, and Datalog. See also the Boo language, which gives you access to the compiler pipeline for the specific purpose of creating Domain-...


12

Tcl has a long history of supporting extensible syntax. For example, here's the implementation of a loop that iterates three variables (until stopped) over the cardinals, their squares and their cubes: proc loopCard23 {cardinalVar squareVar cubeVar body} { upvar 1 $cardinalVar cardinal $squareVar square $cubeVar cube # We borrow a 'for' loop for ...


12

A decorator is basically just a function. Example in Common Lisp: (defun attributes (keywords function) (loop for (key value) in keywords do (setf (get function key) value)) function) In above the function is a symbol (which would be returned by DEFUN) and we put the attributes on the symbol's property list. Now we can write it around a ...


12

As a rule, you should only use macros, when a better alternative does not exist. They should not be used to generate code; you should simply write the code instead (if the code is type-agnostic, write a template instead). They should not be used to define constants; constants should be defined using one of these: (static) constexpr/const variables, ...


12

From http://www.jslint.com/chistory.html ("The Development of the C Language" by Dennis M. Ritchie): Many other changes occurred around 1972-3, but the most important was the introduction of the preprocessor, partly at the urging of Alan Snyder [Snyder 74], but also in recognition of the utility of the the file-inclusion mechanisms available in BCPL and ...


11

Take a look at this posting by Matthias Felleisen to the LL1 discuss list in 2002. He suggests three main uses for macros: Data sublanguages: I can write simple-looking expressions and create complex nested lists/arrays/tables with quote, unquote, etc. neatly dressed up with macros. Binding constructs: I can introduce new binding constructs ...


11

But yes, macros can be designed and implemented better than in C/C++. The problem with macros is that they are effectively a language syntax extension mechanism that rewrites your code into something else. In the C / C++ case, there is no fundamental sanity checking. If you are careful, things are OK. If you make a mistake, or if you overuse macros you ...


11

Don't do this. Using macros to reconfigure the language like this is like writing in slang. One or two instances might not seem so bad to someone has to read it (including yourself) but every time you do it you make it that much more likely that the 'well what does that mean' effect happens. You're needlessly obscuring your code, adding a layer of mental ...


10

Macros can, as Scott notes, allow you hide logic. Of course, so do functions, classes, libraries, and many other common devices. But a powerful macro system can go further, enabling you to design and utilize syntax and structures not normally found in the language. This can be a wonderful tool indeed: domain-specific languages, code generators and more, all ...


10

Version control systems are those systems that allows you to capture changes and create a history for files. That's their purpose and the main reason for which they were created. Therefore if you would like to record changes you should use a version control system, any one out there will do. Nevertheless you should still make and informed decision, and pick ...


10

This is partly a question of semantics. The basic idea of Lisp is that the program is data that can itself be manipulated. Commonly-used languages in the Lisp family, like Scheme, don't really let you add new syntax in the parser sense; it's all just space-delimited parenthesized lists. It's just that since the core syntax does so little, you can make almost ...


10

Byte code weaving and macros are two different things. Byte code weaving is a way to intercept function calls, so that you can inject some sort of functionality (generally a cross-cutting concern such as logging) into a function call, either before or after the function is executed. Byte code weaving is done at the byte code level, which means that it ...


10

The Lisp family of languages is a fuzzy concept. The key aspects seems to be Support for functional programming Macros Homoiconic (The text <=> The AST, eg Lisp's love of parens) Dynamically typed Garbage Collected The big place where Scala falls down in is 3. Scala is hilariously not homoiconic and this is not a bad thing necessarily. It does have ...


10

When are macros idiomatic and when should they be avoided? Macros are idiomatic only when there is no alternative to their use. Examples are include guards (they are the only portable form), embedded domain-specific languages, special compiler support not available through other language features (embedding built-in macros like __FILE__, stringifying and ...


9

Macros in both C and C++ are a text replacement mechanism. Because of that, you can't define a macro in one source file and use it in a different source file. What you can do is define a macro in a header file and include that header in both C and C++ source files where you want to use that macro. Such a header would need to contain only code that comes ...


9

Using macros to create code that's syntactically identical to C but semantically different is almost always evil, especially in an unsafe language like C where the fact that something compiles in no way guarantees it actually has defined behavior at run time. If you must use a macro for something, you generally want to make it clear that a macro is being ...


8

C macros and Lisp macros are entirely different. C macros are expanded using string substitution before any other processing is done. Lisp macros are expanded after the input text has been parsed into a syntax tree1, and can use the entire language during expansion. With Lisp macros, you can not only do stupid things like #define begin {, but you can define ...


8

Lisp macros combine a few distinct properties: Macros define new syntax ↔ they use source-code as input Macros usually are run at compile-time Macros generate source-code The best applications make use of all of those aspects. Probably the most-well known example is the (loop …) in Common Lisp, it wouldn't be anywhere close to its ...


8

Rebol sounds almost like what you're describing, but a bit sideways. Rather than define specific syntax, everything in Rebol is a function call - there are no keywords. (Yes, you can redefine if and while if you truly desire to). For example, this is an if statement: if now/time < 12:00 [print "Morning"] if is a function that takes 2 arguments: a ...


8

macros have a very different meaning in C (or C++) than e.g. in Common Lisp or Scheme (or some homoiconic programming language). In particular, in Lisp or Scheme you can have macros with some local binding scope. In C or C++ the scope is textual, always from the #define till the end of translation unit or some #undef. And C/C++ macros cannot define other ...



Only top voted, non community-wiki answers of a minimum length are eligible