top | item 30317408

Compile-Time Sort in D

115 points| teleforce | 4 years ago |dlang.org

57 comments

order
[+] WalterBright|4 years ago|reply
I like to use compile time code to generate fixed tables, like these:

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...

[+] CyberShadow|4 years ago|reply
(2017)

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
pretty much lisp macros with the constraints of a compile language.

haskell templates are similar.

[+] MauranKilom|4 years ago|reply
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]

Demo: https://godbolt.org/z/6M1Wqc31W

[0]: https://en.cppreference.com/w/cpp/algorithm/sort

[+] cyber_kinetist|4 years ago|reply
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.
[+] dom96|4 years ago|reply
Same code in Nim:

    import algorithm

    const a = [ 3, 1, 2, 4, 0 ]
    static: echo(sorted(a))
[+] melissalobos|4 years ago|reply
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.

[+] cyber_kinetist|4 years ago|reply
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/)

[+] wbradley|4 years ago|reply
The idea of static meaning “fully evaluate this at compile time” in D is a good one.
[+] MauranKilom|4 years ago|reply
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.
[+] bjoli|4 years ago|reply
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.

[+] davydog187|4 years ago|reply
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
[+] toomanydoubts|4 years ago|reply
You'll have lots of fun in Haskell should you decide to learn it.
[+] faisal_ksa|4 years ago|reply
D has many cool features. I always wonder why it is not (more?) popular?