[HN Gopher] C++ Template Macroprogramming versus Lisp Macros
___________________________________________________________________
C++ Template Macroprogramming versus Lisp Macros
Author : oumua_don17
Score : 41 points
Date : 2024-11-15 19:47 UTC (3 hours ago)
(HTM) web link (simondobson.org)
(TXT) w3m dump (simondobson.org)
| liontwist wrote:
| Lisp macros can take arbitrary parameters and are written in
| lisp.
|
| C++ macros can only take types and numbers (until variadic), and
| writing any code to operate on those inputs is challenging.
| spacechild1 wrote:
| The post is actually about template _meta_ programming.
| 'template macroprogramming' isn't really a thing.
| knome wrote:
| https://github.com/knome/metabrainfuck/blob/master/bf.cpp
|
| It's not too bad :)
| Etheryte wrote:
| 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.
| scott_s wrote:
| 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.)
| spacechild1 wrote:
| Note that C++20 introduced _consteval_ as a means to enforce
| compile time computation. See
| https://en.cppreference.com/w/cpp/language/consteval
| pjmlp wrote:
| Besides consteval and constinit, you can force evaluation with
| static constexpr.
| pjmlp wrote:
| Factorial macro example in C++23 metaprogramming,
| #include <iostream> consteval long factorial (int n) {
| if (n == 0) return 1; return n * factorial(n - 1);
| } int main() { std::cout << factorial(7) <<
| std::endl; }
|
| Exercise for the reader if using VC++ or clang/ninja, use _import
| std_ instead.
|
| -- 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.
| lispm wrote:
| macro programming in Lisp would be "programming programs".
|
| 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.
| pjmlp wrote:
| 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.
|
| 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.
| forrestthewoods wrote:
| 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.
|
| https://www.forrestthewoods.com/blog/using-jais-unique-and-p...
| SkiFire13 wrote:
| 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.
| pjmlp wrote:
| Except Jai is never going to get the use any of them have, so
| we use what is there.
| lispm wrote:
| (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 a
| number, which is a valid _form_ in Common Lisp. A number
| evaluates to itself.
| qertuiopas wrote:
| Dudertiosa
| James_K wrote:
| Macaroni art versus the Mona Lisa.
| thunkingdeep wrote:
| 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.
___________________________________________________________________
(page generated 2024-11-15 23:00 UTC)