Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

What if we have a C that removes the quirks without adding too much brain drain?

So no implicit type conversions, safer strings, etc.



Walter Bright will probably show up soon to plug D's BetterC mode, but if he doesn't, still check it out.

https://dlang.org/spec/betterc.html


I've seen this concept tried a few times (For example, MS tried it with Managed C++). The inevitable problem you run into is any such language isn't C++. Because of that, you end up needing to ask, "why pick this unpopular half C/C++ implementation and not Rust/go/D/Java/python/common lisp/haskell."

A big hard to solve problem is you are likely using a C because of the ecosystem and/or the performance characteristics. Because of the C header/macro situation that becomes just a huge headache. All the sudden you can't bring in, say, boost because the header uses the quirks excluded from your smaller C language.


I too have been thinking a lot about a minimum viable improvement over C. This requires actually being able to incrementally port your code across:

* "No implicit type conversions" is trivial, and hardly worth mentioning. Trapping on both signed and unsigned overflow is viable but for hash-like code opting in to wrapping is important.

* "Safer strings" means completely different things to different people. Unfortunately, the need to support porting to the new language means there is little we can do by default, given the huge amount of existing code. We can however, add new string types that act relatively uniformly so that the code can be ported incrementally.

* For the particular case of arrays, remember that there are at least 3 different ways to compute its length (sentinel, size, end-pointer). All of these will need proper typing support. Particularly remember functions that take things like `(begin, middle end)`, or `(len, arr1[len], arr2[len])`.

* Support for nontrivial trailing array-or-other datums, and also other kinds of "multiple objects packed within a single allocation", is essential. Again, most attempted replacements fail badly.

* Unions, unfortunately, will require much fixing. Most only need a tag logic (or else replacement with bitcasting), but `sigval` and others like it are fundamentally global in nature.

* `va_list` is also essential to support since it is very widely used.

* The lack of proper C99 floating-point support, even in $CURRENTYEAR, means that compile-to-C implementations will not be able to support it properly either, even if the relevant operations are all properly defined in the new frontend to take an extra "rounding mode" argument. Note that the platform ABI matters here.

* There are quite a few things that macros are used for, but ultimately this probably is a finite set so should be possible to automatically convert with a SMOC.

Failure to provide a good porting story is the #1 mistake most new languages make.


I have a plan for a safe C and also type-safe generic and bounds-checked containers. Here is some experimental (!) example: https://godbolt.org/z/G4ncoYjfW

Except for some missing pieces, this is safe and I have a prototype based on GCC that would warn about any unsafe features. va_list can be safely used at least with format strings and for union I need an annotations. Life times are the bigger outstanding issue.


> The lack of proper C99 floating-point support, even in $CURRENTYEAR

What do you mean? What's wrong with floating point numbers in C99?


I mean things like: compilers don't support the pragmas, and if the compiler can "see" constants they are often evaluated with the wrong rounding mode.

I'm far from an expert but I've seen enough to know it's wrong.


Oh, I see. I didn't realize that happened.


If you can live without much of the ecosystem (specially if has async) there is way to write rust very simple.

The core of Rust is actually very simple: Struct, Enum, Functions, Traits.


But unfortunately you will encounter async in libraries you want to use, so this approach is difficult


This seems like such an obvious thing to have - where is it? Zig, Odin, etc. all seem much more ambitious.


There have been attempts over the years. See here, a decade ago: https://blog.regehr.org/archives/1287

> eventually I came to the depressing conclusion that there’s no way to get a group of C experts — even if they are knowledgable, intelligent, and otherwise reasonable — to agree on the Friendly C dialect. There are just too many variations, each with its own set of performance tradeoffs, for consensus to be possible.


That was fascinating reading and a graveyard of abandoned "better C" dialects: SaferC, Friendly C, Checked C, etc.


I think if you are going to fix C's footguns you'll have to change so much you end up with a totally new language anyway, and then why not be ambitious? It costs a lot to learn a new language and people aren't going to bother if the only benefit it brings is things that can sort of mostly be caught with compiler warnings and static analysis.


I think the only "C replacement" that is comparable in complexity to C is [Hare](https://harelang.org/), but several shortcomings make it unsuitable as an actual C replacement in many cases (little/no multithreading, no support for macOS/Windows, no LLVM or GCC support, etc.).


And why do you think Zig (and Odin, but I'm not really familiar with that one) is not comparable in complexity to C? If you start with C, replace the preprocessor language with the host language, replace undefined behavior with illegal behavior (panics in debug builds), add different pointer types for different types of pointers (single object pointers, many object pointers, fat many object pointers (slices), nullable pointers), and make a few syntactic changes (types go after the names of values in declarations, pointer dereference is a postfix operator, add defer to move expressions like deallocation to the end of the scope) and write a new standard library, you pretty much have Zig.


Swift is really great these days and supports Windows and Linux. It almost feels like a scripting language other than the compile time of course.


I still have a hard time adopting a language/ecosystem that was originally tied to a particular platform, and is still "owned" by the owners of that platform.

Sun actually did it right with Java, recognizing that if they mainly targeted SunOS/Solaris, no one would use it. And even though Oracle owns it now, it's not really feasible for them to make it proprietary.

Apple didn't care about other platforms (as usual) for quite a long time in Swift's history. Microsoft was for years actively hostile toward attempts to run .NET programs on platforms other than Windows. Regardless of Apple's or MS's current stance, I can't see myself ever bothering with Swift or C#/F#/etc. There are too many other great choices with broad platform and community support, that aren't closely tied to a corporation.


.NET recently had a (very) minor controversy for inserting what amounts to a GitHub Copilot ad into their docs. So yeah, it sure feels like "once a corporate language, always a corporate language", even if it's transferred to a nominally independent org. It might not be entirely rational, but I certainly feel uncomfortable using Swift or .NET.


> Microsoft was for years actively hostile toward attempts to run .NET programs on platforms other than Windows

It's been 10 years. Even before that, no action was ever taken against Mono nor any restriction put or anything else. FWIW Swift shares a similar story, except Apple started to care only quite recently about it working anywhere else beyond their platforms.

Oh, and by the way, you need to look at these metrics: https://dotnet.microsoft.com/en-us/platform/telemetry

Maybe take off the conspiracy hat?

> There are too many other great choices with broad platform and community support

:) No, thanks, I'm good. You know why I stayed in .NET land and didn't switch to, say, Go? It's not that it's so good, it's because most alternatives are so bad in one or another area (often many at the same time).


There is no universe where I'm doing to use Apple tooling on a day to day basis. Their DX is the worst among big tech companies by far.


They have quite robust command line tooling and a good VS Code plugin now. You don’t need to use Xcode anymore for Swift.


I have a plan for a safe subset of C which would just require a compiler to warn about certain constructs. I also have a proposal for a safe string type. I am not so sure about type conversions though, you get useful warnings already with existing compiler flags and you can solve the problem in the article already just by wrapping the types in structs.


Because it's easier to add a warning or error. Don't like implicit conversions? Add a compiler flag, and the issue is basically gone.

Safer strings is harder, as it gets into the general memory safety problem, but people have tried adding safer variants of all the classic functions, and warnings around them.


Maybe just unsafe rust?


I'm inferring that you think Rust adds too much brain drain? If so, what?


The borrow checker rejects loads of sound programs - just read https://rust-unofficial.github.io/too-many-lists/

Aliasing rules can also be problematic in some circumstances (but also beneficial for compiler optimisations).

And the orphan rule is also quite restrictive for adapting imported types, if you're coming from an interpreted language.

https://loglog.games/blog/leaving-rust-gamedev/ sums up the main issues nicely tbh.


> The borrow checker rejects loads of sound programs

I bet assembly programmers said the same about C!

Every language has relatively minor issues like these. Seriously pick a language and I can make a similar list. For C it will be a very long list!


> The borrow checker rejects loads of sound programs - just read https://rust-unofficial.github.io/too-many-lists/

It's important to be careful here: a lot (most? all?) of these rejections are programs that could be sound in a hypothetical Rust variant that didn't assert the unique/"noalias" nature of &mut reference, but are in fact unsound in actual Rust.


I love Rust, but I after doing it for a little while, I completely understand the "brain drain" aspect... yes, I get significantly better programs, but it is tiring to fight the borrow-checker sometimes. Heck, I currently am procrastinating instead of going into the ring.

Anyhow, I won't go back to C++ land. Better this than whatever arcane, 1000-line, template-hell error message that kept me fed when I was there.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: