7 ms·
Learning C3
- dedicate 1y ago[dead]
- Defletter 1y agoC3 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 https://openjdk.org/jeps/8303099
- 90s_dev 1y agoI'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 1y agoIt'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 1y agoIt 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 1y agoIt'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 1y ago> 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 1y ago> 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).
- Maxatar 1y agoI don't think that's much of an issue. If you need deferred initialization then stick to a pointer and then once the pointer is initialized shadow it with a reference. int* pre_foo = null; ... initialize pre_foo ... int& foo = *pre_foo;
- netbioserror 1y agoNim solves this problem by only having two explicit, restricted nullable types: Pointers and references. Pointers are manually managed, references are automatically managed, both start as nil and must have their referenced objects instantiated manually. The entire rest of the language is built on pass-by-value using stack values and stack-managed hidden unique pointers. You basically never actually need to use a ref or a pointer unless you're building an interface to a C or C++ library. I having written a 40k line production application with no reference or pointer types anywhere. Almost any case you'd need is covered by simply passing a compound type or dynamic container as a mutable value, where it's impossible to perform any kind of pointer or reference semantics on it. The lifetime is already managed, so semantically it's just a value.
- monkeyelite 1y agoWhy is there only one way to solve a problem?
- 90s_dev 1y ago> 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.
- deleted 1y ago[deleted]
- lerno 1y agoIt uses operator overloading of [] &[] and "len" to create a straight for loop. Normal C for loops are there of course.
- 90s_dev 1y agoI 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/#foreach-and-foreach_r-statements https://c3-lang.org/implementation-details/specification/#fo...
- lerno 1y agoIt 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.
- 1y ago
- lerno 1y agoSome other links links on C3 that might be interesting: Interviews: - https://www.youtube.com/watch?v=UC8VDRJqXfc https://www.youtube.com/watch?v=UC8VDRJqXfc - https://www.youtube.com/watch?v=9rS8MVZH-vA 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/ https://ebn.codeberg.page/programming/c3/c3-file-io/ Some projects: - Gameboy emulator https://github.com/OdnetninI/Gameboy-Emulator/ https://github.com/OdnetninI/Gameboy-Emulator/ - RISCV Bare metal Hello World: https://www.youtube.com/watch?v=0iAJxx6Ok4E https://www.youtube.com/watch?v=0iAJxx6Ok4E - "Depths of Daemonheim" roguelike https://github.com/TechnicalFowl/7DRL-2025 https://github.com/TechnicalFowl/7DRL-2025 Tsoding's "first impression" of C3 stream: - https://www.youtube.com/watch?v=Qzw1m7PweXs https://www.youtube.com/watch?v=Qzw1m7PweXs
- tiniuclx 1y agoThis 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 1y agoRust 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/ https://www.tiobe.com/tiobe-index/). Rust 1.0 was released 10 years ago by the way.
- metaltyphoon 1y agoTiobe really?
- mahmoudimus 1y agoI hate on Tiobe as well but it is a good benchmark for world wide adoption commercially.
- dymk 1y agoIt's basically just the number of Stack Overflow questions / Google hits there are about a language, it's a pretty poor benchmark
- orangeboats 1y agoTIOBE 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 https://docs.rs etc rather than Googling something.
- dgb23 1y agoI don't 100% understand. Do they really just look at search engine stats? https://www.tiobe.com/tiobe-index/programminglanguages_definition/ 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.
- plainOldText 1y agoHas 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/ https://harelang.org/
- mustermannBB 1y agoProblem 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 1y agoIndeed. 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/ https://c9x.me/compile/
- sitkack 1y agoQBE is an art project. Read the source.
- orthoxerox 1y agoI 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 1y agoThe 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 1y ago
- deleted 1y ago[deleted]
- TheMagicHorsey 1y agoAfter 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 1y agoIs 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 1y agoDepends 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 1y agoI 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 1y agoI 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 1y agoInterestingly there is also C2: http://c2lang.org http://c2lang.org
- sgt 1y agoThere's also C4, but that's either an explosive or a notation language for modeling software architecture.
- rdtsc 1y agoHopefully the notation language folks take full advantage of puns associated with explosives.
- lerno 1y agoEvery time
- lambertsimnel 1y agoAnd C in Four Functions: https://news.ycombinator.com/item?id=22353532 https://news.ycombinator.com/item?id=22353532
- lerno 1y agoYes, C3 started as a variant of C2.
- aidenn0 1y agoAnyone know the story behind Huly (which appears to be a company making a web-app mostly in node) sponsoring C3?
- SuperV1234 1y agoMost 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 1y agothe 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 1y agoMaybe instead of building a restricted C++ we should be building parsers that restrict what C++ features we use.
- pjmlp 1y agoIt is called static analysis tool.
- pjmlp 1y agoA 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 1y agoTo me it didn't really feel like C++; it is much less complicated. Could you explain more what you mean by this?
- jokoon 1y agoI 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.
- throwawaymaths 1y agoa 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 1y agoseems 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 1y agooof. 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 1y agoYou 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.
- deleted 1y ago[deleted]
- norir 1y agoI 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.
- CyberDildonics 1y agoThere 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---programmers https://github.com/jckarter/clay/wiki/Clay-for-C---programme...
- lerno 1y agoIt 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 1y agoC3 has operator overloading.
- lerno 1y agoI was talking about function overloading. Sorry for being unclear.
- CyberDildonics 1y agoI 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.
- lerno 1y agoJai has operator overloading yes.
- PaulHoule 1y agoStrikes 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-caught-an-exception/ 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 1y agoC3 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.
- curtisszmania 1y ago[dead]
- Daril 1y agoBased on this comparison : https://c3-lang.org/faq/compare-languages/ 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 1y agoI 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 1y agoIndeed, first get traction, then add as many features as you want and become perl. That's the real carcinization.
- pjmlp 1y agoI 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.
- synergy20 1y agoI 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 1y agoI 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.
- lerno 1y agoIt was the minimal change from C. It's fairly easy regex out the types, so while not as nice as Odin, it should be straightforward. Named parameters are already in the language. Regarding concurrency, I don't want to pick a single concurrency model over another. I will see what hooks I can make for userland additions, but the language will not be opinionated about concurrency.
- abujazar 1y agoWill everything blow up when they create C4?
- drob518 1y agoUpvoted for humor.
- rubit_xxx17 1y agoI love this. But this was distracting: > Macros are a bag of worms. Sure, they can be a great source of protein, but will you really see me eating them? I might use worms when I'm fishing, but I don't see much use for them around the home. To express my opinion outside of a metaphor: macros have niche use cases, are good at what they do, but shouldn't be abused. One example of this abuse would be making a turing-complete domain-specific language inside of some macro-supporting programming language.
- kasajian 1y agoI wish there was a way to transpile this to C. That way it can be both an escape hatch, and a way to target unusual platforms not directly supported by C3 lang.
- lerno 1y agoA C backend is planned.
- HeartofCPU 1y agoHow does it compare to to Zig ?
- zdkaster 1y agohttps://c3-lang.org/faq/compare-languages/#zig https://c3-lang.org/faq/compare-languages/#zig