In general, a macro produces code at compile time, doesn't matter in which form it ends up in the binary, as long as the observable side effects are the same.
As mentioned the ongoing C++26 proposal with produce the desired source code at compile time, thus reducing the amount of code of libraries such that one.
(defmacro factorial (n)
(labels ((fact (m)
(if (= m 0)
1
(* m (fact (1- m))))))
`,(fact n)))
The `, has no use here and can be removed. Here the backquote and the evaluation just returns the computed value.
Thus, this is okay:
(defmacro factorial (n)
(labels ((fact (m)
(if (= m 0)
1
(* m (fact (1- m))))))
(fact n)))
LABELS defines local recursive functions. The macro returns the result of calling FACT, which is a number and which is a valid form in Common Lisp. A number evaluates to itself.
CL-USER > (macroexpand-1 '(factorial 10))
3628800
T
Common misconception of non Lispers that macros are equivalent to compile time programming. You’re not simply moving the evaluation to compile time, you’re moving it upwards outside the program space into a higher dimension of programmability.
Not to dog on C++ unfairly, CTE is pretty neat after all.
Funnily enough, PGs “On Lisp” has some really neat macros in it that demonstrate capabilities that just can’t be replicated with template based macros, iirc.
Agreed with the technical content and conclusion. However, I think it is worth pointing out that since C++11, it has had a mechanism to specify (maybe) compile-time computations that are written in plain C++: constexpr, https://en.cppreference.com/w/cpp/language/constexpr
(My parenthetical "maybe" is that I don't think compilers have to compute constexpr expressions at compile time. The compiler will be forced to when such expressions are used in contexts that require values at compile time. But I think it would be permissible for a compile to defer computation of a constexpr to runtime if the value isn't needed until runtime.)
As a code golfer, this is beyond satisfying. Doing things in a few bytes is nice, yes, but doing them in a way no reasonable mortal ever would is even better.
I don’t have any experience with Lisp. But I think C++ templates and Rust macros are both super bad and impoverished compared to what can be done in Jai.
The `#modify` thing looks pretty cool, but I can't help but think how a compiler/ide is supposed to analyze the body of such function and provide suggestions. Rust macros have a similar issue, but it's offsetted by the fact that generics are pretty powerful too and can be fully analyzed by the compiler.
-- https://godbolt.org/z/TWe11hM6j
Nicely put 5040 in ESI register at compile time.
Granted, C++ isn't Lisp, but already has quite a room for creativity at compile time, and C++26 might finally have compile time reflection as well.
I don't see it here. This looks like compile-time execution to compute values. If it would be a macro, it could return source code.
Example of a library that generates serialization code, https://github.com/getml/reflect-cpp
As mentioned the ongoing C++26 proposal with produce the desired source code at compile time, thus reducing the amount of code of libraries such that one.
Thus, this is okay:
LABELS defines local recursive functions. The macro returns the result of calling FACT, which is a number and which is a valid form in Common Lisp. A number evaluates to itself.Not to dog on C++ unfairly, CTE is pretty neat after all.
Funnily enough, PGs “On Lisp” has some really neat macros in it that demonstrate capabilities that just can’t be replicated with template based macros, iirc.
I can visualize this metaphor just fine, but I can't tell why it's useful. Can you make this concept more concrete?
(My parenthetical "maybe" is that I don't think compilers have to compute constexpr expressions at compile time. The compiler will be forced to when such expressions are used in contexts that require values at compile time. But I think it would be permissible for a compile to defer computation of a constexpr to runtime if the value isn't needed until runtime.)
C++ macros can only take types and numbers (until variadic), and writing any code to operate on those inputs is challenging.
It's not too bad :)
https://www.forrestthewoods.com/blog/using-jais-unique-and-p...