[HN Gopher] Learning C3
       ___________________________________________________________________
        
       Learning C3
        
       Author : lerno
       Score  : 188 points
       Date   : 2025-05-29 13:33 UTC (9 hours ago)
        
 (HTM) web link (alloc.dev)
 (TXT) w3m dump (alloc.dev)
        
       | Defletter wrote:
       | C3 looks promising, but any language that supports nulls _needs_
       | null-restricted types, not whatever those contract comments are.
       | If I wanted to have to null-check everything, or YOLO it, I would
       | just write Java... and even Java is seeking to fix this:
       | https://openjdk.org/jeps/8303099
        
         | 90s_dev wrote:
         | I'm on the fence about function contracts like this. I've seen
         | them for a decade in other languages, but never really used
         | them, so I can't say how I feel about them.
         | 
         | But having them be _inside comments_ is just weird.
        
           | Jtsummers wrote:
           | It's a directive that happens to be placed at the tail end of
           | a comment. Reading the documentation the doc comment stops
           | being a comment-proper with the first @-directive, after that
           | it's a list of directives. SPARK started in comments, ACSL is
           | placed in specially marked comments. SPARK 2014 moved into
           | Ada proper using Ada 2012 features (aspects). The difference
           | between SPARK 2014's annotation and this is basically, are
           | the annotations above the function or after the function
           | declaration?
        
           | joshring2 wrote:
           | It is different yes, having read a good amount of it by now I
           | find it work's pretty well in practice. It means you can
           | incrementally adopt them if you like and code with or without
           | them looks quite similar assuming you documented your code,
           | the function signatures look the same as well which I
           | appreciate.
        
         | lerno wrote:
         | It's an interesting problem. Originally I experimented with
         | both having ` _` and ` &` syntax, so `int&` being a ref (non
         | null) and `int_` being a pointer. The thing you notice then are
         | two things:
         | 
         | 1. You want almost all pointer parameters non null.
         | 
         | 2. Non-null variables is very hard to fit in a language without
         | constructors.
         | 
         | Approaches to avoid constructors/destructors such as ZII play
         | very poorly with ref values as well. What you end up with is
         | some period of time where a value is quasi valid - since non-
         | null types need to be assigned and it's in a broken state
         | before it's initially assigned.
         | 
         | It's certainly possible to create generic "type safe" non-null
         | types in C3, but they are not baked into the language.
        
           | aidenn0 wrote:
           | > Approaches to avoid constructors/destructors such as ZII
           | play very poorly with ref values as well. What you end up
           | with is some period of time where a value is quasi valid -
           | since non-null types need to be assigned and it's in a broken
           | state before it's initially assigned.
           | 
           | I don't see that as a problem; don't separate declaration
           | from assignment and it will never be unassigned. Then a ZII
           | non-null pointer is always a compile-time error.
        
             | wavemode wrote:
             | > don't separate declaration from assignment and it will
             | never be unassigned
             | 
             | That's tricky when you want to write algorithms where you
             | can start with an uninitialized object and are guaranteed
             | to have initialized the object by the time the algorithm
             | completes. (Simplest example - create an array B which
             | contains the elements of array A in reverse order.)
             | 
             | You can either allow declaring B uninitialized (which can
             | be a safety hazard) or force B to be given initial values
             | for every element (which can be a big waste of time for
             | large arrays).
        
             | lerno wrote:
             | I don't quite see what you mean. As an example, let's say
             | you use ZII and allocate 100 objects in a single
             | allocation. These are now zero initialized and so either
             | invalid (which should not happen) or do not hold non-null
             | types. Can you explain how you intend this scenario to be
             | resolved in your case?
             | 
             | Otherwise it's quite straightforward that they have an
             | uninitialized state (zero) and are then wired up when used.
             | Trying to prevent null pointers here is something that the
             | program to do. However, making the compiler guarantee
             | without requiring constructors it is a challenge I don't
             | know how to tackle.
        
               | aidenn0 wrote:
               | > As an example, let's say you use ZII and allocate 100
               | objects in a single allocation
               | 
               | If you want to do that you can always use a nullable
               | type. You can always assign it to a non-nullable type
               | after initialization if you plan on using the aggregate a
               | lot.
               | 
               | Usually you provide a vector type though, which has an
               | underlying nullable array, but maintains a fill-index
               | such that for all i < fill-index it the value is
               | initialized, and then you have two indexing operations;
               | one which returns a nullable type and the other which
               | bounds-checks and returns a non-nullable type.
        
               | lerno wrote:
               | This could make sense for a from-scratch language, but C3
               | is trying to be an evolution of C, and such constraints
               | would make it so much of a different language that it
               | would be way out of scope.
               | 
               | I think Rust and similar languages fill that niche
               | already, so there is no real need to try to offer that
               | type of alternative.
        
               | aidenn0 wrote:
               | I think we are miscommunicating. Let's imagine a language
               | called "C@" where the only difference is that "@" is used
               | in place of "*" for a non-nullable pointer type:
               | typedef struct {          foo @*data; //Non-nullable
               | pointer to nullable pointer of foo          size_t size;
               | size_t fill;       } foo_vec;              void
               | foo_vec_push(foo_vec @v, foo @x) {         if (v->fill ==
               | v->size) {           //realloc and zero data         }
               | else {           data[idx++] = v;         }       }
               | foo @ foo_vec_get(foo_vec @v, size_t idx) {         if
               | (idx < fill) {           return (foo @)(data+idx);
               | } else {           abort();         }       }
               | 
               | I'm not sure how this constraint makes it "so much of a
               | different language" at all.
        
           | bryanlarsen wrote:
           | the hacker news markdown parser seems to have swallowed your
           | asterisks, which are essential to understanding your comment.
        
             | trealira wrote:
             | Yeah, if you want to use asterisks without italicizing your
             | text, you need to escape them with backslashes, and then
             | you can write things like 5 * 2 * 1 = 10. That is, you'd
             | write it like this:                 5 \* 2 \* 1 = 10
        
             | lerno wrote:
             | Yes, and I was too slow to getting back and trying to edit
             | it. Sorry about that.
        
           | lerno wrote:
           | I'm unable to edit this now... that should teach me not to
           | comment and then go to kendo practice... It should say '*'
           | and '&' and 'int&' and 'int*'
        
       | 90s_dev wrote:
       | > Don't misunderstand me - I love using foreach in other
       | languages; the added syntax better expresses your intent,
       | reducing logic errors. It did jump out at me as "this isn't C"
       | though.
       | 
       | Because it's not. The whole point of C is that you know exactly
       | what's going on and it's relatively clear in the code itself. C++
       | hides logic in abstractions for the sake of convenience. This is
       | a C++ thing. How does it know how to iterate? Is it moving
       | pointers or indexing them or what? Not only is it hiding logic
       | but it also prevents me from modifying the logic. I could easily
       | change a C for loop to use i += 2 instead of i++ if I wanted,
       | that's the beauty of it. With this, I have to read some docs
       | first to see how their abstraction works, and then hope it allows
       | me to modify how it's used to how I need.
        
         | lerno wrote:
         | It uses operator overloading of [] &[] and "len" to create a
         | straight for loop. Normal C for loops are there of course.
        
           | 90s_dev wrote:
           | I just skimmed the C3 spec[1] on foreach and foreach_r, and
           | I'm still confused as to how to move elements by anything
           | other than 1, if it's even possible.
           | 
           | [1] https://c3-lang.org/implementation-
           | details/specification/#fo...
        
             | lerno wrote:
             | It isn't possible. Use `for` instead. `foreach` isn't
             | trying to be a one-stop-shop, but rather help the common
             | case of looping over an array or list. Because it handles
             | caching the length and such it's more efficient than a
             | casually written `for` loop. This is the 90% solution to
             | iteration.
        
               | 90s_dev wrote:
               | Ah that makes sense, as long as the length doesn't change
               | during iteration, which like you said is the 90% case. As
               | long as I also can use for(), then that's fine.
        
               | lerno wrote:
               | Yeah, you will need to pry `for` from my dead cold hands.
        
         | falcor84 wrote:
         | Just curious - in what situations would you want to use
         | `foreach` (with the intent to iterate over a sequence), but use
         | `i += 2` instead of `i++`? I can only think of a situation
         | where I want to group elements by pairs, but then I'm
         | explicitly not doing a "for each", and would prefer to
         | explicitly use a regular `for`.
        
           | renrutal wrote:
           | Vectorization unrolling?
        
             | Windeycastle wrote:
             | In that case I advice using actual C3 vectors. They are a
             | built in type that will use simd (or similar) under the
             | hood if the compilation target supports it.
        
         | itishappy wrote:
         | > I could easily change a C for loop to use i += 2 instead of
         | i++ if I wanted, that's the beauty of it.
         | 
         | If you're not doing something for each element of a collection,
         | you should not be using a `foreach` loop. In exchange for not
         | exposing the implementation, you immediately know the behavior.
         | You also don't have to worry about checking the rest of the
         | loop body for later mutations.
        
         | Rochus wrote:
         | This is a completely valid and reasonable argument; I don't
         | understand why people are downvoting it.
        
           | 90s_dev wrote:
           | Votes on HN are fairly random.
        
             | Rochus wrote:
             | So we should get rid of them, especially the downvotes.
        
           | dgellow wrote:
           | Because it seems fairly obvious you can use a standard `for`
           | if you need more control over the iteration.
        
             | Rochus wrote:
             | The argument is still reasonable. The OP didn't claim that
             | there is no "for" loop, but that the "foreach" is a high-
             | level construct which is not intuitively comprehensible and
             | thus doesn't fit to the C3 language design.
        
         | munificent wrote:
         | _> The whole point of C is that you know exactly what 's going
         | on and it's relatively clear in the code itself._
         | 
         | Given the widespread undefined behavior and the ways that
         | compilers aggressively rely on that to reorganize and optimize
         | your code, that hasn't been the case for many many years.
         | 
         | Sure, if you're using dmr's compiler on a PDP-11, then C is a
         | pretty transparent layer over assembly, which is itself a
         | fairly thin layer over the CPU. But today, C is an ambiguous
         | high level communication language for a highly optimizing
         | compiler which in turn produces output consumed by deep
         | pipeline CPUs that freely reschedule the generated
         | instructions.
        
           | tgv wrote:
           | Rescheduling instructions is not relevant, is it? Are there
           | architectures which change the semantics of the instructions
           | by changing execution order?
        
             | munificent wrote:
             | _> Rescheduling instructions is not relevant, is it?_
             | 
             | I guess it probably depends on _why_ a user might want to
             | think of C as low level. The user visible semantics shouldn
             | 't change, I hope, but the performance might.
        
       | lerno wrote:
       | Some other links links on C3 that might be interesting:
       | 
       | Interviews:
       | 
       | - https://www.youtube.com/watch?v=UC8VDRJqXfc
       | 
       | - https://www.youtube.com/watch?v=9rS8MVZH-vA
       | 
       | Here is a series doing various tasks in C3:
       | 
       | - https://ebn.codeberg.page/programming/c3/c3-file-io/
       | 
       | Some projects:
       | 
       | - Gameboy emulator https://github.com/OdnetninI/Gameboy-Emulator/
       | 
       | - RISCV Bare metal Hello World:
       | https://www.youtube.com/watch?v=0iAJxx6Ok4E
       | 
       | - "Depths of Daemonheim" roguelike
       | https://github.com/TechnicalFowl/7DRL-2025
       | 
       | Tsoding's "first impression" of C3 stream:
       | 
       | - https://www.youtube.com/watch?v=Qzw1m7PweXs
        
       | tiniuclx wrote:
       | This looks promising, but I wonder what advantages it has over
       | Rust. Community support is very important for a programming
       | language, and given that this is the first time I am hearing
       | about this project, it still has some way to go.
       | 
       | Edit: ABI compatibility & two way interop with C seems to be a
       | pretty big selling point!
        
         | synergy20 wrote:
         | Rust is way more complex to say the least, in fact it's the
         | sole reason why it still has the same market share as
         | COBOL(https://www.tiobe.com/tiobe-index/). Rust 1.0 was
         | released 10 years ago by the way.
        
           | metaltyphoon wrote:
           | Tiobe really?
        
             | mahmoudimus wrote:
             | I hate on Tiobe as well but it is a good benchmark for
             | world wide adoption commercially.
        
               | dymk wrote:
               | It's basically just the number of Stack Overflow
               | questions / Google hits there are about a language, it's
               | a pretty poor benchmark
        
               | orangeboats wrote:
               | TIOBE is an especially poor benchmark if the programming
               | language community is not highly reliant on general-
               | purpose search engines like Google.
               | 
               | Take into consideration that most Rust programmers rely
               | on https://docs.rs etc rather than Googling something.
        
             | dgb23 wrote:
             | I don't 100% understand. Do they really just look at search
             | engine stats?
             | 
             | https://www.tiobe.com/tiobe-
             | index/programminglanguages_defin...
             | 
             | That seems like it's a potentially interesting signal, but
             | the index implies that it is about adoption.
             | 
             | Looking at the index, it seems like Python has a 2.5x
             | higher rating than C and Java. While I assume that Python
             | is a widely adopted language, this feels wrong in many
             | ways.
             | 
             | But given that they just look at search engine stats, one
             | can explain the higher rating, because Python is often used
             | by novice programmers and tech workers who are not
             | primarily programmers/SWEs.
        
             | garbagecoder wrote:
             | OK, so show us your source that shows Rust has higher
             | uptake.
        
               | leadingthenet wrote:
               | https://spectrum.ieee.org/top-programming-languages-2024
        
               | hu3 wrote:
               | Rust jobs: 0.04
               | 
               | Python jobs: 0.9
               | 
               | Seems about right, maybe.
               | 
               | Except there's no way PHP (0.09), Ruby (0.07) and Go
               | (0.1) are on the same magnitude as Rust jobs.
               | 
               | So this site doesn't pass the sniff test for me.
        
         | fn-mote wrote:
         | I want to second this comment.
         | 
         | The comparison shouldn't be with C, it should be with C++,
         | Rust, or Zig.
         | 
         | The place to go is actually the C3 comparison page:
         | 
         | https://c3-lang.org/faq/compare-languages/
         | 
         | There you can see that there are very few items "in C3 but not
         | Rust", for example. Mainly "it's a familiar C-like language".
         | 
         | I am also suspicious of the macro system. I'd like more of an
         | explanation of how it works. Especially how it relates to Zig
         | comptime, and whether it has "hygiene" problems. Hygiene to me
         | means: can a variable name in a macro expansion refer to a
         | variable outside of the macro? (The concern is that this could
         | be accidental.)
         | 
         | https://c3-lang.org/generic-programming/macros/
        
           | lerno wrote:
           | All macros are hygienic. However, you can pass in a lazy
           | expression which then is evaluated in its original context.
           | 
           | The macro cannot insert variables into the caller scope, nor
           | cause the function to return. Mostly it's similar to a static
           | inline function with optionally polymorphic arguments. But it
           | can do some more things as well, but nothing violating
           | hygiene.
        
           | sph wrote:
           | The comparison is with C because C3 wants to be "C, but
           | better". Rust doesn't have that design goal, it doesn't look
           | like an incremental update to C and it's more akin to C++ in
           | philosophy (with an ML-inspired syntax)
           | 
           | There is a space for a C alternative, and Rust ain't it.
        
         | joshring2 wrote:
         | Community support in C3 is massive, as you can use C libraries
         | directly, it might parallel or exceed Rust on that metric, and
         | the barrier to adding native C3 wrappers or versions is
         | significantly lower too.
         | 
         | Rust is solving a different problem, that of safety over all
         | else. C3 on the other hand is more akin to developer experience
         | above all else.
         | 
         | If you find something that should be easier to do in C3, that's
         | a bug.
        
           | dymk wrote:
           | Is massive really the right word to use here? I've never
           | heard of C3, meanwhile most big tech companies are hiring
           | Rust developers of some sort.
        
         | lerno wrote:
         | Rust is a C++ competitor with all the semantic complexity that
         | comes with it. And similar compile times.
         | 
         | C3 is more complex than C (because of a net increase of
         | features), but it's miles from C++ and Rust in complexity and
         | it compiles as fast or faster than C.
        
           | vram22 wrote:
           | How does C3 compared to C in runtime performance?
        
             | lerno wrote:
             | I based the LLVM-IR output on what Clang outputs for C. And
             | so they should be identical. C3 has a single module option
             | for maximum interfunctional optimizations, but Clang can
             | give you LTO for the same thing.
             | 
             | So they should be the same, otherwise it's a bug.
        
       | plainOldText wrote:
       | Has anyone tried both C3 and Hare[1]. How do they fare? There
       | seems to be quite the overlap between the two.
       | 
       | [1] https://harelang.org/
        
         | mustermannBB wrote:
         | Problem with Hare is that it is (or at least was last time I
         | checked) Linux/Unix only and so by design. That kinda makes it
         | DOA for many.
        
           | plainOldText wrote:
           | Indeed. There's a port for macOS though.
           | 
           | And yet out all these newer C-like languages, it looks like
           | Hare probably takes the crown for simplicity. Among other
           | things, Hare uses QBE[1] as a backend compiler, which is
           | about 10% the complexity of LLVM.
           | 
           | [1] https://c9x.me/compile/
        
             | sitkack wrote:
             | QBE is an art project. Read the source.
        
               | orthoxerox wrote:
               | I tried. It's not at Arthur Whitney's levels of
               | terseness, but compared to the source of, say, Redis it's
               | a pain to read.
        
             | lerno wrote:
             | The downside of QBE is that it then requires an assembler
             | and a linker. And QBE's only input and output is still
             | text.
             | 
             | Plus the "frontend -> QBE -> assembler -> binary" process
             | is slower than "frontend -> LLVM -> binary". And LLVM is
             | known for being a fairly slow compiler.
        
               | stevefolta wrote:
               | The downside of QBE is that it doesn't have a way to
               | generate debug symbols. But I still love and use it.
        
         | amelius wrote:
         | There's also Zig in the C-alternatives space.
         | 
         | https://ziglang.org/
        
           | mapcars wrote:
           | There is also Odin: https://odin-lang.org/
           | 
           | Would be nice to have a list of these and comparisons
        
             | uecker wrote:
             | There is also C23 and at some point C2Y.
             | 
             | C23 got typeof, constexpr constants, enums with underlying
             | type, embed, auto, _BitInt, checked integers, new struct
             | compatibility rules, bit constants, nullptr, initialization
             | with {}, and various other improvements and cleanups.
             | Modern C code - while still being simple - can look quite
             | different than what people might be used to.
             | 
             | C2Y already already got named loops, countof, if with
             | declarations, case range expressions, _Generic with type
             | arguments, and quite a lot of UB removed from the core
             | language. (our aim is also to have a memory safe subset)
        
               | eacnamn wrote:
               | What's the state of things regarding statement
               | expressions? Are there any intentions of adding them? I
               | think I've read Meneide make an offhand comment about
               | that.
        
               | uecker wrote:
               | This is being discussed. It has some weird corner cases
               | and limitations though. But since it is widely used and
               | supported, I think there is a good chance that some
               | harmonized version of it will be standardized.
        
       | TheMagicHorsey wrote:
       | After using Rust on a couple of projects, I understand the appeal
       | of simpler languages like C3, Zig, and Odin. As one commenter
       | very aptly put on the Zig subreddit ... "I used Zig for (internal
       | tool) because I wanted to quickly write my tool and debug it, and
       | not spend all my time debugging my knowledge of Rust."
        
         | tayo42 wrote:
         | Is Zig really that common at this point that you'd feel
         | comfortable using it for a work project? Its not just going to
         | piss off the next person and have them need to rewrite it? I
         | guess Rust has the same problem to some extent but there is a
         | lot of resources for writing Rust out there now
        
           | chrisco255 wrote:
           | Depends on the project and the team, yeah? In my opinion, Zig
           | is simple and lends itself to simpler patterns. Ultimately
           | though it's always a trade-off to consider talent, project
           | scope, team preferences, technical challenges, long-term
           | maintenance, etc.
        
           | throwawaymaths wrote:
           | I suppose the nice thing about zig is that for many things,
           | porting back to C is relatively straightforward and if you
           | wanted to incrementally do it, there's a way to do that, too.
        
           | TheMagicHorsey wrote:
           | I wouldn't use Zig for something production critical, but
           | other people like TigerBeetle have decided its good enough
           | for them, and they seem to be doing fine commercially, so I
           | just refrain from saying its not production ready.
           | 
           | But one things for sure ... there's just not a lot of sample
           | Zig code out there. Granted its simpler than Rust, but your
           | average AI tool doesn't get how to write idiomatic Zig.
           | Whereas most AI tools seem to get Rust code okay. Maybe
           | idiomatic Zig just isn't a thing yet. Or maybe idiomatic Zig
           | is just like idiomatic C ... in the eye of the beholder.
        
       | rdtsc wrote:
       | Interestingly there is also C2: http://c2lang.org
        
         | sgt wrote:
         | There's also C4, but that's either an explosive or a notation
         | language for modeling software architecture.
        
           | rdtsc wrote:
           | Hopefully the notation language folks take full advantage of
           | puns associated with explosives.
        
             | lerno wrote:
             | Every time
        
           | lambertsimnel wrote:
           | And C in Four Functions:
           | 
           | https://news.ycombinator.com/item?id=22353532
        
         | lerno wrote:
         | Yes, C3 started as a variant of C2.
        
       | aidenn0 wrote:
       | Anyone know the story behind Huly (which appears to be a company
       | making a web-app mostly in node) sponsoring C3?
        
         | joshring2 wrote:
         | As far as I am aware, they support open source as part of their
         | marketing campaign, smart move in my view and helps grass roots
         | projects, Win win.
        
           | lerno wrote:
           | Yes, just a sponsorship. No other relationship with the
           | project.
        
       | SuperV1234 wrote:
       | Most of these features have been used by countless C++ developers
       | for the past decades -- I really don't see the point in adopting
       | a language that's mostly C++ but without some of the warts.
       | Either pick C++ or something like Rust.
        
         | throwawaymaths wrote:
         | the problem with picking C++ is that eventually you onboard
         | someone who uses the warts in their code, and then the warts
         | become like craft glitter.
        
           | jack_pp wrote:
           | Maybe instead of building a restricted C++ we should be
           | building parsers that restrict what C++ features we use.
        
             | pjmlp wrote:
             | It is called static analysis tool.
        
           | pjmlp wrote:
           | A matter of code review and static analysis configuration.
           | 
           | Unfortunately adhering to modern tooling is always a quixotic
           | battle, even when they come for free on modern FOSS
           | compilers.
        
         | Retro_Dev wrote:
         | To me it didn't really feel like C++; it is much less
         | complicated. Could you explain more what you mean by this?
        
         | jokoon wrote:
         | I would prefer a "lightweight" C++.
         | 
         | C++ is fine, but it's insanely slow to compile.
         | 
         | I generally like C++, but I could trade anything to make it
         | faster to compile, and most of the time, I just use a small
         | subset of C++ that I feel okay with.
        
           | pjmlp wrote:
           | Pre-compiled headers, binary libraries, avoid header only
           | libraries, if lucky to be on latest clang/VC++, modules.
        
           | SuperV1234 wrote:
           | C++ is not slow to compile. The Standard Library is.
        
         | pjmlp wrote:
         | Is for the _C++ without Classes_ crowd, mostly.
         | 
         | Personally when I initially learned C++ back in 1993, with
         | Turbo C++ 1.0 for MS-DOS, I hardly saw a reason to further use
         | C instead C++, other than being required to do so.
        
         | joshring2 wrote:
         | C3 benefits from focusing more on the problem at hand than
         | language complexities.
         | 
         | There are definitely advantages to simpler tools, you can
         | streamline development and make people more productive quicker.
         | Compare that scenario to C++ where you first have to agree the
         | features you're allowing and then have to police that subset
         | throughout on every PR.
        
         | arp242 wrote:
         | C3 is "mostly C++" in the same way that my bicycle is "mostly a
         | motorbike".
        
       | throwawaymaths wrote:
       | a nitpick:
       | 
       | a bit down the page there is stuff on the case syntax. The fact
       | that "you can't have an empty break" is a good choice, but the
       | fact that having two cases do the same thing has syntax
       | case X:         case Y:
       | 
       | is footgun waiting to happen. I would strongly suggest the
       | authors of C3 make stacking cases look like this:
       | case X, Y:
        
         | fragmede wrote:
         | seems subtle to distinguish between case 3,4: for values 3 or
         | 4, and case (3,4): for an array with the value [3,4]
        
           | throwawaymaths wrote:
           | oof. To me switch/case mentally implies constant time
           | matching and routing, I wonder if that is the case (it could
           | be if arrays have compile-time known length).
        
             | lerno wrote:
             | You have both in C3:                   switch (x) {
             | case 0:              ...            case 1 + 1:
             | ...         }
             | 
             | This will behave in the normal way. But you can also have:
             | switch {             case foo() > 0:               ...
             | case bar() + baz() == s:               ...         }
             | 
             | In which case it lowers to the corresponding if-else.
        
               | norir wrote:
               | I am not a fan of this design in a low level language.
               | The first version of switch does exactly one thing and is
               | very clear. The second now is forcing me to think both
               | about branching logic and control flow. I understand the
               | surface level appeal of the syntax, but if I encountered
               | code written with this feature in the wild, I would think
               | something must have gone wrong in the program design.
        
               | throwawaymaths wrote:
               | i think hlls sometimes distinguish between these
               | situations with a different keyword.
        
         | lerno wrote:
         | "case X, Y" works for 3-4 values, but for something longer
         | problems accumulate:                   case SOME_BAD_THING,
         | SOME_OTHER_CONDITION, HERE_IS_NUMBER_THREE:             foo();
         | int y = baz();
         | 
         | Placing them on the next row is fairly hard to read
         | case SOME_BAD_THING, SOME_OTHER_CONDITION,
         | HERE_IS_NUMBER_THREE, AND_NUMBER_FOUR, AND_NUMBER_FIVE,
         | AND_THE_LAST_ONE:             foo();             int y = baz();
         | 
         | In C I regularly end up with lists that have 10+ fallthroughs
         | like this, because I prefer complete switches over default for
         | enums at least.                   case SOME_BAD_THING:
         | case SOME_OTHER_CONDITION:         case HERE_IS_NUMBER_THREE:
         | case AND_NUMBER_FOUR:         case AND_NUMBER_FIVE:
         | case AND_THE_LAST_ONE:             foo();             int y =
         | baz();
         | 
         | I understand the desire to use "case X, Y:" instead, and I did
         | consider it at length, but I found the lack of readability made
         | it impossible. One trade off would have been:
         | case SOME_BAD_THING,         case SOME_OTHER_CONDITION,
         | case HERE_IS_NUMBER_THREE,         case AND_NUMBER_FOUR,
         | case AND_NUMBER_FIVE,         case AND_THE_LAST_ONE:
         | foo();             int y = baz();
         | 
         | But it felt clearer to stick to C syntax, despite the
         | inconsistency.
        
           | fn-mote wrote:
           | > In C I regularly end up with lists that have 10+
           | fallthroughs like this [...]
           | 
           | Frankly, that seems like a code smell, not a problem that
           | needs a solution within the language.
        
             | lerno wrote:
             | No, it's not a problem.
        
       | CyberDildonics wrote:
       | There was already a better evolution of C called clay. It had
       | templates and ownership. It was C compatible and could be used as
       | a substitute.
       | 
       | https://github.com/jckarter/clay/wiki/Clay-for-C---programme...
        
         | lerno wrote:
         | It might be interesting to note that none of the C
         | alternatives: C3, Zig, Odin, Hare, Jai use ownership nor RAII.
         | 
         | Overloading is also generally missing from today's breed of C
         | alternatives.
         | 
         | There has certainly been many attempts at C alternatives: eC,
         | Cyclone etc etc
        
           | lnkl wrote:
           | C3 has operator overloading.
        
             | lerno wrote:
             | I was talking about function overloading. Sorry for being
             | unclear.
        
           | CyberDildonics wrote:
           | I think Jai has operator overloading. I won't use any of
           | these though because I can't give up value semantics of data
           | structures. In modern C++ it massively simplifies things and
           | basically makes memory and most resource management a non
           | issue.
        
       | PaulHoule wrote:
       | Strikes me as so so.
       | 
       |  _defer_ is the kind of thing I would mock up in a hurry in my
       | code if a language or framework lacked the proper facilities, but
       | I think you are better served with the with statement in Python
       | or automated resource management in Java.
       | 
       | Similarly I think people should get over Optional and Either and
       | all of that, my experience is that it is a lot of work to use
       | those tools properly. My first experience with C was circa 1985
       | when I was porting a terminal emulator for CP/M from _Byte_
       | magazine to OS-9 on the TRS-80 Color Computer and it was pretty
       | traumatic to see how about 10 lines of code on the happy path got
       | bulked up to 50 lines of code that had error handling weaved all
       | around it and through it. When I saw Java in  '95 I was so
       | delighted [1] to see a default unhappy path which could be
       | modified with catch {} and fortified with finally {}.
       | 
       | It's cool to think Exceptions aren't cool but the only
       | justification I see for that is that it can be a hassle to
       | populate stack traces for debugging and yeah, back in the 1990s,
       | Exceptions were one of the many things in the C++ spec that
       | didn't actually work. Sure there are difficult problems with
       | error handling such as _errors don 't respect your ideas of
       | encapsulation_ [2] but those are rarely addressed by languages
       | and frameworks even though they could be
       | 
       | https://gen5.info/q/2008/08/27/what-do-you-do-when-youve-cau...
       | 
       | putting in ? or Optional and Either though are just moving the
       | deck chairs on the _Titanic_ around.
       | 
       | [1] I know I'm weird. I squee when things are orderly, more
       | people seem to squee when they see that Docker lets them run 5
       | versions of libc and 7 versions of Java and 15 versions of some
       | library.
       | 
       | [2] Are places where the "desert of the real" intrudes on "the
       | way things are spozed to be"
        
         | lerno wrote:
         | C3 error handling is fairly novel though. It tries to find a
         | sweet spot between composability, explicitness and C
         | compatibility.
         | 
         | The try-catch has nice composability:                   try {
         | int x = foo_may_fail();             int y = bar_may_fail(x);
         | } catch (... ) {             ...         }
         | 
         | Regular _Result_ types need to use flatmap for this, and of
         | course error codes or multiple returns also struggle with this.
         | With C3:                   int? x = foo_may_fail();
         | int? y = bar_may_fail(x);         if (catch err = y) {
         | ...            return;         }         // y is implicitly
         | unwrapped to "int" here
         | 
         | This is not to say it would satisfy you. But just to illustrate
         | that it's a novel approach that goes beyond Optional and Either
         | and has a lot in common with try-catch.
        
       | Daril wrote:
       | Based on this comparison :
       | 
       | https://c3-lang.org/faq/compare-languages/
       | 
       | One would argue that the best C/C++ alternative/evolution
       | language to use would be D. D also has its own cross-platform GUI
       | library and an IDE.
       | 
       | I wonder for which reasons D doesn't have a large base adoption.
        
         | lerno wrote:
         | I can only speak for myself:
         | 
         | 1. It is so big.
         | 
         | 2. It still largely depends on GC (less important actually)
         | 
         | It keeps adding features, but adding features isn't what makes
         | a language worth using. In fact, that's one of the least
         | attractive things about C++ as well.
         | 
         | So my guess:
         | 
         | 1. It betted wrong on GC trying to compete with C++.
         | 
         | 2. After failing to get traction, kept adding features to it -
         | which felt a bit like there was _some_ feature that would
         | finally be the killer feature of the language.
         | 
         | 3. Not understanding that the added features actually made it
         | _less_ attractive.
         | 
         | 4. C++ then left the GC track completely and became a more low
         | level alternative to, at which point D ended up in a weird
         | position: neither high level enough to feel like a high level
         | alternative, nor low level enough to compete with C++.
         | 
         | 5. Finally: the fact that it's been around for so long and
         | never taking off makes it even harder for it to take off
         | because it's seen as a has-been.
         | 
         | Maybe Walter Bright should create a curated version of D with
         | only the best features. But given how long it takes to create a
         | language and a mature stdlib, that's WAY easier said than done.
        
           | GoblinSlayer wrote:
           | Indeed, first get traction, then add as many features as you
           | want and become perl. That's the real carcinization.
        
           | pjmlp wrote:
           | I think the biggest issue has been trying to always chase the
           | next big thing that eventually could bring mindshare to D,
           | while not finishing the previous attempts, so there are quite
           | a few half baked features by now.
           | 
           | Even Andrei Alexandrescu eventually refocused on C++, and is
           | contributing to some of the C++26 reflection papers.
        
             | fuzztester wrote:
             | >while not finishing the previous attempts
             | 
             | I agree, and that applies to many software projects, and
             | not just programming languages only.
             | 
             | >so there are quite a few half baked features by now
             | 
             | what are some of those half baked features?
        
               | pjmlp wrote:
               | The new allocators, some corner cases of the destroy and
               | destructors, not everything on Phobos is @nogc friendly,
               | BetterC still chockes on many common C extensions, DIP
               | 1000, the whole set of @live semantics.
               | 
               | Now there is a new GC being redesigned, and there are
               | discussions about a possible Phobos V3.
        
           | arp242 wrote:
           | The dmd compiler not being open source until 2017[1] made it
           | more or less a non-starter for a great many use cases. That
           | would have been okay in the 80s, but with tons of languages
           | to choose from now your language needs something very special
           | to sell licenses.
           | 
           | [1]: Specifically: _" The Software is copyrighted and comes
           | with a single user license, and may not be redistributed. If
           | you wish to obtain a redistribution license, please contact
           | Digital Mars."_
        
           | zamalek wrote:
           | 6. It has exceptions.
           | 
           | Many people consider that an anti-feature.
        
       | synergy20 wrote:
       | I wish C3 has simple RAII/object/class built-in(no inheritance
       | needed, no Polymorphism is fine, just some Encapsulation better
       | than c's struct with function pointers), then it becomes a more
       | powerful c, and a much simpler c++, really a sweet spot in the
       | middle of both and works for 90% of the c/c++ use cases.
        
       | jcaguilar wrote:
       | I only wish that the syntax was changed to make it easier to
       | search/grep for the definition of functions and types. Odin makes
       | this so nice, you can search for "<function|type name> ::". Maybe
       | moving the return type to after the closing parenthesis would be
       | enough?
       | 
       | 2 more wishes: add named parameters and structured concurrency
       | and I think it would be a very cool language.
        
       ___________________________________________________________________
       (page generated 2025-05-29 23:00 UTC)