... downsides of local gotos? Obviously I know the consensus is generally against, but AFAICT Dijkstra was mostly upset it made manual reasoning hard, but nowadays compilers all use SSA and basic/extended block graphs that have no problem with it.
November 8, 2025 at 11:44 PM
... downsides of local gotos? Obviously I know the consensus is generally against, but AFAICT Dijkstra was mostly upset it made manual reasoning hard, but nowadays compilers all use SSA and basic/extended block graphs that have no problem with it.
I would need to test but I suspect GCC/clang would do that. If I remove any expression in my example at all it figures out there is a common tail, so a single call in each position should qualify, unless we're unlucky and it inlines them all first. Curious to hear though what your thoughts are on...
November 8, 2025 at 11:44 PM
I would need to test but I suspect GCC/clang would do that. If I remove any expression in my example at all it figures out there is a common tail, so a single call in each position should qualify, unless we're unlucky and it inlines them all first. Curious to hear though what your thoughts are on...
It's a lot simpler too than trying to implement your own Swift style witness tables or having a templated derived with an untemplated base to share generated code. But you still need a template wrapper for type safety, and you're adding a layer of indirection.
November 3, 2025 at 8:30 PM
It's a lot simpler too than trying to implement your own Swift style witness tables or having a templated derived with an untemplated base to share generated code. But you still need a template wrapper for type safety, and you're adding a layer of indirection.
One thing I don't like about the separation is you can't easily mix args that are compile time fixed with ones that vary at runtime in the same call. You can do foo<ctime_arg>(runtime_arg) but that requires defining foo with that exact separation in mind.
October 29, 2025 at 10:57 PM
One thing I don't like about the separation is you can't easily mix args that are compile time fixed with ones that vary at runtime in the same call. You can do foo<ctime_arg>(runtime_arg) but that requires defining foo with that exact separation in mind.
Well yes but that's just more of the problem with the current model. C++ and Rust very slowly accrete more and more things that are allowed in constexpr/constfn until it converges to let you do everything you could at runtime. In a few decades they'll catch up to lisp.
October 29, 2025 at 3:50 PM
Well yes but that's just more of the problem with the current model. C++ and Rust very slowly accrete more and more things that are allowed in constexpr/constfn until it converges to let you do everything you could at runtime. In a few decades they'll catch up to lisp.
In Rust or C++ you do shenanigans like variadic template recursion, or generating trait impls for many different lengths of tuple that each define some different associated type. You have to circumlocute to get your Turing completeness.
October 29, 2025 at 3:44 PM
In Rust or C++ you do shenanigans like variadic template recursion, or generating trait impls for many different lengths of tuple that each define some different associated type. You have to circumlocute to get your Turing completeness.
It's part of the general benefit that you get rid of metaprogramming being done in a totally separate language than regular programming. In Zig, if you want to conditionally use one type vs another you just write a regular if. If you want to loop over types at compile time you write a regular loop.
October 29, 2025 at 3:43 PM
It's part of the general benefit that you get rid of metaprogramming being done in a totally separate language than regular programming. In Zig, if you want to conditionally use one type vs another you just write a regular if. If you want to loop over types at compile time you write a regular loop.
I'm somewhat sympathetic to the readability argument but I'm more concerned that functions that take types and return types are being treated as special and have their own dedicated metalanguage with completely different semantics. Just treating them as functions nicely unifies things.
October 29, 2025 at 3:40 PM
I'm somewhat sympathetic to the readability argument but I'm more concerned that functions that take types and return types are being treated as special and have their own dedicated metalanguage with completely different semantics. Just treating them as functions nicely unifies things.
Vec is a function that takes a type X and returns a new container type that holds Xs. Viewed this way <> is just the call syntax for compile time functions, except that C++ and Rust also introduced constexpr/constfn that still use the () syntax so it's just inconsistent.
October 29, 2025 at 3:39 PM
Vec is a function that takes a type X and returns a new container type that holds Xs. Viewed this way <> is just the call syntax for compile time functions, except that C++ and Rust also introduced constexpr/constfn that still use the () syntax so it's just inconsistent.
I actually think C++ and Rust are in the wrong here, generics/templates are just function calls where the argument is a type. Zig uses parens for this reason.
October 29, 2025 at 3:30 PM
I actually think C++ and Rust are in the wrong here, generics/templates are just function calls where the argument is a type. Zig uses parens for this reason.
C++11 added "trailing return type syntax". You signal you are using it with auto, it doesn't actually mean the type is inferred, it's hack to avoid new lang keywords. The benefit is that by the time the arrow is reached the parser knows more, so some return types can be written more concisely.
October 28, 2025 at 6:22 PM
C++11 added "trailing return type syntax". You signal you are using it with auto, it doesn't actually mean the type is inferred, it's hack to avoid new lang keywords. The benefit is that by the time the arrow is reached the parser knows more, so some return types can be written more concisely.
In short, the Rust aliasing model is very strict, and IME it's more difficult to write unsafe code satisfying it than satisfying C++'s more conservative rules.
In short, the Rust aliasing model is very strict, and IME it's more difficult to write unsafe code satisfying it than satisfying C++'s more conservative rules.