C++ Encounters Of The Rusty Zig Kind

The rust language logo being branded onto a microcontroller housing

There comes a time in any software developer’s life when they look at their achievements, the lines of code written and the programming languages they have relied on, before wondering whether there may be more out there. A programming language and its associated toolchains begin to feel like familiar, well-used tools after you use them for years, but that is no excuse to remain rusted in place.

While some developers like to zigzag from one language and toolset to another, others are more conservative. My own journey took me from a childhood with QuickBasic and VisualBasic to C++ with a bit of Java, PHP, JavaScript, D and others along the way. Although I have now for years focused on C++, I’m currently getting the hang of Ada in particular, both of which tickle my inner developer in different ways.

Although Java and D never quite reached their lofty promises, there are always new languages to investigate, with both Rust and Zig in particular getting a lot of attention these days. Might they be the salvation that was promised to us C-afflicted developers, and do they make you want to zigzag or ferrously oxidize?

Solving Problems

As hilarious it is to make new programming languages for the fun of it, there has to be some purpose to them if they want to be more than a gag. That’s why Whitespace and Brainf*ck are great for having some (educational) fun with, while Forth is a serious and very much commercially successful language. Meanwhile there’s still an ongoing debate about whether Python may or may not be an esoteric language, mostly on account of it granting whitespace so much relevance that would make the Whitespace developers proud.

This contrasts heavily with languages like C and consequently C++ where whitespace is not relevant and you can write everything on a single line if that’s your kink. Meanwhile in Ada, COBOL and others case sensitivity doesn’t exist, because their developers failed to see the point of adding this ‘feature’. This leads us to another distinguishing feature of languages: weakly- versus strongly-typed and super-strongly typed languages.

If one accepts that a type system is there to prevent errors, then logically the stronger the type system is, the better. This is one reason why I personally prefer TypeScript over JavaScript, why Java reflection and Objective-C messaging drove me up various walls, why my favorite scripting language is AngelScript, why I love the type system in Ada and also why I loathe whoever approved using the auto keyword in C++ outside of templates.

With those lines marked, let’s see what problems Rust and Zig will solve for me.

Getting Ziggy

The Zig language is pretty new, having only been released in early 2016. This makes it four years younger than Rust, while also claiming to be a ‘better C’. Much of this is supposed to come from ‘improved memory safety’, which is a topic that I have addressed previously, both in the context of another ‘improved C’ language called TrapC, as well as from a security red herring point of view. Here again having a very strong type system is crucial, as this allows for the compiler as well as static and dynamic analysis tools to pick up any issues.

There is also the wrinkle that C++ is already an improved C, and the C11 standard in particular addresses a lot of undefined behavior, which makes it a pretty tall order to do better than either. Fortunately Zig claims to be a practically drop-in solution for existing C and C++ code, so it should be pretty gentle to get started with.

Unfortunately, this is the part where things rapidly fell apart for me. I had the idea to quickly put together a crude port of my ncurses-based UE1 emulator project, but the first surprise came after installing the toolchain. My default development environment on Windows is the Linux-like MSYS2 environment, with the Zig toolchain available via pacman.

A feeling of dread began to set in while glancing at the Getting Started page, but I figured that I’d throw together a quick ncurses project based on some two-year old code that someone said had worked for them:

const std = @import("std");
const c = @cImport({
    @cInclude("curses.h");
});

pub fn main() !void {
    var e = c.initscr();
    e = c.printw("Hello World !!!");
    e = c.refresh();
    e = c.getch();
    e = c.endwin();
}

Despite the symbol soup and chronic fear of fully writing out English words, it’s not too hard to understand what this code is supposed to do. The @cImport() block allows you to include C headers, which in this case allows us to import the standard ncurses header, requiring us to only link against the system ncurses library later on. What’s not inspiring much confidence is that it’s clear at this point already that Zig is a weakly-typed language, bringing back highly unwanted embedded JavaScript flashbacks.

While prodding at writing a standard Makefile to compile this code, the reality of the Zig build system began to hit. You can only use the zig command, which requires a special build file written in Zig, so you have to compile Zig to compile Zig, instead of using Make, CMake, Ninja, meson, etc. as is typical. Worse is that Zig’s API is being changed constantly, so that the sample build.zig code that I had copied no longer worked and had to be updated to get the following:

const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const exe = b.addExecutable(.{
        .name = "ncurses",
        .root_source_file = b.path("main.zig"),
        .target = target,
        .optimize = optimize,
    });

exe.linkSystemLibrary("c");
    exe.linkSystemLibrary("ncurses");
    b.installArtifact(exe);
}
With this change in place, I no longer got compile errors for the build file, but even after deleting the .zig-cache folder that the toolchain creates I kept getting the same linker errors:
Zig-Zagging from error to error.

 

While I’m sure that all of this is solvable, I was looking for a solution to my problems, not to get new problems. Instead I got a lack of strong typing, an oddly verbose syntax, ever-shifting APIs, being strong-armed into giving up the build tools of one’s choosing and finally some weird linker errors that probably require constant nuking of caches as one has to already suffer through with CMake and Gradle.

It is time to zigzag out of dodge to the next language.

Rusted Expectations

As mentioned earlier, Rust is a few years older than Zig, and in addition it has seen a lot more support from developers and companies. Its vibrant community is sure to remind you of these facts at any opportunity they get, along with how Rust cures all ills. Ignoring the obvious memory safety red herring, what problems can Rust solve for us?

Following the same pattern as with Zig, we first have to set up a development environment with the Rust toolchain and the ability to use ncurses. Unlike with Zig, we apparently cannot use C (or C++) code directly, so the recommendation is to use a wrapper. From its code we can worryingly tell that it is also a weakly-typed language by the use of type inference, and the fact that the unsafe keyword is required to cooperate with C interfaces gives even great cause for concern. Ideally you’d not do the equivalent of hammering in raw assembly when writing C either, as this bypasses so many checks.

Regardless, the task is to figure out how to use this ncurses-rs wrapper, despite it already being EOL-ed. Rather than dealing with this ‘cargo’ remote repository utility and reliving traumatic memories of remote artefact repositories with NodeJS, Java, etc., we’ll just copy the .rs files of the wrapper directly into the source folder of the project. It’s generally preferred to have dependencies in the source tree for security reasons unless you have some level of guarantee that the remote source will be available and always trustworthy.

Although you can use the rustc compiler directly, it provides an extremely limited interface compared to e.g. Clang and GCC. After trying to understand and massage dependency paths for the included files (modules) for a while, the sad result is always another fresh series of errors, like:

The frustrating end to trying out Rust.
The frustrating end to trying out Rust.

At this point any enthusiasm for doing more with Rust has already rapidly oxidized and decayed into sad shards of ferrous oxide.

Workflow Expectations

Most of my exposure to Rust and Zig prior to this experience had been from a theoretical and highly academical perspective, but actually trying to use a language is when you really begin to develop feelings that tell you whether the language is something you’re interested in. In my case these feelings were for both languages primarily frustration, mixed with an urge to get away from the whole thing as soon as possible.

This contrasts heavily with my recent experiences with COBOL, which saw me working for days on code and figuring out the language, but with a feeling of almost giddy joy at grasping yet another concept or mechanism. What helped a lot here is that the COBOL toolchains are just typical GCC compilers with the whole feature set, which means that you can use them with any build system of your choice.

Even with the Ada toolchain and its multi-step process of module dependency resolving, compiling and linking you can use these tools any way you like. It’s this kind of freedom that is at least in my view an essential part of a good development environment, as it gives the developer the choice of how to integrate these into their workflow.

The workflow with Zig and Rust reminds me mostly of the harrowing struggle with Android development and its Gradle-based environment. You get similar struggles with just getting the basic thing off the ground, are always dealing with baffling errors that may or may not be related to a component that’s a few versions too old or new, and basically it’s just a gigantic waste of time.

Even ignoring whether Zig and Rust are or can become good languages, it is this complete disregard for individual workflow preferences that’s probably the most off-putting to me, and reason to avoid these ecosystems at all cost. Something which I wish I could do with Gradle as well, but I digress.

In the end I think I’ll be sticking with C++, with a bit of C and an increasing amount of Ada and Fortran on the side. Unless you’re being paid big bucks, there is no reason to put yourself through the suffering of a workflow you loathe.

 

87 thoughts on “C++ Encounters Of The Rusty Zig Kind

  1. I absolutely refuse to learn gradle when I dabbled with android dev. It never felt like it offered any value, only an impediment in the actual development work. Learning rapidly depreciating API (and often, the only API to do something) is tiring, and not a pleasant experience. You would be lucky if you can get your 1 year old android studio project to compile without having to download 100s of MBs worth of random software which no one can even explain in simple terms does what.

    I have not tried rust or zig but hearsay about the latter is a lot better than the former. That said, both of them are still immature, and they need to either become better than C/C++ or choose a decent niche that C/C++ or other languages refuse to cater to. These two are the only ways I see them surviving. Still, best wishes to the creators and users!

      1. ” it’s virtually impossible to write safe C/C++ code”
        What utter rubbish. Bad workers blame their tools.

        C and C++ is perfectly safe if you first think about and design your system, it’s called software engineering. Just bashing away at some code because you think you know the solution is just a monkey at a keyboard trying to write code.

        I’ve written a lot of mission critical systems in C and C++. And they are still working today without a hitch. I’ve had systems in stalled and run 24/7 in manufacturing that has out lasted the plant. Spend a day of writing up your requirements, sketching out the system and your solution and doing a review of this with another developer will pay dividends.

        1. Clearly the continued presence of unsafe code aligns with “it’s all the programmers fault”, rather than “a better tool just might help those bad programmers”.

          1. the word “might” in your sentence makes it irrefutable. and that’s the word that’s missing in a lot of the hogwash.

            better tools are worth contemplating, worth trying, worth building and using and striving for. but blanket condemnations of the status quo are of little value, and they become outright slanderous when they’re paired with grandiose statements about the new experiments.

            i like garbage collection, and i don’t like tracking down buffer overflows, duplicate free()s, etc. i’m very good at C, and i make those mistakes infrequently, and i track them down quickly. but still, it’s a problem. and honestly, i like more complicated types than C provides (might as well be “objects”). i’m eager for something new but i’m not in denial about the strengths of the old or the weaknesses of the new. and when people tell me the old has no strengths and the new has no weaknesses, it’s easy to dismiss that kind of speech as what it is: hogwash.

            but i really do 100% agree with you.

        2. and yet, 90% of security vulnerabilities are due to memory corruption in C & C++ code bases :)

          Its okay for 50 year old tools to be bad–we’e gotten better at making them

        3. So what do you think about the Ford Pinto? We’ll give you this 1970 Ford Pinto, and as long as you’re a good driver, you should have no problems.

          There’s a long history of C and C++ programs with security holes due to bugs. C was created with a security hole, “gets” in the standard library, a function that cannot be used with anything but a completely trusted partner without opening a security hole, and it was used with untrusted input in finger, leading to the Morris worm.

          Good workers use good tools. Bad workers use whatever’s at hand and get themselves or others injured and produce low quality product.

      2. Just use the MISRA subset of C and all your problems will go away. Well, most of them. MISRA is, oversimplified, the part of C that’s also in Fortran. No malloc, no free, no pointers, no memory errors. It’s Intro To Programming 101, for C. It makes “original” Pascal look like a powerful, general-purpose programming language.

        And for all that, there’s still no array bounds checking. :-) Not in the spec, anyway.

      3. “the niche is that it’s virtually impossible to write safe C/C++ code.”

        What Youtuber did you get that opinion from?

        I’ve worked in both for decades and heard that line from people that were either out of their element or terrified of C/C++. Fortunately as long as you follow some super basic rules, your code will be perfectly memory safe.

      4. “It’s virtually impossible to write safe C/C++ code”

        Zillions of operative programs and several decades of C and/or C++ programming says otherwise. But suddenly, now we can’t (MUSN’T!) write not even a line of code, if it isn’t blessed by rustc.

        Not that the rust language interest me in the least, but the other day I learned that you can access array [i] in an array of size= 100, an if i=101 (can happen), the programs panics.

        1. In C, array[101] provides access to attackers to run arbitrary code. If you’re saying that array[101] can happen, then you’re saying that C can’t be used safely.

          1. What I’m saying is that a bad/inexperienced programmer can shoot himself in the foot the same, Rust or no Rust.

            Not all the bug are security bugs -the Rust “specialty”-, don’t you think? I doubt Rust can help you write bad data in al microcontroller SFR, have a bottleneck or write a stupid algorithm, put a mistaken value or limit in a “if/then”, etc, etc, etc…

            So, if you want “borrow check” anything you create in your program, be my guest. I’ve programming (C/C++) for 30 years now, and I prefer to use my energy in something more productive that being in panic of “doublefreeing” something if the compiler don’t shout that to me.

    1. Minecraft modding relies on Gradle heavily and the build times can be truly terrible. Starting a gradle daemon can literally take 1 min in a project with a few submodules.

      1. build time is an under-reported modern scourge. i’ve been working on large C projects for decades, and so i have watched build time decrease! through faster CPUs and more cores, big builds that used to be a 30 minute ordeal have become 3 minutes or less. and the usual incremental rebuild of chaged components can be just a couple seconds. the linux kernel still takes a while to build, if you don’t disable all of the unused device drivers. but even that is much faster than it was. even as the project gets bigger, my computer is so fast!

        but lately i was building a C++ project. it wasn’t even that big a project! but each and every compiler invocation processed literally tens of thousands of lines of STL in the header files. even small files take multiple wall seconds to compile. it wound up taking 30 minutes to build something that was smaller than the big project i usually compile in 3 minutes!

        nevermind that i have a bunch of android apps written in java and NDK that each take 30 seconds to compile even though they’re all of them put together less than 10,000 lines of code!

        build time matters for programmer productivity. fast turn around for testing and development is as important as things like memory safety or object orientation when it comes to getting quality results from your programmers. but it seems to have been abandoned. even as our hardware has gotten faster, so many developers today are spending more time waiting on the computer than i used to in the 1990s!

        don’t get me started on IDEs!

  2. Meanwhile people who want to get work done learn Go. Great type system, stable ecosystem, awesome toolchain with everything solved: format, build, cross-compile, … and if you want: it is quite easy to convince your system to run Go code as scripts.
    All that without the dependency hell that Python or anything JavaScript has attached.
    The whole thing just works. Which is the only “downside”, because the missing complaints keep the noise low, this is the opposite of the Arch / Rust world.

    1. +1 for Go, it’s a wonderful language

      Simple syntax that’s easy to memorize, modern & memory safe, fantastic concurrency primitives, automatic per-pronect dependency management, dead easy to cross compile, strong typing… There is so much to love!

      I was very happy with Python for general purpose work, until I sat down and learned Go over a weekend. Managing dependencies / virtual environments is a headache in python, and I don’t know how I accepted such loose typing before.
      I have since moved 100% of my new projects to Go, and have started to port my older stuff. Python still has the good ML libraries, but I’m just wrapping those in Go now. I am doing some microcontroller projects in Tinygo, although library support is not yet as good as c++/micropython/circuitpython

      C/C++ and Rust are faster than Go, but Go is not ‘slow’ (like an interpreted language), and my speed to finished product is much faster in Go than anything else.

      If you’re not familiar with it, have a go – it’s the easiest language I’ve ever learned (including python, which has a bazillion ways to do things)

      https://go.dev/tour/welcome/1

    2. The problem I have with Go is that the language lacks a strong formal specification. There is an informal specification for the language which is versioned but in reality, it’s just updated ad hoc. The result is you cannot specify code works for a specific version of the language, provide a compiler flag and expect it to work.

      This lack of a formal spec is also an impediment for compiler writers because you end up having to chase the latest version of Go since how it works is the real specification.

      1. You don’t seem to know about the go.mod file in a project.

        About the compiler writing .. what language do you have in mind that can be implemented anywhere by specification alone in a way that every code ever written will run without any modification?

      2. hahah funny that you went to R5RS next because when you said “informal specification for the language which is versioned but in reality, it’s just updated ad hoc”, R5RS is exactly what popped into my mind! R5RS is literally a ‘report’, not a ‘standard’. and i’ve met some of the guys at the bleeding edge of scheme compiler development, they’re just updating ad hoc and the report tails them.

        but in practice, i guess scheme is only up to R6RS? so in practice, it is evolving very slowly and i suspect people who program in scheme for one reason or another don’t find it is a big problem for them.

        i used rust for a few days, about 7 years ago, and i could not throw a stone without running into something that had changed. i ran into bugs in the version system, vaporware support for ARM, existing code that used features that had been abandoned, existing code that used features newer than the public binary builds of the compiler, existing code that didn’t work any longer because the then-standard behavior had been tweaked in a minor way. and worst of all i found code that had been cut and pasted 10 times for each of the 10 types because either the rust generic type system sucks, or the actual users never learned how to use it. and that code was broken by the rapidly evolving language standard, so i had to fix it 10 times!

        i take El Gru’s report as anecdata that he used Go and didn’t run into this nightmare. that’s a practical matter and no amount of formalization around the standard can guarantee that result. it’s a result of the strengths and weaknesses of the original design, and the way the community responded to that situation over time. it piques my interest.

        1. If I remember correctly you create and pass around allocators in zig instead of having global malloc/free/new, so you can have gc-style zig or you can have malloc/free-style zig, both at once, or even no heap at all enforced by never creating an allocator.

    3. I used Go for a while, they don’t have generics back then, and I waited for it, until they got generics, but what an abomination.

      To be clear, I like generics in general, but the implementation in Go is really, really horrible.

  3. Personal preferences matter a lot and many people seem to ignore that. I am a tinkerer and scripy kiddy, no professional programmer, and can hack together something in many, many languages. In many cases Python would be the best language for what I want to do but I’ve tried quite a lot of times over almost a decade but get immediate aggrevation when having to deal with it’s whitespace rules – which means python simply /is not the language for me/.

    1. “Personal preferences matter a lot” … Absolutely. Why a language should be flexible — like ‘C’. Although, I must say, some styles people use just should not be ‘not allowed’ IMHO… :D . Ha!

      The ‘go’ language was pretty much a no go for me the way the language used braces. Couldn’t get pass it.

      Python white space style fit my workflow perfectly the way it forces you to line up your code blocks for readability. A good habit (my preference .. and worked very well for my software teams back in the day) even with c/c++, Pascal, Java, and other languages…

      I try to like Rust… but it just doesn’t seem to fit. Back to C/C++/Pascal/assembly where things are ‘normal’ again. Forcing you to have to use cargo over rustc for anything more than ‘hello world’ just seems wrong.

  4. “we can worryingly tell that it is also a weakly-typed language by the use of type inference.” This is simply not true. Type inference has nothing to do with the strength of a type system. You may be mixing up type inference with dynamic typing, but they are very different. Take OCaml as an example. I doubt anyone would say OCaml is weakly typed, but it is probably the most famous example of type inference, being based on ML which is what Hindley-Milner type inference was created for.

  5. Those “definitions” of weakly/strongly typed are not helpful in many ways.

    Start by considering variables and data separately and you can see that:
    Smalltalk is strongly typed and C is untyped[1]
    to repeat that
    Smalltalk is untyped and C is strongly typed[2]

    [1] data, that is. In C you can process a lump of memory as if it is either a camel or a wardrobe; just use a cast. That’s completely impossible in Smalltalk; a wardrobe cannot be cast to a camel (unless there is a subtype relationship, of course).

    [2] variables, that is. In C you define a variable’s type, and hope the data is the same type. In Smalltalk a variable has no type; type is part of the variable.

  6. Amen, brother! Maybe I’m lazy, but I really like having a toolchain consisting of one install, and it works. It generates my makefile for me, compiles my code and runs it. Yeah, like using C++ in Visual Studio.

  7. Zig is absolutely not a “weakly-typed language”. It’s compile-time enforced. You do not have to explicitly state types, but they are still strictly enforced at the type of initial assignment. It’s hard for me to take any of this article very seriously, when it’s the equivalent of, “I spent 30 minutes trying to make something work and when it didn’t immediately I gave up”. That isn’t how programming works. You have to put some real effort into understanding at least the basic paradigms of the language. There’s plenty of legitimate criticism to be had about both of the languages in this article. Zig for sure is rapidly still changing. However, if you don’t want to put in the effort to actually learn them, then don’t, but your criticisms are pretty meaningless to everyone else if that is your standard of “trying”.

    1. “I spent 30 minutes trying to make something work and when it didn’t immediately I gave up”.

      That’s how Jerry Pournelle’s Chaos Manor column in Byte ended up. Shame; it became a waste of his reader’s time.

    2. Thank you for assuming that this was just the ol’ 30 minute college try. This was actually multiple attempts over the course of two days.

      But, feel free to show a working version of ncurses integration instead of waxing philosophically on ‘real programming’.

      1. I would argue that, especially for rust, you should not be looking to shoehorn c/c++ libraries into a project. For rust, there are better libraries built to construct tui applications (c.f. ratatui) and the programming paradigms are significantly different in order to make use of rust’s type system and other compile time guarantees

        1. Fortunately in the Rust case I didn’t even get to that point yet, as its include system is apparently too advanced for a lowly C++ developer.

          I may give it another shot in the future, but this was about whether Rust can solve existing problems for me, rather than create new ones. Using ncurses and similar standard C API libraries is in my book an absolutely valid test.

          1. One of Rust’s initial goals, way back in its infancy, was to be a good neighbor to existing C/C++ codebases. I mean, this is the “Firefox language” meant to slowly take over its vast C++ codebase.

            It’s a noisy neighbor on good days. I usually point to the Linux kernel for an example of how much glue code is necessary nowadays to interface the two. It’s never really lived up to that original goal.

    3. Exactly. And trying to build a rust program without cargo is like self induced pain for no expected benefit. His rust experience would have turned gold if he typed “cargo build” in its main source repository. Trying to use “make” (which is, more or less, made to make C and C++ programs) here is simply stupid. The tool is “cargo” not “make”. Same for zig. If you want to learn a new language, don’t expect the tool made for another language will work: They don’t and no-one cares if they do. Don’t hammer with a spoon, don’t use a screwdriver with a nail.

      1. That’s the main reason why I use makefiles (and shell scripts) too. It’s just nice to have customised control flows over the whole process, without having more layers in between that will absolutely cause grief. Plus a well-written Makefile is just poetry, unlike that auto-generated vomit that CMake creates, whether Ninja or Makefiles…

  8. This article reads as dismissive and under-researched.

    Contrary to what the author says, Rust is statically typed; not weakly typed. That’s fundamental, not a footnote. That’s one of the first things that’s mentioned in the rust book, which the author clearly did not bother reading, for some inexplicable reason.

    Also, Cargo is a first class build tool–I don’t think anyone would recommend using Rust without it. I can’t think if a single rust developer who uses raw rustc. You don’t need to use third party dependencies if you don’t want to, but Cargo is extremely lightweight and simple to use. Would be interested to hear why it doesn’t fit in your workflow.

    Rust has real flaws worth critiquing, but this piece doesn’t do that. It criticizes a surface-level impression rather than taking the time to learn a new tool in an earnest way. Learning new things takes time and just a little bit of effort. Your readers deserve better than that.

    Disappointing 😔

    1. i agree with what you said but i just wanted to share how much i hate cargo :)

      i think it’s a good example of the attitude within rust that makes it so hard for me to use. i know some people must get along fine with it. but for years i’ve heard this gospel, that cargo is powerful and robust and useful, and already mature. but it hasn’t held up in my experience. cargo is nothing but trouble for me. but, you know, i’ve bootstrapped it, and i imagine no one praising it has.

      rust evangelists are doing real harm to community relations when they find themselves unable to say “we’ve got this experimental brand new build system, and sure you’re forced to use it, but once we work the bugs out it’ll be grand.” the way you frame something matters. saying it’s already been accomplished when in fact it’s still an untested quagmire is going to really upset some people that could have enjoyed their experiment with your language.

      and fwiw i don’t know the ins and outs of it, but i looked in linux 6.14.7. and at least from my superficial glance, it seems like the Makefiles call rustc directly. i think my criticisms of cargo must be shared by some linux devs.

        1. i last used it in 2018 and its bootstrapping process was a huge hack and it had not been ported to any non-x86 linux hosts yet, so i had to go through that bootstrapping. it made me intimately aware of how every choice systematically embrittled the system. defect upon defect, masked so long as cargo is fully working and up to date. if it isn’t, nothing to do but reinstall from scratch.

          now i’m sure you want to tell me, that’s ancient history. and rust and cargo have been ported to linux-arm, and the kinks have been worked out. not only does no one have to bootstrap anymore, but the bootstrapping process is now both simplified, standardized, and maintained!

          the thing is, you’re probably right. but people told me exactly all of those things back in 2018. but they weren’t true then so i don’t listen to people telling me things like that about rust. and it beat out of me the inclination to look for myself. :)

    2. This article is pretty shockingly poor. Many outright falsehoods, and many other misunderstandings. It’s also a classic example of trying to force a language into what you want it to be, and not using it as it’s intended. Why would you copy-pasta an unsupported wrapper into your project and just ignore the entire ecosystem of crates? If they has said “I wanted to make a curses app and tried cursive or ratatui, but ran into these problems” that would have been valid. But what they actually did was pretty nuts.

  9. Rather than dealing with this ‘cargo’ remote repository utility and reliving traumatic memories of remote artefact repositories with NodeJS, Java, etc., we’ll just copy the .rs files of the wrapper directly into the source folder of the project.

    Using rustc raw instead of cargo.

    I mean you are asking for pain by doing things that way. I also find it quite lazy at best because there was no attempt to use cargo or myopic at worst to immediately reject the idea of using cargo because of “NodeJS”.

    I find it a little hard to take this seriously since there is no intention of trying to do things as intended and instead hack together something like it is C.

  10. I’m going to try and be as diplomatic as I can in making this response:

    To call Rust a weakly typed language because of type inference shows either a complete misunderstanding of what “strongly typed” means, or a complete lack of research for the article. Rust is notorious for being strongly typed, almost to a fault. Type inference is only available when the type is explicitly defined somewhere else in the code, and is also optional: you can specify to your heart’s content.

    The use of unsafe when interfacing with C is because C is the language of foot guns, and provides exactly 0 safety measures, in terms of typing, memory, compilation, or name spacing. If you are afraid of the unsafe keyword, it means you haven’t read anything about the Rust language, or how to use it.

    “It’s generally preferred to have dependencies in the source tree for security reasons…” Says who? In what context? For what kinds of projects? This is a very old-school, C way of thinking, and hasn’t been /generally/ the case for years. Sure, there are situations where it may be preferable, but in the modern software development landscape, it’s certainly not “generally” the case. Package managers offer wider access to existing solutions, and there’s a reason they are so common for modern languages.

    “…we’ll just copy the .rs files of the wrapper…” this is not how Rust packages work, suggesting you didn’t put in much effort to actually learn the language. If you’re going to have the source code locally (which cargo does) you need to at least bring in the complete project.

    This brings up the main issue I have with this article: it pretends to be “a quick glance of what these languages are like” but without putting in any amount of real effort to show what the languages are actually like.
    In the spirit of full disclosure, I work with Rust professionally (and personally), every day for the last 4 years, in a very complex project, and very much enjoy working with it. I come from an embedded C background, and learned Rust on my own, in my spare time, in about 3 weeks. I have little to no experience with Zig, but from how this article goes about Rust, I don’t feel like I can trust the section on Zig either.

    Does Rust have some pain points at first? Sure. Are there other languages that avoid those pain points? Yeah, definitely. But Rust does provide a lot of benefits that other languages can’t. Does it cure all ills? No. Is it a panacea? No. Do other languages do other things better? Of course. Different languages have different strengths, but you’ll never expand your toolset if you aren’t willing to put at least some amount of elbow grease into giving different tools a fair shake.

    C and C++ are unparalleled languages, and have been the foundation of software for decades. But that doesn’t mean they’re therefore infallible, or explicitly better. Doing things in “the C/C++ way” is not inherently a better way than others, and not being able to do things in “the C/C++” way is not inherently a bad thing. We have learned much in the last 50 years, and it would be a shame to miss out on progress because we refuse to accept improvements.

    “If we have seen further afield, it is because we have stood on the shoulders of giants”

    1. “C is the language of foot guns, and provides exactly 0 safety measures, in terms of typing, memory, compilation, or name spacing.”

      i agree with your general thrust in this comment but that statement is so factually wrong as to make it hard to take you seriously, even though you’re making good points.

      C provides very powerful tools for typing, memory, and name space. they seem primitive today, but they aren’t “0”. they’re real and i make use of them every day and they are very powerful.

      they’ve been revealed to have significant weaknesses, too. there’s reasons to step beyond it. but to say they don’t exist is just pointlessly wrong.

      and fwiw C++ is not unparalleled at all. making some tiny changes to C, “just tiny changes, it won’t hurt everything” and then finding yourself in a hole and spending decades digging yourself deeper…seems to be very popular these days. extremely paralleled.

  11. “If one accepts that a type system is there to prevent errors, then logically, one is a naive developer exposed too much to 2nd decade web dev corp propaganda”

    Typing JS is a limitation sold as feature to convince coward naive devs they must include Micro$oft in their pipeline.

    To believe “types prevents errors” is like believing you must write the name of your limbs in your limbs so you don’t get hurt, which is utterly absurd.

    Typing in JS is simple, manageable and intuitive, as long as you know what you’re doing.

    No matter what you believe, adding TS only makes everything worse, bloated, fragile, expensive and disposable.

    Using TS is like using a bicycle training wheel on a super fast car.

    1. “Typing in JS is simple, manageable and intuitive, as long as you know what you’re doing.”

      Yes, everything is ‘intuitive’ if you already ‘know what you’re doing’.

    2. “To believe “types prevents errors” is like believing you must write the name of your limbs in your limbs so you don’t get hurt, which is utterly absurd.”

      While I have no dog in the strong/weak typing fight, this is an awesome analogy. Because if you’re going to get operated on, for instance, the doctors do mark your limbs with a permanent marker during a pre-op discussion so that they absolutely don’t cut open the wrong one.

      You can argue about whether or not this level of safety is relevant for web coding, but yeah. That’s what it’s like.

  12. Strong typing doesn’t mean you have to repeat yourself constantly all over the place. The fact that zig can infer types at compile time (as can C++, by the way), doesn’t make it weakly typed. I hope some other Hackaday author can give the language a bit more justice with a coding technique that is more based on understanding and less on vibe-coding.

  13. I genuinely do not get how you can call Rust and Zig “weakly-typed” without either severely misunderstanding both of those languages or without severely misunderstanding what that term means.

    That is an absolutely baffling claim to make about both of those, frankly.

  14. Rust was a dead language, the creator abandoned it. It was revived by all the big corps (look at how it is funded) that are trying to take control of the open source world. And the best way to do that is to alienate all the grey beards that built these systems. Rust’s only purpose is to dissuade independent developers getting involved. When only employees at Google and MS write the Linux kernel and it’s supporting infrastructure then they win, they dictate its future and direction. Look at all the attempts to remove 32bit support. Then look at what Google has done to the Android project, putting development behind closed doors only to release the final source when done. This the future of Linux, MS putting development behind closed doors for ‘security’ reasons. Rust is a virus, we must kill it now before big tech owns it all.

    1. Brilliant summary of the end game here.

      Similarly, the outraged reaction to the release of a new Xorg fork that fixes bugs and adds new features tells you a lot too.

  15. I never understood why whitespace in python is a problem for some people, even more so for an individual who shows interests in strong typing, albeit with some uncommon opinion with it.

    Maybe for some strong/weak is a spectrum, for me, if typing errors rise at compile time instead of run time, it’s strong enough.

    Cargo’s problem is like npm, a dependency managing system that’s so easy to use exposes you to a lot of low quality libraries. In the good old days, dependency managing is such a big headache you’d only use something you really need. But a system being easy to use is not the real problem itself, the problem is how not to abuse it, constrain yourself in the new wild west.

    Rust’s main selling point for me is how it manages memory, the borrow checker is basically type checking but for memory safety, at compile time, once I got the hang of it, it’s way easier than hand managing memory in C.

    All my hobby projects are now in Rust or TypeScript.

    My main grit on rust is some enthusiasts’ enthusiasm, like attacking C for being not memory safe, but please don’t hate the language because of those people.

  16. I’m a rust novice, but have to agree with the other critics here. You might try a few rust tutorials before attempting to shoehorn C curses into it and then throwing up your hands. The rust package system is by far the best I’ve experienced, and dollars to donuts, you can find a cargo package to replace curses.

  17. i am really down on rust because i’ve used it. more than my criticisms of the language, i have learned that when a rust evangelist is talking, they aren’t describing the experience i’ll have. and i’m skeptical of things like Zig and TrapC because i think they probably leapt before they looked, but i’m truly ignorant about them.

    i recently ran into something i found a lot easier to digest. it’s called “fil-c”. it’s regular C, but the compiler and runtime lib enforce memory safety, more thoroughly even than rust does. the catch is, you have to rebuild the whole world with the custom fil-c compiler, meaning all of your library dependencies too. and on top of that, of course, it’s up to 3x slower, depending on the idioms in your original source. it has some neat features, too, like garbage collection…you can call free() if you want, but it doesn’t actually reuse the memory until it can prove that the references are gone.

    and you can still write bad code of course, it’s just guaranteed to crash in a specific way.

    it made me comfortable because it’s “just” a memory-safety hack to a regular C compiler. i’ve seen versions of this forever. before valgrind, i used to link with a shared lib that replaced malloc/free for debugging. and i can’t put my finger on it but i know i’ve used a C compiler that had a like -fstrict-arrays that would add bounds checking code to every array dereference. fil-c is unique mostly in its completeness, performance, and newness. but the idea is old and proven to be useful at least for debugging.

    but then once you put it that way…i very much would enjoy fil-c as like a mode to use when debugging. but would you want everything on your production computer to be 3x slower? same code, and you chose whether it runs fast vs slow. safe enough vs safe. seems like a harder sell when put that way. but otoh, computers are so fast now…i could afford it.

    fwiw i just stumbled onto “fail-safe c” which i think is very similar to fil-c. it’s an idea that’s been done.

  18. AI Overview.

    Yes, both Zig and Rust can be used for bare-metal development,
    which means running code directly on hardware
    without an operating system.

    Rust and bare-metal:

    Rust can create freestanding binaries that don’t link the standard
    library and thus don’t rely on an operating system.

    Rust can create freestanding binaries that don’t link the standard
    library and thus don’t rely on an operating system.

    Zig and bare-metal:

    Zig is designed for low-level, efficiency-centered development and
    is well-suited for embedded software due to its compile-time
    execution and lack of standard library dependence.

    In essence, both languages allow for low-level control and
    can run without an operating system, making them suitable
    for bare-metal development, especially in areas like embedded
    systems and OS development.

  19. is there a gcc c to rust converter?

    AI Overview.

    Yes, there are tools designed to translate C code into Rust,
    and C2Rust is a prominent example of such a tool.

    C2Rust functions as a transpiler, taking C code (specifically targeting C99)
    and generating semantically equivalent Rust code. It’s built to
    produce output that is as close as possible in behavior to the original
    C code.

    Here’s how C2Rust works and what it aims to achieve:

    In summary, while tools like C2Rust can significantly automate the
    initial conversion from C to Rust, producing unsafe but functionally
    equivalent code, achieving fully safe and idiomatic Rust typically
    requires subsequent manual refactoring and cleanup.

    AI Overview.

    Yes, Rust programs can run on x86 Ubuntu systems.

    Here’s why and how:

    To get started with Rust on Ubuntu:

    1 Install Rust using rustup: curl –proto ‘=https’ –tlsv1.

    2 -sSf https://sh.rustup.rs | sh. Set up your development environment (e.g., using VSCode and the rust-analyzer extension).

    3 Write your Rust code and compile it using rustc or cargo build.

    4 Run the generated executable.

    does rust have a x86 inline assembler?

    AI Overview.

    Yes, Rust has stable support for x86 and x86-64 inline assembly
    using the asm! and global_asm! macros. This allows you to embed
    handwritten assembly code within your Rust programs.

    The asm! macro is used for inserting assembly code within a function’s
    scope, while global_asm! inserts assembly code in a global scope.
    The syntax for inline assembly is target-specific and opaque to
    the compiler, but the macros provide a way to interface with
    different architectures like x86, x86-64, ARM, AArch64, RISC-V,
    and LoongArch.

    Here’s a breakdown:

  20. does zig have a x86 inline assembler?

    AI Overview.

    Yes, Zig supports inline assembly for x86 architectures.
    However, it’s important to note a few things: Syntax:
    While inline assembly in Zig works on x86, the exact syntax
    can be tricky to nail down. Documentation on this area is
    not as comprehensive as other aspects of the language.
    It’s suggested that the current inline assembly syntax
    may be influenced by or refer to LLVM and GCC
    documentation, but it’s not a direct equivalent to either.

    Backend Details: Currently, Zig sends inline assembly directly
    to LLVM when using the LLVM backend. However, there’s also
    a custom parser in the x86_64 backend. There’s a recognition
    that having consistent syntax across different backends is
    important, and a custom assembler that parses into an
    intermediate representation (MIR) is considered a potential
    future direction.

    Features and Behavior: Zig inline assembly allows for
    specifying inputs, outputs, and “clobbers” – registers whose
    values may be modified by the assembly code.

    In short, while Zig definitely has inline assembly capabilities for x86,
    be prepared to consult existing code examples and potentially
    external documentation for the most accurate and up-to-date
    syntax and usage information.

    is there a gcc c to zip converter?

    AI Overview.

    No, GCC itself is the GNU Compiler Collection and is used to
    compile C code into executable files. It doesn’t have a built-in
    feature to directly convert C code into a zip file.

    However, you can achieve this by using separate tools and libraries:

    does zig work under ubuntu?.

    AI Overview.

    Yes, Zig works well on Ubuntu. Here’s how you can get Zig
    installed and working on your Ubuntu system:

    Using Snap
    Manual Installation

    Once installed, you can verify it by running zig version in
    your terminal.

    does zig generate itself from source?

    AI Overview.

    Yes, the Zig compiler is self-hosting. This means that the Zig
    compiler is written in Zig and is capable of compiling its
    own source code.

    Specifically:

    Since version 0.10, the Zig compiler is written
    in the Zig programming language.

    The transition to a self-hosted compiler was a significant milestone,
    as it allows the Zig development process to be more efficient and
    less dependent on C++.

    The self-hosted compiler utilizes LLVM as a backend for optimization
    by default, but it also has its own self-hosted backend that can be
    enabled using the -fno-llvm flag.

    The self-hosting capability has several benefits, including improved
    memory usage during compilation, faster compile speeds, and a
    more accessible codebase for potential contributors.

    does Rust generate itself from source?

    AI Overview.

    Yes, the Rust compiler (rustc) is written in Rust and is self-hosted.
    This means that the compiler is able to compile its own source
    code.

    Here’s a breakdown of the process:

    Self-hosting: Rust’s compiler was initially written in OCaml. It w
    as then rewritten in Rust, a process called “self-hosting”.

    Bootstrapping: The
    initial Rust compiler (written in OCaml) was used to compile
    the first version of the Rust compiler written in Rust. This process
    is known as bootstrapping.

    Verification: To ensure correctness, the self-compiled Rust compiler is
    verified by comparing its output with the output of the previous compiler
    (the one written in OCaml).

    Modern Usage: Today, the Rust compiler is written entirely in Rust and
    uses LLVM for code generation.

    LLVM: While the front-end of the compiler is written in Rust, it relies on
    LLVM (Low Level Virtual Machine) for code generation and optimization.

    Therefore, the Rust compiler can indeed be built from its own source
    code, making it a self-hosted language.

    FIG Forth x86 generated with the Nautilus 2 metacompiler
    is self-hosting … too.

  21. This Seattle tech giant is gobbling up computer science grads from the University of Washington

    The graduation ceremony last month in Seattle for the University of Washington Paul G. Allen School of Computer Science & Engineering. (UW Photo / Matt Hagen)
    Amazon doesn’t have to go far to find fresh tech talent.

    The Seattle tech giant is hiring more than 100 engineers from the latest graduating class at the University of Washington Paul G. Allen School of Computer Science & Engineering — an all-time high, according to university data shared with GeekWire.

    The record-setting move underscores Amazon’s close ties to the UW’s top-ranked computer science program, even as the broader tech job market shifts amid the rise of generative AI.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.