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); }
.zig-cache
folder that the toolchain creates I kept getting the same linker errors:
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:

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.
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!
the niche is that it’s virtually impossible to write safe C/C++ code.
correctness is the niche rust fits and that c/c++ will never be able to match.
” 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.
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”.
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.
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
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.
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.
“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.
“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.
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.
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.
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.
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!
Hey! If you experience large build times with C/C++, I would suggest you to take a look at Conan package distribution system…
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 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
” I don’t know how I accepted such loose typing before.”
Because you never learned Perl.
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.
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?
Ever seen well-specified languages, like R5RS?
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.
Go is managed. You cannot use it for anything real-time. So it should have never been even mentioned in the context where C++/Zig/Rust is discussed, their problem domains do not even overlap.
Zig is GCed, So it should have never been even mentioned in the context where C/Rust is discussed.
Zig is not garbage collected. It’s fully manual memory management. You have to allocate and free memory just like you would have to in C.
Thanks for the correction, I wonder where did I get that wrong impression.
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.
There’s no GC in Zig unless you manually link against something like libgc and write an allocator yourself.
It is not. Why would you say something outrageous on a topic you know nothing about?
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.
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/.
“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.
Aaaaand … an article about Gradle would be nice also.
“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.
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.
In Smalltalk a variable has no type; type is part of the data.
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.
If it can “generate” a makefile, then it don’t need a makefile.
Since when Zig is weakly typed?
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”.
Move Zig, for great justice!
Wonder when ‘zag’ after ‘zig’ will come along… or ‘stainless’ after ‘rust’… The new fad languages of the next generation. Ha!
“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.
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’.
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
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.
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.
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.
I really wish most build systems could do everyone a favor and stop existing. CMake isn’t great but it’s simple enough that a lot of people use it.
Just use simple make … instead of have cmake generate make … Makes sense to me rather than add another ‘layer’. :)
CMake is birthing ninja files, no one use makefile any more (or you’re struck 10 years old in the past).
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…
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 😔
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.
Hm. Could you be more specific? What about it do you not like? Because I do think it’s robust, useful, and fairly mature–it’s not that new.
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. :)
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.
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.
Cargo is a wrapper around rustc, so this is a perfectly valid approach. I don’t use the Python-based wrapper around the ESP-IDF tools either but use them directly from CMake.
Just to note: 97.3% of embedded rust users use cargo, according to the most recent survey, so not using Cargo is definitely valid, but very unusual for most embedded Rust users.
https://github.com/rust-embedded/wg/discussions/796#discussioncomment-10742588
Yeah, I mean, it’s ok to try unusual things, but I’d delay that until I got a hang to the language under usual terms.
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”
Exactly. What next, they’ll call Haskell or Agda “weakly typed”?
Good comment – even reading the readme for ncurses-rs which explains why it’s not maintained and how to make an TUI in safe Rust, would be a good start.
And in computer science, it is more traditional to stand on each other’s feet.
“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.
“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.
“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’.
“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.
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.
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.
Exactly. People who don’t know what lambda cube is should really always stay away from discussing typing. Just to avoid embarrassment.
tl;dr “Let’s use these new languages I’m not familiar with” 2s later “Oh my god they’re totally not what I’m used to I give up!”
C>zig>rust
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.
100% this.
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.
It introduced more bugs than it fixed, left out of removed licensing, and added diatribes against the people hosting the project iirc
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.
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.
Please update your zig section by correcting all instances of “weakly” with “strongly”, since zig is a strongly typed language (https://en.m.wikipedia.org/wiki/Zig_(programming_language))
It simply has inferred types or type annotations like so ‘var x: u32 = 12;’
This is really beginner zig stuff so please don’t misrepresent the language this egregiously.
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.
Regarding tools, I prefer using a knife without rust.
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.
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:
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.
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.
…