lainchan / λ
C3 Language Discussion
Anna Karenina · 2024-08-03 14:57
Hey lainons. What are your thoughts on the new C3 language?
It seems to market itself as being an "evolution" of C for C programmers, but honestly, looking at the new ""additions"", the language seems to be yet another weird grab at trying to fix something that isn't really broken. In my opinion, many of the changes (such as non-mandatory header files and generics) are unnecessary at best and genuinely bothersome at worst.
All in all, I can't really seem to find any reason to see why this project is particularly special compared to all of the other attempts at "C-killing" languages like C++, Rust, Zig, Carbon, etc. It feels like programmers have seriously been trying to kill C from the day the language was born, and every single time, they somehow end up creating something even more annoying than C is.
⍕ · 2024-08-03 16:43
The only feature "missing" from C is being able to put functions in structs (like you do with classes in C++ and Java) imo. ut that wouldnt fit in well.
Anna Karenina · 2024-08-03 20:54
>>39761
To be honest, I actually prefer it the way C does where data and code are inherently separate. That inherent difference is sort of big when you consider that it stops developers from looking at code as objects doing things, but rather, as functions always performing operations on objects as sets of data.
Iverson · 2024-08-05 07:10
I don't think I like that extra "fn" that you have to type in front of function headesr. I don't want to have to type more. An evolution of C should save my time, not take more. If I wanted to waste time I'd use Rust.
Nemissa · 2024-08-05 20:50
>>39760
The problem with these C-killer projects is they all get way too fancy for their own good. They all add a million features, all of which are themselves complex enough to require a goddamn PHD to understand.
The only things C really needs are stronger typing and a proper module system. Simple generics and better error handling would be nice too, but anything beyond that is not only superfluous but outright unwanted cruft that serves to complicate the language and obscure what the code does.
Splicer · 2024-08-06 12:04
>>39767
>If I wanted to waste time I'd use Rust.
Do you use C in your daily job?
How do you tackle around stuff like generics or what >>39769 mentions, what would a proper module system be like? Not the perfect one, but a proper one.
(Asking cause I'm curious and haven't really used much of C and strongly thinking of using rust for my personal projects to learn something new but well you say otherwise and now I'm curious)
Undisclosed · 2024-08-06 19:17
>>39772
>what would a proper module system be like?Namespaced headers. That's all you need, really.
Anna Karenina · 2024-08-06 21:18
>>39773
>Namespaced headers
yeah. accurate as fuarrrk. literally all C needs to be good enough is to just have a slightly less confusing dependency/modulation system (unlike the current translation unit system). As long as it's simple enough to stop the circular dependency problems that plague every C program, it's good enough.
Cypher · 2024-08-06 21:47
>>39774
Aren't there any forks of something which implement a better dependency system?
I never could wrap my head around it and considering I use python, it's darn confusing to understand how it works in C or even C++.
Rust has been something similar to python's import system which is why I usually incline towards it for a new language to learn.
Don't want one 11k lines long file for the whole project lol
setq · 2024-08-07 07:48
>>39769
You're missing the CPP, metaprogramming woes have to be solved and that's usually where the fancier features come in. Be it comptime of macros or whatever.
Anna Karenina · 2024-08-07 08:34
>>39779
I swear that there should be some kind of trend for programming languages called something like the "C++ Effect": Programmers attempting to simultaneously simplify and extend C just make the language both more bloated and even more annoying to debug.
drop · 2024-08-07 09:01
>>39760
I don't like it, these ppl lack of knowledge to design a good language probably there were exposed to C or C derivatives.
McCarthy · 2024-08-07 09:10
>>39774
> namespace
> dependency/modulation system
> stop circular dependency problems
Not the lain you're replying to, but thanks for the motivation. I've built namespaces into my linker for my VM bytecode assembler. At the root of the dependency graph problem is the compiler's file system/pathname flexibility. By requiring .o files to share the same primary name as the .c/.h files, and mapping the namespace tree to directory names it allows the compiler to locate headers and perform incremental compilation as well as dependency graph resolution. Really, C knows what files are #included and does provide some info to the linker in the .o __FILE__, or similar macro, but the linker doesn't resolve dep graphs.
To resolve circular references is easy. Simply DO NOT RESOLVE ANY REFERENCES...(until link time). References in intermediary (module) files thus become simply notations that a reference is needed in one of the currently scoped namespaces. This is not really applying an additional level of indirection, since linkers already do undefined name resolution... I chose to simply let the linker do all the name resolutions rather than duplicate that code in the code generator (compiler). My linker then simply loads all the modules, makes the module's table of namespaces point to actual other modules in memory, then resolves all the references. The linker first walks the dependency graph and recursively adds modules to be loaded to the load list, (unless said module name already exists in the load list). Modules are loaded in order of encounter until no more modules are in the load list; All references are then resolved and written into the code blocks: As a codeblock is placed in its final address in "process" memory, the references therein are resolved (or added to an undefined ref table for resolution after all other blocks have been arranged/finalized) [standard linker behavior].
There's really no other reason except the legacy linker and C's insistance that files can be anywhere in the FS, file content not related to its path in any way. (a folly when you think about it, since we have to #include by file path, eh?)
It's typical for C to be this way because it's paranoid about adopting a standard that would limit hardware or OS design in any way... FFS, they just now started to standardize on Po2 sized integer primitives/registers...
Anyhow, yeah, thanks for validating my desire for a linker that understands namespaces, and doesn't need a separate MAKE utility.
How does C3 stack up in this reguard, can't really bring myself to go delve into yet another language of the month... That's why I built my own, so I can begin to transpile to target languages from my own rather than learn yet another algo dialect.
nibble · 2024-08-08 08:56
I have little idea about that C3 allows or aims for but the last memorable improvement to the C syntax that didn't suck was Holy C. Anything else is not a "C killer" per se.
C++ is a superset of C which did not intend to alter anything about C but to simply incorporate it. With that there was also no intention to simplify anything but rather adding functionality with their class based OOP and generics component.
Rust aims at being something between C and C++ and with very stringent checks to avoid the common error sources of these languages but mostly only good for rewriting existing code as something more reliable.
While Zig is somewhat its own thing but if there was a successor to C then my bet would be on this. It's a fairly simple language with its stated goal to be such while also avoiding undefined behavior as far as possible and introducing comptime which is a feature that makes both C macros and generics mostly obsolete. The killer feature being substitutable allocators however which allow it to be truly platform agnostic and its own compiler system that can compile mixed projects with both C and Zig code while C is still required to compile to systems which are grossly outdated for backwards compatibility. But while it's great that we can still build programs for the tape computers that it was developed on, one feature of a modern language would be to not be bound by the nuances of hardware architectures which aren't even in production any more.
>>39761
>The only feature "missing" from C is being able to put functions in structs
God, please no! C is a procedural language. Bloating it with a V table is the exact thing that OP bemoaned here. Besides why can't you use function pointers?
>>39767
>If I wanted to waste time I'd use Rust.
kek
>>39769
>They all add a million features, all of which are themselves complex enough to require a goddamn PHD to understand.
I agree on the grounds of Rust. While having been interested I gave up half way through while Zig is truly an overhaul that does some things quite neatly and they purposefully left out variadics to keep the syntax and compiler simpler for something one can simply pass an array.
>>39772
>How do you tackle around stuff like generics
Officially you don't. But the way to achieve the same effect you use void pointers or simply copy paste your functions to alter them slightly for your purpose.
And yes, the only way I'm aware of to do modules in C is to use headers that include everything that needs to be included for that module. And be sure to use include guards to avoid circular includes. Something that is also very dated and done better by modern languages without having to use header files or bother about how the internals of a linker work. But someone had the question: #include just pastes the contents of another file in place of it self at the line where it is called. And if (usually thought recursion) you paste the same thing twice you end up with declaration conflicts. It's really this dumb and simple.
>strongly thinking of using rust for my personal projects
As one other Lain pointed out, if you don't have time and patience to waste, don't bother with it. If you aren't rewriting existing code to have a borrow check and more colorful CLI then you might be better off using C or Zig or hell even Python, Golang* and JS. And then once things work, only then rewrite it in Rust.
*Just like Carbon, I personally wouldn't touch Golang since even if it's the best way ever, I worry about Google trying to get developers trapped in yet another stupid walled garden, even if the gates are wide open for now.
>>39783
No offense but I wouldn't cast stones from your vantage point. While something like Odin which is mostly spear headed by a single hobbyist, the others have a great deal of consideration put behind them where there's many points that make sense from their reasoning if you care to dig deeper. The only way your criticism has any weight is if you happen to be another Lisp purist.
t. wrote a purpose oriented game engine in C.
Jane Doe · 2024-08-08 14:38
>>39769
>proper module system, better error handling, simple generics
These are the three that always scare me off from reaching to use C for a new project.
I despise having to check for three unique error conditions that are different for every function in the standard library. It's one of the things Rust got right. Does C3 come with changes to std?
car · 2024-08-08 15:24
>>39779
>metaprogramming woes have to be solved and that's usually where the fancier features come in
I contest both points. In my experience, you really don't need most metaprogramming stuff. Most of those features don't add enough to the programming experience on a moment-to-moment basis to justify their inclusion.
Off the top of my head, the only metaprogramming-adjacent feature I can think of with significant practical benefits is generics, and they're very simple from both a logical and implementation standpoint.
xolatile · 2024-08-10 11:31
>>39760
Russian toyboy Tsoding is shi-market it via his streams, he's the programmer who applies TypeScript brain to other good languages, such as C and Ada.
Objectively speaking, C3 is bad, because nothing can replace C at this point, and it has useless features serious C programmers don't even want.
It's a language that'll be used by the likes of Zig, Nim, Go, aka people who want to try something new, and not stick to 3-4 languages they know.
--
Conclusion: I consider it bad, other people will use it anyway, but it'll stay niche language non-the-less. Also, it's funny how unprofessional it feels...
Gyula Kovacs · 2024-08-11 17:38
>>39761
i've been learning C for the two last months, coming from OOP languages and now that i fully catch the separation between data and code i feel like adding that is not a good idea, the more you look at data as an object and think "what this structure represents and what it can do" blurs the line of whats really happening in code
Hopper · 2024-08-13 09:45
>>39804
>what's really happening in code
What do you mean by this? If you're saying "what my code compiles to", that's dependent on the platform and implementation. C is only close to the metal when the metal is close to C. Latter day C compilers perform all sorts of wacky transformations on your code in order to properly take advantage of modern hardware that can't be readily discerned just by looking at the code. C's real power is that its core feature set is very low overhead, making it easier for these kinds of optimizations to take place.
But if you're referring to the way OO makes programming logic hard to follow, I 100% agree with you. Everything is attached to something else and there's this constant feeling of "where does this actually exist?"
Switch · 2024-08-13 18:10
>>39810
> But if you're referring to the way OO makes programming logic hard to follow, I 100% agree with you. Everything is attached to something else and there's this constant feeling of "where does this actually exist?"
I used to have the same problems, but then I learned smalltalk. I believe the issue you have is purely a presentation and textual one.
If we instead of storing code in text, we instead model the system around us, then that issue goes away.
In the attached image, you can see that we can click to see up to what level we see methods on. When we look at a method it for example says inputSize (SimpleNode) so we know it exists on SimpleNode. Thus the confusion of latebinding does not really come into play once proper tools are had.
>>39804
> i've been learning C for the two last months, coming from OOP languages and now that i fully catch the separation between data and code i feel like adding that is not a good idea
Adding functions to structs is not really blurrying the lines between functions and data. You already can do that with passing functions around (read in C, function pointers).
Further, Functions are data, and having metaprogramming would allow the simplification of C by quite a bit.
For example, if we are talking about low level languages, variables, structs, objects, if, pattern matching are all reader words in forth. We can derive a fairly minimal language within forth, and then add in all the higher level sugar that C has. Things like for loops, while loops, variables, structs, etc are all higher level features we have all come to enjoy and there would be more that we could enjoy if C had metaprogramming.
>>39791
> Off the top of my head, the only metaprogramming-adjacent feature I can think of with significant practical benefits is generics, and they're very simple from both a logical and implementation standpoint.
There are plenty that we could enjoy. Things like common lisp's with-open-file[1] macro shows creating safety in the operation of files even when trying to throw outside of a scope. There are other things we can add as well such as:
1. pattern matching
2. Easy way to make tagged unions.
3. Safe way to operate over tagged unions (so you don't access the other variants versions which you can in C).
4. Stripping out the complexities of C into the language itself, so it's truly "low level".
5. Adding an Object system (Adding an object system to Scheme or Forth is a sophomore project. Where as CPP is....), something like CLOS would be quite nice.
6. Reflection/meta programming/macros of the environment may be needed for this but you could derive a module system with this. At worst you can just use a CLOS like abstraction to keep namespaces, but if you aren't hell bent on objects for everything, then using some environmental information (making a real API over the system itself) you could make a module system by utilizing the base primitives and then having a macro or function at the user level toggling this. I remember making module functors and nested modules for CL in this fashion, I would have done it differently now but it's amazing what one can do with a bit of macros and environmental reflection.
The list can go on, every time you have a custom problem where the user interface is bad, macros and environmental reflection can help sure up the user interface. They aren't an always write. However for any decent sized software project (even the boring ones), there are a few macros that really help the style and ensure better habits from the engineers involved.
On one of my current projects, we are thinking of add a macro to overide the private definitions in our language, so that when the mode is in debug, all private functions are public, so we can just hack away when debugging and generally developing. Along with some extra macros to add annotation to certain functions to basically overhaul the base languages test suite to being much more usable. We currently use a different kind of assertion macro that when tripped adds a break point to the user's REPL, all of these really do help any engineering efforts.
I could add a lot more to this thread, but proper responding would take too much time, I wish lambda was in a better state.
[1] https://novaspec.org/cl/f_with-open-file
Unknown · 2024-08-14 10:17
>>39813
>There are plenty that we could enjoy. Things like common lisp's with-open-file[1] macro shows creating safety in the operation of files even when trying to throw outside of a scope. There are other things we can add as well such as:
I mean specifically within the context of a language like C. A lot of C's appeal is that it's small and stays small. A project rolling its own object system isn't always a good thing.
HELIOS · 2024-08-14 21:07
>>39815
Yes C projects.... small
> Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
The Phantom Phreak · 2024-08-14 21:52
>>39800
This post was written by language tribalism.
Ivan Horvat · 2024-08-16 02:40
>>39810
>>39813
Yes I meant the logic way, of course there is a lot happening in the background I'm not aware of.
After reading about the function pointers and such I realized that OOP is not the problem, but the mentality behind it, I often read posts complaining how OOP tends to overcomplicate things, having a lot of classes and/or how they have to interact with each other, maybe im stupid but makes understanding the logic of a program way too hard to understand if you didn't write the entire thing from scratch.
The best example I can think of is a hitbox, is the character you controlling scanning for all hitboxes or should be the other way around, every hitbox checking for you, if you lose health, should the hitblx handle that or your character.
This could be just skill issue but I think C structs are just easier to understand and use, but if a project gets big enough or i have to make an UI without a doubt i will use OOP (may god save you if you try to do a GUI in C).
Jean Dupont · 2024-08-17 01:43
>>39830
Consider the problem of algebraic data types vs object in terms of abstraction.
I highly recommend reading what criag chambers wrote about data abstraction here:
https://www.cs.utexas.edu/%7Ewcook/Drafts/2009/essay.pdf
> I often read posts complaining how OOP tends to overcomplicate things, having a lot of classes and/or how they have to interact with each other, maybe im stupid but makes understanding the logic of a program way too hard to understand if you didn't write the entire thing from scratch.
Consider that most of those come from Java and other places, there is always the slides by Peter Norvig:
https://norvig.com/design-patterns/design-patterns.pdf
Along with the saying that design patterns are what happens when one runs out of language. this is of course hyperbole, but I'd argue that one should consider what the posters have been exposed to. Being exposed to Java and C++ will of course make you think things are more complicated than they might otherwise be if they experienced those concepts under more amenable terms.
> The best example I can think of is a hitbox, is the character you controlling scanning for all hitboxes or should be the other way around, every hitbox checking for you, if you lose health, should the hitblx handle that or your character.
This could be just skill issue but I think C structs are just easier to understand and use, but if a project gets big enough or i have to make an UI without a doubt i will use OOP (may god save you if you try to do a GUI in C).
I don't really see how this applies, even if the hitboxes were actors, computation would happen in a few places. IIRC when John carmack was playing around with functional programming and game design, he designed that every actor would take a step in parallel and collisions would happen with some logic on the combination process. I forget his exact words, but what you described is more about how one wants to process data rather than Algebraic Data types imply design X, and Objects imply design Y.
> This could be just skill issue but I think C structs are just easier to understand and use, but if a project gets big enough or i have to make an UI without a doubt i will use OOP (may god save you if you try to do a GUI in C).
Both ADT's and Objects have their place in terms of application development. They go both ways. I recommend reading the paper I linked above. Note that C could be miles easier to use if it had proper abstractions, but that's a different argument for a different day I think my post showing what kinds of macros could exist show this off.
I will make one final point, language design in an OO way is conceptually much simpler than other approaches, as one just needs to make some base object system and some rules around it, and an entire environment spawns. As all that is required is objects. Messages sends are objects, classes are objects, modules are just objects.
word · 2024-08-17 15:52
>>39819
>> Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
And what of the other half?
I used to be a big Lisp evangelist, and I still like it quite a bit; it's easily in my top ten programming languages. But over time, I've come to see the value in languages that are a bit stricter in terms of what you can do and how. Haskell, for example, cannot easily do a lot of what Lisp does, being statistically typed and more-or-less purely functional. But what you lose in expressive power, you gain in stronger guarantees of correctness and code that is easier to reason about.
pogeet · 2025-06-05 22:13
>>39761
>being able to put functions in structs
dynamic dispatch has never been a C feature so its not actually missing that one.
>>39767
the language's design was not about just being an evolution, its also about making C3 feel as if its C. Odin on the other hand didn't care about that so it ended up resembling more of a Pascal.