HNHacker News
TopNewBestAskShowJobs

lerno

1,425 karma · joined April 1, 2014

submissionscomments
lerno··on Learning C3
It 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.

lerno··on Learning C3
No, it's not a problem. If you think it's a problem, write a C compiler in C and come back to me and show me your code that doesn't have that. :)
lerno··on Learning C3
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.

lerno··on Learning C3
I was talking about function overloading. Sorry for being unclear.
lerno··on Learning C3
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.

lerno··on Learning C3
Yes, just a sponsorship. No other relationship with the project.
lerno··on Learning C3
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.
lerno··on Learning C3
"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.
lerno··on Learning C3
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.

lerno··on Learning C3
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.
lerno··on Learning C3
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

lerno··on Learning C3
Yeah, you will need to pry `for` from my dead cold hands.
lerno··on Learning C3
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.

lerno··on Learning C3
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.

lerno··on Learning C3
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.

lerno··on Learning C3
Every time
lerno··on Learning C3
Yes, C3 started as a variant of C2.
lerno··on Learning C3
Yes, and I was too slow to getting back and trying to edit it. Sorry about that.
lerno··on Learning C3
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.

lerno··on Learning C3
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*'
lerno··on Learning C3
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.
lerno··on Learning C3
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

lerno··on Learning C3
It uses operator overloading of [] &[] and "len" to create a straight for loop. Normal C for loops are there of course.
lerno··on Learning C3
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.

lerno··on Odin, a pragmatic C alternative with a Go flavour
Amusingly enough, I found that the compiler also accepted MyEnum.len (completely undocumented!). That was an easter egg!

But I'm trying to update the docs for types now. It's reasonable to just have all the compile time type properties in one place so people can find them.

lerno··on Odin, a pragmatic C alternative with a Go flavour
I saw what you wrote about the enums, anything else? And feel free to add issues for things that feel off.
lerno··on Odin, a pragmatic C alternative with a Go flavour
Oh `.elements` would you believe that this is a remnant of C2's builtin function `elemsof`? Its used so rarely (I think two uses in the entire stdlib), so it hasn't come up. I opened an issue for it: https://github.com/c3lang/c3c/issues/2130

This is a good example of the sharp edges I hope to smoothen out in 0.7-0.9.

lerno··on Odin: A programming language made for me
I always find this opinion intriguing, where it's apparently fine that globals are initialized to zero, but you are INSANE to suggest it's the default for locals. What kind of programs are y'all writing?

Clearly the lack of zeroing in C was a trade-off at the time. Just like UB on signed overflow. And now people seem to consider them "obvious correct designs".

lerno··on Reflecting on a Year of Gamedev in Zig
Out of C3, Odin and Zig, Zig is actually the language with the worst SIMD support. Odin has SIMD vectors, array programming and built in matrix types while C3 has built in SIMD vector types and operator overloading for userland numerical types such as matrix and complex types.

Odin and C3 has things like swizzling, assigning a scalar to all elements etc out of the box, whereas Zig is similar to C and just provides compiler builtins. Compare `vec * @splat(foo())` (Zig) to `vec * foo()` (Odin/C3).

lerno··on Zig, the Ideal C Replacement Or?
C gives either, I think that is the true with Odin as well, it certainly is for C3. I was assuming Zig allowed both. Is this another one of Zig being strict with ”only one way”?
← PreviousPage 5 of 13Next →