4 ms·
> Within my first 5 minutes of porting a magnetic encoder driver, the type system caught an error in my ported code. I used the wrong pin for my SPI MOSI connec
by lelanthran 2y ago
> Within my first 5 minutes of porting a magnetic encoder driver, the type system caught an error in my ported code. I used the wrong pin for my SPI MOSI connection to my driver. It absolutely blows me away that the type system knew I was using the wrong pin. Turns out the code I could never get to work in C was broken because I was referencing the wrong pin, and I never knew why.
The type system in C allows you declare the pins as enums with literal bitmaps and declare functions that take only those enums to perform logical bitwise operations.
Trouble is, the libraries that (probably) came with your system (ESP32, or whatever) have these things defined as macros.
Still, you can have this type of type-safety at this level, and get compile-time errors when doing the wrong thing.
> Fifteen minutes later, it caught another error: by sharing the SPI bus, it could identify that there were more than two devices connected, because there were two CS pins declared, and because the device wasn't exclusive, I had to wrap the bus in a refcell for memory safety.
This is also something that can be done within the C typing system so that you get compile-time errors.
> I never thought that embedded programming could be fun, and strong types were what changed my mind.
Good for you. You should note, however, that none of these two scenarios you listed are specific to Rust - you could have solved both those issues by leaning on the typing guarantees already in C.
A big problem is that using the escape hatches in C to break the typing guarantees are not really frowned upon, so much of the code you see does extra work to break the typing.
And then newbies come along, look at the code that does extra work to break the type system, and conclude that the type system can't prevent some class of problems.
The reality is that, until and unless you put in the extra effort to break the typing (such as throwing around casted void pointers), you will get quite a lot of compiler errors when you mismatch types in C.
- darksaints 2y agoHow do you write a function in C that restricts its parameters at a type level to a subset of an enum's set of values? I'm aware of how to do that at runtime, but I don't think I've ever seen it done at a type level. Same goes for detecting two different usages of a resource at a type level...got an example? I'm not saying you're wrong, just that my beginner level understanding of C has never seen anything remotely close to that, and from my attempt at googling, its apparent I don't even have the right vocabulary to find it. Admittedly, a lot of this complaint with C/C++ might not be technical but cultural. The pervasive use of macros and templates might have an origins in avoiding some technical painpoint of the languages or compilers, but they have a real effect in how they are used. For example, I didn't know that C had consts until I started reading K&R...real world usages in open source code almost always use define. And the same goes for rust...for example, the extremely restrictive type system of Rust means that a lot of effort has gone into making type errors extremely helpful, so that you don't end up wrapping your whole program in an unsafe block. In C, you are told that you have a type error, but in Rust, you are told why, and given extra context, and in common cases you are pointed towards what you probably wanted.