10 ms·
How types make hard problems easy
- tinthedev 2y agoNot to devalue the author, or their findings/learnings... but I could see this was a JavaScript/Typescript coder (very likely self-taught) learning about typing paradigms. A lot of people, especially people from the same background, would benefit from branching out and learning some other programming languages/paradigms. Some... statically typed and actually compiled languages. Maybe to take an entry course in CS. It's very popular to hate on formal education, especially in software, but all these lessons would have been learned in the first semester or two.
- tugu77 2y ago100% this. For a C++ or Rust programmer this reads so weird. Don't get me wrong, I'm not hating on JS here, and I have lots of beef with C++, but I fully agree with your take that TS barely scratches the surface of the statically typed world.
- throwuxiytayq 2y agoBased on my small amount of work done in TS, it seemed like one of the more advanced type systems out there. To the detriment, even. The language was just huge, and that was years ago.
- eyelidlessness 2y agoAnd it’s so advanced because it was/is designed to represent the types of real world dynamic JavaScript. More often than not, when people complain about the complexity of the types they encounter in the TS type system, they’re really complaining about the types of the underlying JS (which are the same whether they’re expressed statically or not).
- wk_end 2y agoThere's a cultural problem in the TypeScript ecosystem, I find, where people are impressed (with both themselves and others) when complex interfaces can be expressed in the type system, and tend to embrace that instead of settling for simpler (and often admittedly more verbose) ones. Maybe that's because they're an ex-JS programmer who wants to use the exact same interface they'd use in JS with no compromise, or maybe it's just because they think it's cool. Either way I think it's really detrimental to TypeScript as a whole.
- TheHegemon 2y agoDo you have some examples for that? Most cases I've seen with more complex interfaces is due to the fact that it is what the interface truly expects. Usually making it simpler tends to mean it's actually wrong or incomplete.
- wk_end 2y agoThis is hand-wavey, but that can't be true: less complex type systems manage to express all kinds of interfaces correctly all the time (sometimes at the cost of verbosity, but that that’s usually a good trade-off is the point). You're asking me to tell on my coworkers, and I'm too loyal to throw them under the bus :) Well, OK, here's one, but I'll keep it as blameless as possible. We had a thing where we wanted to register some event handlers. The primary use of these event handlers was to run a selector, and if the selected data changed, trigger an update, passing the selected data along. The initial implementation used existential types to store a list of callbacks, each returning different selected data. The "driver" then did the equality checking and update triggering. We later changed this, so that the callbacks - as far as the driver was concerned - all returned `void`, eliminating the need for an existential type. We just had to move the equality checking and update triggering to inside the callbacks. Some features are straightforward translations: anywhere you have overloading and/or optional arguments you can (and often should) simplify by refactoring into multiple functions. For a concrete, public example...well, I remember the Uppy library had a lot of stuff like this. A lot of work goes into making it's "Plugin" interface look the way it does (start at [1] and keep reading I guess) for instance, and while I haven't sat down and re-engineered it I don't think it needs to be this way, if you're willing to give up some of the slickness of the interface. [1] https://github.com/transloadit/uppy/blob/main/packages/%40uppy/core/src/Uppy.ts#L58 https://github.com/transloadit/uppy/blob/main/packages/%40up...
- FractalHQ 2y agoThis isn’t true, is it? I’ve only ever heard that TypeScript has one of the most advanced type systems of any mainstream language.. but I don’t have enough experience with other languages to know how true that is.
- shepherdjerred 2y agoTypescript has one of the most advanced type systems of any of the common languages
- deleted 2y ago[deleted]
- chamomeal 2y agoNawww I’d say something like python or php is “scratching the surface”. Typescript’s type system is phenomenal and pretty deep. Honestly I think it’s the most interesting one to work with, too. Which is not always a good thing, but it is fun. The only type systems I’ve seen that are similarly expressive are rust and Haskell. Even go doesn’t come anywhere close.
- throwuxiytayq 2y agoIn my experience, university is one of the least efficient ways to learn CS. The actually useful classes are few and far between, dwarfed by useless outdated courses, courses that aren’t very relevant to the job, and classes that are sadly lead by incompetent burnouts who don’t know that they’re teaching, come terribly unprepared, and in general seem to hate their job. Most of the people there have theoretical experience in writing software. But maybe that’s just my shitty university. I dunno. Supposedly one of the better ones.
- CaptainNegative 2y agoI think the problem is in going for a Computer Science degree when you really meant to study Software Engineering.
- n4r9 2y agoI imagine quite a bit of a Computer Science degree is relevant if you plan to be a computer scientist.
- karaterobot 2y agoOn the other hand, as an Engish Lit major who taught himself programming from zero, and worked as a programmer for over a decade, all my experience writing software was practical, and I don't think that's the right way to go either. I wish I'd had any level of theoretical education that might have exposed me to fundamental concepts you (with yer fancy book-learnin') probably take for granted. If someone just learns on the job, or just learns as they go, they don't learn stuff until they need to. They learn it in a hurry, and on a deadline. That's not the best way to get a firm handle on tricky subjects, and maybe as a consequence, I always felt a couple steps behind my peers.
- digging 2y agoAs someone in a similar position, may I take a tangent? I'm curious what you transitioned into out of programming. The stress of feeling "always behind" is taking its toll on me, and I wonder about another career change often.
- deleted 2y ago[deleted]
- tlf 2y agoThat's interesting to hear. I started out with a formal CS education learning Java & C in school. I've found that traditional CS education doesn't really take this approach. A lot of what I was exposed to was very OOP-heavy practices that emphasized data modeling via class hierarchy. To me, the expressiveness of the Typescript system (being able to do things like sum types or branded types) is what unlocked a lot of potential despite not being a compiled language.
- tpoacher 2y agoYour experience of Java likely relates to Java 8, or possibly even prior versions. Modern Java is an entirely different beast, which feels very functional these days. (and yes, I say this as someone who teaches these things as part of an undergrad java course)
- TexanFeller 2y agoAfter using languages like Scala, Java(I use 17) feels like a joke in terms of type system expressiveness and ability to use functional patterns. I currently have to switch between the two and the kindest thing I can say about Java is it’s getting better(very slowly). Even though the language is getting less painful, frameworks like Spring that do things at runtime instead of compile time, including rewriting bytecode on startup to inject code, make the ecosystem quite hostile to folks who want to work in a stricter, safer manner that’s easier to reason about(expressed in the language, not in some annotation based metalanguage with no principles and whose implementation changes randomly). We need to stop defending Java and move on to something actually modern and good. Scala has fallen from favor, so maybe Rust is the next thing I’ll try.
- Groxx 2y agoA lot of the runtime fiddling is indeed a plague (the limited reflection is one of my favorite parts of Go, it means I can trust function call boundaries FAR more), but Java does do some nice things. E.g. I wish every language had as powerful of a compile time system as Java does - annotation processors and compile-time byte-code weaving enable magic "best of all worlds" stuff like Lombok, and it integrates with IDEs transparently. And hprof -> MAT is absolutely incredible compared to the memory-profiling capabilities of most languages.
- motorest 2y ago> A lot of people, especially people from the same background, would benefit from branching out and learning some other programming languages/paradigms. I completely agree. I started reading the article expecting to read something interesting or smart about functional programming,but it turns out the blogger is just very vocal at telling the world their excitement over reinventing the wheel and being completely obliovius to what actually represents very basic things in any intro to software engineering course.
- shepherdjerred 2y agoWhat? I have never heard of a school teaching the importance of static typing esp when it comes to engineering practices
- jfwuasdfs 2y agoVery true. You need to go to a school that specializes in type theory [1]. [1]: https://cstheory.stackexchange.com/questions/50780/which-universities-in-the-u-s-are-doing-research-in-type-theory https://cstheory.stackexchange.com/questions/50780/which-uni...
- motorest 2y ago> What? I have never heard of a school teaching the importance of static typing esp when it comes to engineering practices The blogger is not a really talking about static typing. The blogger is waxing lyrical over designing a domain model and then writing an application around it. You know, what others call basic software architecture. Wait until the blogger learns of the existence of Domain-Driven design.
- TheTaytay 2y agoI didn't get the impression that this was a self-taught or newbie coder. I think their audience is not assumed to be a CS grad though. I found it a good and well-reasoned explanation of _why_ he enjoys types in a large codebase. He does take time to explain different type concepts, but I assumed that was because he doesn't assume his audience is familiar with all of them. Considering that the opinion "types are good and helpful in a codebase" is not universally held, even by very experienced/productive coders (see https://world.hey.com/dhh/turbo-8-is-dropping-typescript-70165c01 https://world.hey.com/dhh/turbo-8-is-dropping-typescript-701... or basically any ruby codebase), I think articles like this have a definite place.
- ninetyninenine 2y agoThe irony is that before types became popular with interpreted languages and modern languages like golang or rust, untyped languages became MORE popular because of formal education. The reason why is because most formal education curriculums teach C++ which ironically is more error prone and contains error conditions far harder to debug then untyped interpreted languages like python or JavaScript or ruby which were coming into popularity at the time. This is of course despite the fact that C++ has a type system with generics. Because of this, a lot of people tended to associate typing with something more error prone and harder to work with. It wasn’t until the advent of typescript, golang and rust when people started to get the difference.
- neverartful 2y agoSemi-pedantic point -- Python is not untyped. In fact, it's strongly typed. It's not statically typed, but rather dynamically typed.
- ninetyninenine 2y agoIs it? Then why can’t parameters be checked by default when called in a function? Anything passes through with zero runtime checks. Any type checks you need to implement it yourself.
- neverartful 2y agoBecause Python isn't a statically typed language. Many will argue that this is a huge benefit of Python since you don't have to declare types. There are newer developments like mypy that allows you to add types as annotations, but the data types that you declare with the annotation is not enforced.
- ninetyninenine 2y agoRight and I asked you a question and it wasn’t answered. If it’s dynamically typed how come I don’t get type checking at runtime for functions I defined?
- t-writescode 2y agoIt's always fun getting to see people experience the positives of type systems. So many of the most popular and "easy" / "user-friendly" languages drop types in favor of friendliness and speed. The most vocally popular web languages - Python, Ruby and Javascript - all seem to either ignore or not have types at all. People make huge projects in them and start learning new techniques and then the weight of the choices they made begin to grow. Enter: Types, a frequent savior. Not always the best choice for everyone, but a very good and useful thing. I welcome this person on their journey!
- stavros 2y ago> The most vocally popular web languages - Python, Ruby and Javascript - all seem to either ignore or not have types at all. All three of those languages have ways to use typing, so this statement is only true in the sense of types not being mandatory, which is also the case in any language that has the Any type.
- pavel_lishin 2y agoBut Python, Ruby and Javascript effectively encourage you to skip using types out of the box. (Elixir, too - it supports @spec, but doesn't require it.) If you want to skip out on types in Typescript, you have to be explicit about it.
- deleted 2y ago[deleted]
- Barrin92 2y ago>Using the same language everywhere. Naturally, if we want to share type information as much as possible, we need to be using the same language This goes to the heart of what's not great about this, types impose global semantics on a piece of software, they introduce coupling. (It's why Alan Kay used to stress "late binding of all things") as a feature of managing complexity. In fact one result of this kind of programming were microservices. What do they do? Reintroduce runtime dynamism. It's not often framed that way but there's a reason you see more statically typed microservices than Lisp or Erlang ones. It's because they're an attempt to get away from the coupling imposed by type driven programming and towards more independence of each service. Which is already baked into message based, dynamic languages. And there's also a fundamental misunderstanding about data and types in the article. > Making our types represent the “truth” Types can't represent truth. Real world data doesn't have types. It changes incrementally however it wants, and all the time. You can use types to not let something you don't want into your program, but you can never represent arbitrary real world data by matching types onto them.
- esafak 2y ago> Types can't represent truth. Real world data doesn't have types. It changes incrementally however it wants, and all the time. What do you mean? If a variable is a date/time or an integer etc. in the real world it should stay that way and be represented as such in software.
- leeeeeepw 2y agoAI chatbot example, you're chatting and then there could be some Mark down, latex, images maybe base64 encoded webp, audio files, we can type all this stuff do all the validations and such, understand it better and there's some gains to be had doing that, then likely someone like Facebook comes along with this Giant byte Transformer expert system with all of the data specific optimisations, that's kind of the bitter lesson but I guess the main point is that the problem itself of how to best communicate with AI is not necessarily solved so you can get bogged down typing the best possible ways to do it but it's a moving target. Same with a lot of systems like say a search system that tracks data using the best embedding, well we don't know what that best embedding is in terms of price performance and encoded knowledge perf it's just a moving target. Send me the system that tracks important metrics effecting the stock market, or a weather system etc... the sensors are all updating and then an entirely new thing comes along like Starlink that helps us track the weather in totally new ways
- wryoak 2y agoThe first point lost me because it pushed responsibility for functioning software onto the user. If your entire application ecosystem has to be recompiled because you conceived of a new clever way to conceptualize the data that doesn’t actually affect the user experience, what happens is I have to update my damn bank app every time you think you’ve done a smart, even though you’ve changed nothing in regards to my checking my balance.
- digging 2y agoI loved this paragraph: > This dichotomy gels really well with the way my brain works. I’m able to channel short bursts of creative energy into precisely mapping the domain or getting type scaffolding set up. And then I’m able to sustain long coding sessions to actually implement the feature because the scaffolding means I rarely have to think too hard. It's why I keep begging my team, every time there's a new codebase (or even a new feature), to stop throwing `any` onto everything more complicated than a primitive. It is exhausting. It forces me to waste energy on the shitty, tedious parts. It forces me to debug working code just to find out how it works before I can start my work. They tend to take the quickest solution to everything -- which means everyone else has to do the same work over and over again until someone (me, invariably) sits down and makes a permanent record of it. In doing this they ensure that I can't trust any of their code, which is counterproductive for what should be obvious reasons. Every time I work on established, untyped (or poorly typed) code, it's like I'm writing new code with hidden, legacy dependencies.
- ervine 2y agoWhy is `any` allowed at all? Enable strict mode, set up your linter, don't allow any implicit or explicit `any` anywhere. Without this, Typescript is next to useless. Not knowing if the types are good is worse than no types at all.
- phyrex 2y agoProgressive typing of an untyped code base. Types that are too complex to represent in that type system.
- t-writescode 2y ago* Common functions such as parsing functions in languages that don't support function overloading * "equals" and other global functions.
- shepherdjerred 2y ago
- alephxyz 2y ago>Changing our database schema should cause us to see errors in our frontend code. I shuddered.
- shepherdjerred 2y agoWhy is that bad?
- Kuraj 2y agoThis seems like a good thing if front-end fragmentation is not an issue, ie. if it's hosted on a server and kept in sync with the backend through deployment. As a mobile app? Maybe not. I'm honestly a bit puzzled which scenario the original article is envisioning when arguing this, because it mentions mobile, but then also argues for monorepos, which are kind of at odds with each other, unless you somehow force your mobile users to always be using the version that matches your back-end.
- shepherdjerred 2y agoOh, I see. Yeah, you'd definitely need to be very careful in this case. To be fair though, this is a general problem when clients and servers might not agree on data formats. You can still safely do what the author is describing since type checking occurs at compile-time and not runtime. You would, of course, need to be sure your app handles whatever the API/db returns at runtime though. But, again, this is a general problem.
- axelthegerman 2y agoAnd: > How types make easy problems hard Sure that's sometimes an issue with the type system itself (looking at you Sorbet) but also preventing the programmer from taking advantage of the flexibility, expressiveness and elegance the language itself my add (yes, Ruby). But even Typescript, which is arguably one of the better type system/language pairings out there, often causes more headache than it's worth.
- umvi 2y agoI've seen some truly insane TS types. Ones that validate SQL queries and stuff. The problem with complex TS types is that there's no debug tooling. You can't set a breakpoint, you can't step through the type propagation. If there's an issue you have to just do trial and error, which can be very tedious. Here's a super complex type I ran into in the wild that has a bug that is extremely difficult to fix unless you burn hours on trial and error: https://github.com/openapi-ts/openapi-typescript/blob/main/packages/openapi-fetch/src/index.d.ts#L193 https://github.com/openapi-ts/openapi-typescript/blob/main/p... (the bug in question, still unfixed): https://github.com/openapi-ts/openapi-typescript/issues/1769 https://github.com/openapi-ts/openapi-typescript/issues/1769 It was so hard to fix this bug that I found it easier to just rewrite the entirety of the library but using code generation instead of ultra complex TS types to accomplish the same outcome.
- incrudible 2y agoIf you see programming primarily as a creative outlet, maybe Typescript is not for you. Otherwise, I can vouch for the techniques described in the article, they really keep the code manageable and understandable. They guide you towards working on specific things rather than premature generalizations, but if the specifics change (as your understanding changes), they will also help you change the code without fear. The escape hatch (any) is always there if you need it.
- shreddit 2y agoI also recently switched from javascript to typescript and noticed a clear improvement on my speed to write code. Before i had to constantly switch between files to check what i exactly passed to a function. But I knew C# before so a typed language is nothing new for me. But when i started with javascript exactly this “untyped” language felt like something good, it felt much less of a burden to think about the code beforehand. Now i look at dozens of projects which a have to be converted to typescript because I simply cannot deal with this typelessness anymore…
- TZubiri 2y agoLooking forward to the response article on how types can make easy problems hard.
- moshegramovsky 2y agoIn C++ you can make all kinds of easy problems much harder with C-style casts or static_cast.
- neverartful 2y agoTrue, but C and C++ are not the only statically types languages available (thankfully!).
- digging 2y agoHonestly, yes, I'm curious to hear that perspective. The negative responses to "TypeScript makes JS programming fun and easy" are always pretty ill-formed, and I really want to know if there's a genuine argument against it in any complex application. (My suspicion is that no, there is not, but I'm trying to be generous and curious.)
- shepherdjerred 2y agoThe biggest con is that you have to do all of the legwork of learning how static typing works, and types in TS can be fairly complex. When you have a team of engineers, this means your entire team needs to either learn or lean on an expert when tougher situations arise.
- akdor1154 2y agoLess charitably, it means you need a competent team?
- shepherdjerred 2y agoCompetent in types, yes. Just like you’d want a team competent in functional programming before starting a project in Haskell. It would be unfair to consider your team incompetent just because they are experts with another set of tools. It’s also unreasonable to expect these things to be quickly learned (TypeScript types are not friendly). But I think it’s reasonable to explain the benefits of this approach and to help your ramp up and learn the skill. But, anyway, I understand the frustration. I’m usually the one trying to get my team to understand the value of modeling problems in type systems.
- moshegramovsky 2y agoC++ guy here. I love being able to make a change and watch the compiler tell me what's broken. In the past year, I was able to justify large scale changes to a big codebase because I could say with confidence that the type system would reveal all. And it did.
- Measter 2y agoYeah same, though with Rust. I once did a refactor of my compiler project where I completely rewrote how the AST was represented, then spent the next three or four hours fixing compiler errors. Worked perfectly first time, because the type system allowed compiler to tell me everything that was broken.
- shepherdjerred 2y agoZod [0] is my favorite TypeScript library. It really helps ensure that all the little nooks and crannies of your application can be properly typed. An example is receiving API response with `fetch`. Normally you'd cast the response to the expected type, but it's not uncommon for you to misunderstand what the API can return or for the API to be changed/updated. Zod lets you verify your types at runtime so that if your API returns something unexpected then you can act on it. This is really useful anytime you're interacting with I/O or user input. For example, I've used Zod for: loading from JSON files, reading from local storage, parsing URL params, or validating form input. [0]: https://zod.dev/ https://zod.dev/
- threatofrain 2y agoI'd also say checkout Valibot. It has a nice composable pipe¹ API so a small handful of atoms is expressive over a lot of type needs. It's also more petite and performant. const natural = pipe(string(), transform(atoi), minValue(0)) const percent = pipe(natural, maxValue(100)) [1]: https://valibot.dev/guides/pipelines/ https://valibot.dev/guides/pipelines/
- akira2501 2y ago> The default return type for posthog.getFeatureFlag is string | boolean | undefined. You could just as well say "how bad APIs make simple problems complicated and how you might strain at a type system to pretend this bad design is worth keeping." I mean, "string or boolean or undefined," is not at all a "type." This is a poorly specified contract for an overloaded interface with terrible semantics built on the abuse of language grammar. It's why I think a language with the core semantics of JavaScript plus a goofy type system are never going to produce anything worth actually having. The two sides of the system are constantly at odds with each other. People are mostly using the type system to paper over bad design semantics.
- cjr 2y agonice post :) I’m surprised there’s not been any mention of effect (http://effect.website/ http://effect.website/) yet, as it is kind of the next level up if you really want to model things like errors, dependencies and side effects in the type system, using functional concepts borrowed from more pure functional languages. It would be a bit of a risk adopting this into a shared code base depending on your team and the kinds of devs you’re looking to hire, but it could be useful to some folk that feel like they want even more type safety.
- smj-edison 2y agoI see proponents of type systems often mention that types make refactoring easier and safer, but wasn't the first refactoring browser made for and in Smalltalk? How did Smalltalk maintain the types when performing large changes?
- layer8 2y agoIt could fail. It also collected runtime information to improve correctness. See: https://www.researchgate.net/publication/220346807_A_Refactoring_Tool_for_Smalltalk https://www.researchgate.net/publication/220346807_A_Refacto... E.g.: “In a reflective environment such as Smalltalk, any change to the system can be detected by the system. Therefore, it is possible to write programs that depend on the objects being a particular size, or that call methods by getting a string from the user and calling perform: with it. Therefore, it is impossible to have totally correct, nontrivial refactorings. However, the refactorings in our system handle most Smalltalk programs, but if a system uses reflective techniques, the refactorings will be incorrect.” “To correctly rename a method, all calls to that method must be renamed. This is difficult in an environment that uses polymorphism to the extent that Smalltalk does. Smalltalk also allows dynamically created messages to be sent via the perform: message. If an application uses this approach, any automatic renaming process has the potential of failure. Under these conditions, guaranteeing the safety of a rename is impossible. “The Refactoring Browser uses method wrappers to collect runtime information. […] Whenever a call to the old method is detected, the method wrapper suspends execution of the program, goes up the call stack to the sender and changes the source code to refer to the new, renamed method. Therefore, as the program is exercised, it converges towards a correctly refactored program. […] The major drawback to this style of refactoring is that the analysis is only as good as your test suite. If there are pieces of code that are not executed, they will never be analyzed, and the refactoring will not be completed for that particular section of code.”
- smj-edison 2y agoInteresting, thanks for the link and quotes! I've been trying to find more information Smalltalk in the 90s, with XP, GoF, and other interesting developments—I wasn't alive when all that was happening and it's been fun to rediscover.
- langsoul-com 2y agoOne thing author neglected to mention is just how time comsuimg making everything types is. Sure, primative types are fine, but anything more and it's a massive pain. Actually, types are best when someone else already did all that work.
- pkoird 2y agoLooks like a job for LLMs?
- tantalor 2y agoprices: NonEmptyArray<Price> Doesn't this mean you can't ever remove an element from the array, only add to it? Like, the compiler should throw a type error if you try to pop() from an array with one element.
- bruce343434 2y agoCould also be that pop() can now error out at runtime
- tantalor 2y agoInterestingly, [].pop() does not throw an error.
- MichaelNolan 2y agoTypeScript is just for compile time. You can pop() every element out of the array at runtime with no error. This compiles with no issue - https://www.typescriptlang.org/play/?#code/C4TwDgpgBAcg9gOwKIFsygIICcsEMQA8AKgHxQC8UA2kQDRQB0TRVAuqwNwBQXAxogGdgUFCGx4QALliJU6MTnwEEAVxQAjCFjKUqARnoAmegGZOPAPQWoAJQgo4AN2jAAFtAA2uIVAgf7EAjAXKLi+AxgcGAAFACU3HyCcP4MHnAA5tGhiiDxUFZQAPIqwGAl0vpGrJbWdg7OUG6e3sJ+AUFQuOm4AJYIIQoSEVFxCfwIAskQqRlZg-h5BcWl5dR61VwFdU4u7lBePm0ogcJdvf3ZQ5Ex8TzjkylpmZcLHPnWy2XAFdVAA https://www.typescriptlang.org/play/?#code/C4TwDgpgBAcg9gOwK...
- tantalor 2y agoIf that's true, then how is a type like this (non-empty array) useful at all, if it can't be relied on at runtime? TS should say, you can't pop() this array, unless TS can infer it has >1 elements. Otherwise it can enter a state at runtime which doesn't conform to the type. That seems bad!
- motoboi 2y agoIt’s funny and sad to have people talking about types while I have Java and and IDE that basically writes code itself. JavaScript was a bad trip, guys.
- darksaints 2y agoI've long been a fan of strongly typed languages, but have settled into using dynamic types a bit mostly for ecosystem reasons. Recently I've gotten into embedded programming and initially my thought was that I would have a much easier time getting into it by learning C and C++ simply because those are pretty well standardized on embedded devices. And it has been so fucking painful. The build systems absolutely suck...cryptic, finicky, and archaic. Small variations in developer environments cause so many errors. The package management is basically non-existent. Maybe you use Boost or a couple other libraries, but mostly you avoid them because the package management is terrible and build systems are even worse. You're basically writing everything from scratch. The thing I overlooked the most though was the type systems. C and C++ are statically typed, but weakly so. And therefore, the thought of using the type system for safety guard rails doesn't exist. You specify types so that programs will compile, and that's it. In comes Rust. I know the memory management is the thing that sells it, but in an embedded project, I'm simply not doing any dynamic memory allocation, so I didn't think I'd see much benefit. I mostly tried it because Cargo is an amazing build system. But the thing that has sold me on it is the type system. 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. 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. Absolutely amazing. I never thought that embedded programming could be fun, and strong types were what changed my mind.
- sinuhe69 2y agoYeah, I see the same problem with C and C++ in embedding, too. My guess is that people in embedding were working originally in low-level language like assembly where types don’t exist (at least that's what I did with the PIC and older AVR microcontrollers). So when they introduced higher level languages such as C into it, they did it in an assembly-like fashion and not truly in the spirit of high level languages. For example macros are still extensively used for definition of a lot of things, including IO-pins, and they undergo no type checking. C is not a strong -typed language anyway and this mode of thinking and programming continues to spill-over when C++ was introduced. Type is used merely to limit memory allocation and ensure memory alignment, not truly used in its conceptual sense. Of course, the resource constraints and efficiency of the compiled code play a significant role here. So unless a new memory efficient strict-typed language/compiler comes along with a modern mindset, the power of type will not come into play.
- kazinator 2y agoIf the code writes itself due to type declarations, it must be mindless drivel, not something containing "hard problems". For instance, if we just declare some data structures for computational geometry, like points, line segments and whatnot, code for, say, intersecting two meshes is not effing going to write itself! The author is living in some CRUD world of pulling things from one API or database, converting to a different data model, and stuffing them into another API, with maybe some HTML generation sprinkled on top.
- tasn 2y agoGood utilization of the type system really makes a difference. I wrote a similar blog post a while back: https://www.svix.com/blog/strong-typing-hill-to-die-on/ https://www.svix.com/blog/strong-typing-hill-to-die-on/
- hansvm 2y agoI can't look at a conversation about types without thinking of hexing the technical interview [0]. It's not quite the sort of thing TFA is talking about, but how does everyone here feel about sneaking parsers and other code that normally exists at runtime or in the build system into the type system instead? [0] https://aphyr.com/posts/342-typing-the-technical-interview https://aphyr.com/posts/342-typing-the-technical-interview
- throwaway2037 2y ago> type NonEmptyArray<T> = [T, ...T[]]; I never used TypeScript before, but this looks very useful. Is that possible in C+++ templates or Java generics or C# generics?
- yawaramin 2y agoFun fact: TypeScript can typecheck JSON files directly. I use this ability to define all my translation keys in my code as a type and enforce that my translated messages JSON files all have the correct keys.
- revskill 2y agoStructural typing is the key here.