Notice how a static immutable array is created by a lambda at compile time. The lambda never appears in the executable. Before D, I'd use a separate C executable to generate the tables, which were then #include'd.
More impressive: manipulating strings at compile-time.
Even more impressive: using string manipulation at compile-time to build valid D code, then use string mixins to inject it into the current program, passing it on to the compiler to be compiled as part of the program being built. This is done by std.regex to compile regular expressions to native code during compilation.
Even further impressive: using a string import to read a DSL from disk, transpiling it into D code, and passing it on to the compiler. This is used by Vibe.d to compile HTML templates to native code.
Granted, all this is fairly old news, and a few other languages have since caught up.
You can get virtually the same effect with marking functions `constexpr` in C++. Yes, you need to do it explicitly, and yes, you can't call functions that aren't marked `constexpr` inside, but it's more or less the same - just opt-in.
In fact, since C++20, you don't need any template metaprogramming for compile-time sorting - std::sort is constexpr! [0]
I’m worried about the compile-time performance though. C++ compilers currently use direct tree-walking on the AST to interpret code, which is going to be horrendously slow once you go past a certain number of elements.
Not sure why this was downvoted, it was a valid comparison from someone who is highly involved in Nim development. Nim compiles to C(by default, other backends available) and the static means it is done at compile time.
The article itself is a D implementation of something done in C++ to show how D does it, and how much simpler it is. The Nim example is right in line with this.
Nim can run almost any code (that doesn’t interface with C FFI) at compile time, since in addition to a compiler they have a bytecode VM that executes a large subset of the language. (https://nim-lang.org/docs/nims.html) Really cool stuff, the only other language that I’ve seen doing this approach is Jai, which is sadly still in closed development. (Jai’s CTE is much grander in scope, in that it would be able to do anything normal code can do.)
C++ (gcc and clang) and D’s compile-time evaluation is a bit more limited in scope, and still uses a tree-walk interpreter, although D might also migrate to a bytecode VM someday (https://dlang.org/blog/2017/04/10/the-new-ctfe-engine/)
Obligatory C++ comparison: C++ has constexpr since C++11 and constinit since C++20. They mean more or less the same when applied to variables ("must be evaluated at compile-time"), but constinit does not imply constness.
Another example of compile time evaluation: one of my favourite things about the guile repl is the ,opt[imize] command at the repl. You run it on a piece of code and it shows you the result of macro expansion, inlining, DCE, some other things, and most notably partial evaluation.
One example of how I use it can be found here: https://git.sr.ht/~bjoli/goof-loop/#speed in the first example where I contrast ,expand (macro expansion) and ,opt (the source->source optimizer.
After spending time with Elixir which has hygienic macros and the whole language available to you at compile-time, this is no longer interesting to the old C++ dev in me
[+] [-] WalterBright|4 years ago|reply
https://github.com/dlang/dmd/blob/master/src/dmd/backend/ope...
Notice how a static immutable array is created by a lambda at compile time. The lambda never appears in the executable. Before D, I'd use a separate C executable to generate the tables, which were then #include'd.
The lambdas can also include sanity checks:
https://github.com/dlang/dmd/blob/master/src/dmd/backend/ope...
[+] [-] unknown|4 years ago|reply
[deleted]
[+] [-] CyberShadow|4 years ago|reply
More impressive: manipulating strings at compile-time.
Even more impressive: using string manipulation at compile-time to build valid D code, then use string mixins to inject it into the current program, passing it on to the compiler to be compiled as part of the program being built. This is done by std.regex to compile regular expressions to native code during compilation.
Even further impressive: using a string import to read a DSL from disk, transpiling it into D code, and passing it on to the compiler. This is used by Vibe.d to compile HTML templates to native code.
Granted, all this is fairly old news, and a few other languages have since caught up.
[+] [-] dmead|4 years ago|reply
haskell templates are similar.
[+] [-] MauranKilom|4 years ago|reply
In fact, since C++20, you don't need any template metaprogramming for compile-time sorting - std::sort is constexpr! [0]
Demo: https://godbolt.org/z/6M1Wqc31W
[0]: https://en.cppreference.com/w/cpp/algorithm/sort
[+] [-] cyber_kinetist|4 years ago|reply
[+] [-] dom96|4 years ago|reply
[+] [-] melissalobos|4 years ago|reply
The article itself is a D implementation of something done in C++ to show how D does it, and how much simpler it is. The Nim example is right in line with this.
[+] [-] cyber_kinetist|4 years ago|reply
C++ (gcc and clang) and D’s compile-time evaluation is a bit more limited in scope, and still uses a tree-walk interpreter, although D might also migrate to a bytecode VM someday (https://dlang.org/blog/2017/04/10/the-new-ctfe-engine/)
[+] [-] wbradley|4 years ago|reply
[+] [-] MauranKilom|4 years ago|reply
[+] [-] bjoli|4 years ago|reply
One example of how I use it can be found here: https://git.sr.ht/~bjoli/goof-loop/#speed in the first example where I contrast ,expand (macro expansion) and ,opt (the source->source optimizer.
[+] [-] davydog187|4 years ago|reply
[+] [-] toomanydoubts|4 years ago|reply
[+] [-] faisal_ksa|4 years ago|reply