1. 16
  1.  

  2. 10

    While many experienced programmers can write correct systems-level code, it’s clear that no matter the amount of mitigations put in place, it is near impossible to write memory-safe code using traditional systems-level programming languages at scale.

    This is actually something I can agree with. I’m glad to finally hear a more nuanced view than “Hurr, durr, it’s impossible to write correct software”.

    1. 6

      I think it’s too soon to be picking a language to replace C. Sure it could do with replacing, but the field is advancing incredibly quickly at the moment: With time, my money would be on Zig as the generally preferred successor, over Rust.

      1. 6

        I’d prefer something now instead of waiting another five years. I’m perfectly happy with something good. instead of something perfect. There are infrastructure adoption effects to think about.

        (I would have preferred a C replacement in the early 00s, but the technology just wasn’t there yet.)

        1. 5

          The problem is that the would-be alternatives are constantly changing making adoption potentially more costly, where as C is largely unchanged since C99.

          1. 4

            The technology was there back then, but nobody bothered to make a production quality tool out of it. Which just reinforces your point about choosing something now to take this out of academia.

            I’m not that hot about rust myself (c++ level complexity in places, and the sigil soup doesn’t help), but the cambrian explosion in tools recently only means that people will get used to using different tools in the same project.

            1. 4

              Ada was in production at the time.

              1. 1

                But not with a great open source story, unfortunately.

                1. 1

                  That’s true. Many were paying for IDE’s and compilers, though. So, it was there at least for them.

              2. 1

                I’m sorry if this is an ignorant question, but what is sigil soup?

                1. 2

                  It’s not an ignorant question :-)

                  Sigils: “magic” symbols.

                  Sigil soup: lots of sigils, for example (randomly picked from somewhere on the web):

                  struct Sub<'a> {
                      name: &'a str
                  }
                  

                  There’s lots of stuff going on in that short snippet that is signified by such “magic symbols” (&? ‘? &’?). Contrast that to Ada whose most curious syntactical feature is probably the Type’Attribute syntax while everything else is spelled out in rather verbose and easy to follow language. (although the Ada 2012 expression functions aren’t really helping readability either, in my opinion)

                  1. 1

                    What’s “magic” here? Verbose? Yes. Magic? No. It would be entirely possible to allow this as

                    struct Sub {
                        name: &str
                    }
                    

                    (and indeed, in some function signatures, the 'a can be elided)

                    But that would lead to the introduction of an implicit generic parameter (anonymous lifetime), making diagnostics quite a bit harder. The current situation is clear: Sub has a lifetime that is bound to the lifetime of the reference in “name”.

                    Indeed, the change was discussed, but we decided to keep it clear when a structure is one where the borrowing rules apply. In the current version, all you need to look at is the structure generic parameters, otherwise, you’d have to look at every parameter.

                    Considering that structs with private fields are notated as:

                    struct Sub<'a> {
                      // fields hidden
                    }
                    

                    In the docs, this also allows for better visibility there.

            2. 8

              With time, my money would be on Zig as the generally preferred successor, over Rust.

              But Zig does nothing about memory safety, so I don’t see it as a step up the same way I do Rust.

              1. 4

                D has already claimed the throne.

                1. 6

                  I’m waiting for Pony to get a Better Horse mode.

                  1. 3

                    Is that a giraffe, or an OCaml?

                    1. 2

                      A Giraffe, OCaml is better Perl.

                  2. 1

                    Does anyone want to use it, though?

                    1. 11

                      To butcher the Bjarne quote, there are only two kinds of languages: the ones nobody wants to use, and the ones nobody wants to use.

                      1. 1

                        Nice!

                  3. 1

                    Interesting re your statement. How come? Why Zig? Why not ATSlang?

                    1. 3

                      Zig was just the first language that came to mind as a C successor. Simplicity is somewhat key. ATS would be a completely different direction and equally as valid.

                  4. 2

                    It looks like system programming language became synonym to compiled language.

                    Are large system not written in python? Ask Google.

                    So system languages meam those to write the kernel with?

                    What about low-level of the OS. Will memory-safe language replace the few assemblgly bits to make it boot? What about saving the state of registers to switch between processes, can it be done too? Won’t higher levels languages get in the way?

                    My belief is C is good for simple things, as with comicated things, the technical challenges of how a computer work sums up with the logical challenges the programmer carries with him.

                    Although, if you keep compiled programs to simple workhorse/engines wrapped up with glue languages, you get a simple, very debuggable system (as you can take the simple compiled programs aside to swap them with debuggers to check the input for debugging the glue wrapper code), very performant (if you avoid antipatterns like exec in a loop and go for streams when performance is at stake). And simple programs are reasonable to be kept safe.

                    I suppose there is an aim for a higher level system programming language for writing large complex programs. This is not necessarily bad:

                    This is the real question for me:

                    • Organize the code base in different processes sharing the same libraries (libc, …) and count on this process separation to keep the house tidy.
                    • Organize the code base in one binary, and count on clear and clean library API to keel the hpuse tidy, with test programs, ubiquitous debugging, …

                    My take is to do both of course !

                    • Write the bulk of the code as libraries that does all the work,
                    • Take time to think on how will this will be split onto programs for best isolation (security, performances, usability).

                    That kind of approach helps with preventing larger systems to become comllex, and spliting the part where you think of memory management (buffers, arrays…, when writing the lower level libraries), actual challenge you’re trying to solve (when writing the higher level libraries), and the integration with the system (while writing the main() programs that get split, privdropped, chrooted, connected to socket… as needed).

                    Then, you only deal with raw memory while writing your very low level.

                    Let’s not get fooled thinking we can avoid it by usibg a memory-safe language, as then you still need to write the actual language.

                    Large, and even small companies have their own labguage to fit their beed anyway: Microsoft’s C#, Google’s Go, Mozilla’s Rust, …

                    These act as your “low level libraries” on top of which you write your higher level code that get used by main() programs, regardless of the program you use.

                    The essential is to split the low-level bit tinkering from the high-level challenge thinking, and all languages can provide that. It might be more comfortable to do it in languages that enforce the separation, by putting lower-level things in the implementation of the language rather than in libraries.

                    If you consider all humans dealing with one common bag of challenges,

                    • in one case with memory safe languages,
                    • in the other with low-level language but libraries providing easy-to-use/understand operations (add, del, open, close, set, get, next, prev, …),

                    You may get about the same amount of time dealing with the risky details of the low levels (one time with the programming language internals, one time with the low level libraries).

                    All reside on how ti provide sane interfaces from the low levek ti the higher level. We night not be so good at providing good high level interfaces in low level programming languages such as C (since this is what we point at with the finger).

                    The sad thing with replacing existing low level languages by slightly higher level languages is we throw away all the existing efforts for writing the low level, and even mid level bricks (the lib… packages), and re-write them all in about 4/5 different programming languages.

                    We will get programs in high level languages using libraries written in up to 5 different languages, with things like wrappers in C to use Rust from Go.

                    Solutions the industry uses rarely comes from multiple implementations… If the future de-facto standard high performance QUIC library is in Rust, but the new CURL is in Go, then what do you think will happen?

                    A question of security? I boldly claim it is a questiob of taste and comfort, which is still a good question!