[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)