\

Comptime – C# meta-programming with compile-time code generation and evaluation

102 points - last Saturday at 8:49 PM

Source
  • spicyusername

    today at 12:37 PM

    I started using C# recently for a hobby project writing a game engine on top of Monogame, and I have been very surprised at how nice of a language C# is to use.

    It has a clean syntax, decent package management, and basically every language feature I regularly reach for except algebraic data types, which are probably coming eventually.

    I think the association of .NET to Microsoft tarnished my expectations.

    • CharlieDigital

      today at 12:04 AM

      C# meta programming game is strong. Source generators are :chefs_kiss:

        • daeken

          today at 4:51 AM

          I love (and heavily use) source generators, but the development experience is godawful. Working with the raw Roslyn types is painful at best and this is compounded by them having to be written against .NET Standard, severely limiting the use of newer .NET functionality.

          Eventually I want to write a good baseline library to use for my source generators -- simplifying finding definitions with attributes, mapping types to System.Type, adding some basic pattern matching for structures -- but haven't found a way to do it that's general enough while being very useful.

            • pjmlp

              today at 8:53 AM

              Yeah, it is kind of sad that it was the community that had to step up for some T4 like experience instead of string concatenation.

              That isn't as cool as Aspire and AI features.

      • rubenvanwyk

        today at 9:21 AM

        How is Comptime different from default AOT compilation? I assume it can work with third-party libraries that AOT don’t work with yet?

          • betaporter

            today at 12:21 PM

            I believe this is like `constexpr` for C#.

        • smcnc

          today at 2:30 AM

          I think Zig really shines here: https://ziglang.org/documentation/master/#comptime

            • pjmlp

              today at 6:37 AM

              D was already doing it in 2010 thereabouts, an then there is the whole reader macros in Lisp and Scheme.

                • jibal

                  today at 8:52 AM

                  And Nim, which has multiple levels of metaprogramming.

              • Zambyte

                today at 3:40 AM

                A key difference is that in this C# package, `[Comptime]` is an attribute (annotation? not sure on the C# term) applied to methods. In Zig, the `comptime` keyword can be applied to pretty much any expression. In the C# package, if you want to do factorial at runtime and at compile time, (I think, from reading the README) you need to define the same function twice, one with `[Comptime]` and once without. Contrast this to Zig, where if you have a regular runtime factorial function, you can just execute it at compile time like:

                    const x = comptime factorial(n);
                
                Another limitation of the C# package is it only works with primitive types and collections. Zig comptime works on any arbitrary types.

                  • hahn-kev

                    today at 4:13 AM

                    You don't. The way it works is that it intercepts the call site when the input args are constant. If they're not then it won't be replaced and it will call the original method. C# source generators can't replace method definitions, however a call site can be changed to another method via source generators.

                      • NuclearPM

                        today at 5:20 AM

                        You don’t what?

                          • ygra

                            today at 6:51 AM

                            You don't have to write the method twice. Source generators can only add new code, they cannot take away a method you declared, so it will still be there at runtime when called with non-constant arguments.

                • Tiberium

                  today at 3:44 AM

                  There's also Nim, it shines even more in compile time and has proper compile time macros :)

              • mfro

                yesterday at 11:58 PM

                This seems like the kind of feature that should be built into MSBuild.

                  • eterm

                    today at 12:12 AM

                    It's a lot less ergonomic but there are source generators in C# :

                    https://devblogs.microsoft.com/dotnet/introducing-c-source-g...

                    That said, for more complex results, you'd typically load a serialization on start.

                    I can see the value in this tool, but there must be a fairly limited niche which is too expensive to just have as static and run on start-up and cache, but not so large you'd prefer to just serialize, store and load.

                    It also needs to be something that is dynamic at compile time but not at runtime.

                    So it's very niche, but it's an interesting take on the concept, and it looks easier to use than the default source generators.

                      • richardw

                        today at 1:33 AM

                        Not terribly niche. All config that isn’t environment-specific and is used in inner loops or at startup. It’s even got a test for serialised values so can be used to speed your case up:

                        https://github.com/sebastienros/comptime/blob/main/test/Comp...

                        But you need to be sure you won’t want to change without compiling.

                          • eterm

                            today at 9:34 AM

                            Well it also needs to be something that you need to generate/calculate, otherwise you would just write by hand the code that comptime outputs.

                        • piskov

                          today at 12:51 AM

                          Also t4 templates before that for at least a decade

                            • pjmlp

                              today at 8:54 AM

                              And much more developer friendly.

                  • jauntywundrkind

                    today at 3:12 AM

                    Makes me think of Boo language; Boo was so good at metaprogramming and multi-phasr programming! A very fine .NET language that was so far ahead of the curve, with having the tools of that language be usable at runtime.

                    Alas many of the docs are offline now. But it had great quasiquotes, which let you write code that gets turned into AST that you can then process. Good macros. A programmable compiler pipeline. So much. Alas, obscured now. https://boo-language.github.io/

                      • daeken

                        today at 3:14 AM

                        Boo and Nemerle both were really showing what was possible in .NET back in the early days. I still miss the metaprogramming they had, not to mention their pattern matching (which C# has closed the gap on, but is still way, way short.)

                    • mgaunard

                      today at 12:03 AM

                      So it's like C++ consteval?