It is common knowledge among most - if not all - civilizations that you do, in fact, need to learn to read in order to know how to read.
Anyway, since you want a direct representation of the text - presumably, you configured your editor to render EOL sequences explicitly, to distinguish tabs from spaces, etc?
You and me both. Ligatures are a solution to a problem that monospaced fonts don't have. I don't mind if a mono font uses ligatures to harmonize character spacing/alignment a little bit. But I don't want things like a "proper" greater/less-equal sign; if a font goes so far as to replace >= with ≥, then it's lying to me about what characters are actually present in the file.
I wouldn’t say so… I consistently choose Rust mainly because it’s a sanely designed modern C++ alternative. It’s 20% more effort than writing Python or Typescript, and you get to use the full power of your hardware without compromise.
Safety is a nice side-benefit. The main reason why I like the safety is because it allows you to fearlessly write high-level code without being constantly paranoid about memory as in C++. It’s more about enabling ergonomics without loosing performance, rather than security or correctness.
> It’s 20% more effort than writing Python or Typescript
I'd disagree with this point, there is more typing involved with a first draft of code than Python or Typescript, that's certainly true, but if we bring all the tools (e.g. docblock comments for "type declaration") that are habitual to make up for the shortcomings in most developer's minds then that gap shrinks and, imo, ends up swapping. It's cheaper to have automatically enforced and consistently maintained checks than moving that information out of band and the resulting code in a strictly typed and memory enforced language ends up removing a significant cognitive overhead when reading and maintaining the code.
I have a strong aversion to boilerplate code so it's important to try and allow terse expressions when possible - but unstated assumptions are worse than overstated assumptions.
Most things like "sanely" and "20%" are pretty subjective. To me writing (or really reading well written) Nim (https://nim-lang.org) is less effort than writing Python or Typescript. Nim is mostly Ada & Lisp ideas packaged in a more terse & flexible surface syntax. Nim also has nice compile-time introspection and very low effort macros to allow packaging near zero-code APIs like github.com/c-blake/cligen. Also, something like 5 out of 5 times I've investigated some Rust alternative to some Nim code, the Rust ran more slowly than my Nim on my tested CPUs.
With access to inline asm, all speed is ultimately more a measure of effort applied than PLang. So those perf ideas are just "with my level of effort". Even Python via Cython has pretty direct access to asm. The "do it in pure X" that Sun popularized (even in a meta-/cross-PLang-sense) as a business attempt to define Java virtual machines as The platform has had many casualties, not the least of which is the quality of discussion of PLang practicalities, not just on HN, but everywhere.
I have heard great things about Nim, you may be very right. It’s just that it’s impossible to ignore the benefits of a mainstream dependency ecosystem. The ecosystem is exactly what made Python and Javascript the giants they are today, despite being somewhat mediocre languages. And the Rust ecosystem is in that same league, without giving up exceptional performance, and without giving up too much ergonomics.
PS: I was very enthusiastic about Cython for a good while and I went deep into it, but I found that it is rather a mess to use in practice. Yes you get C performance within Python, kinda, but you also get all the C footguns, amplified by the complex interactions with Python features.
Yeah. Other ecosystems are undeniably larger than Nim's. I keep hearing about how LLMs are going to nullify that advantage with "not so sloppy" ports of anything to any PLang, but I've yet to see that pattern materialize. "What is a clean interface" is probably a kind of subjective judgement call, but also very clearly depends on PLangs and even PLang cultures. For example, the microdependency culture of Rust/JS/Node have very little to do with the PLang's themselves.
EDIT: With Cython how I mostly kept things organized was the "caller allocation" so common in C where memory was always managed the usual mostly refcounting way of CPython/NumPy, but I had dozens (maybe even 100) little "kernels" I could pass that memory into that could even use Intel/MSFT "intrinsic" asm calls (things like immintrin.h) or even just #include C code which did similar. It didn't seem too bad to me, but Nim always seemed a more complete solution (at the PLang level - not counting ecosys). (And these days there is even NimPy (https://github.com/yglukhov/nimpy) to write low-level speed-up code for Python in Nim.)
This is misinformation. There is (at least!): `method`, procedurally typed fields (inside case-object variants or not), run-time keyed `Table` with proc values, {.dynlib.}, importc/importcpp things. Beyond that, yes, Nim has rare compile-time superpowers that do lead many of its proponents to use static constructs (totally grant that!). So, you may not see a lot of dynamic dispatch in code bases, but there is little stopping you from using them in your own code.
Ah, yes, I should have been more precise. It doesn't have an equivalent of an interface/trait/protocol with dynamic dispatch.
Yes, you can pass around an object of procedures, but that is awkward, doesn't have any support from the language or stdlib, and from what I can tell isn't a normal thing that is done.
I think you & I are really back & forth-ing "the PLang not enforcing/strongly encouraging a very specific way of doing things that a whole ecosystem/community organizes around". Relying instead on self-organization has many pros & cons, to be sure. Lisp suffered much the same "until" Common Lisp (which still leaves many things open). My tag line lately is: delegation affords so much, but trust sure is tricky. Much of the time people seem to discount the often rather large cost of establishing/maintaining trust. (I'm not saying you are - just that it's an easy thing to do. I think it's why there is this is a big megathread on "trusting rust", even though "rust" is a veritable suffix of "trust". Lol.)
The paranoia about memory use in C++ should mostly be a thing of the past if you’re using smart pointers and sane patterns. In 2026 almost nobody should be calling new and delete and passing around raw pointers.
The reality though it many people are not using smart pointers. I have seen many people argue they don't like them because they want to see every place delete is called. (meanwhile of course they never notice all the places it should be called but isn't - but at least where it is they see it)
It's more than that. Smart pointer help, but there are cases where even when using smart pointers you can encounter memory safety issues. Especially when you need to interact with c or older c++ code that doesn't use smart pointers. And smart pointers don't provide any protection against data races in multi-threaded code, like rust does.
And yet applications written in modern C++ are constantly discovering new memory safety issues. Sean Baxter wrote a whole manifesto talking about the shortcomings of the existing C++ model [0].
The problem with manefestos is they often harp on small parts that don't matter much in the big picture. There are real shortcoming of the C++ model, but if you use modern C++ they are rare.
The real shortcoming it is very common for people to not write modern C++. I know several C++ developers who refuse to use smart pointers because they don't like magic happening.
It's not enough for memory safety issues to be "rare". To meet your obligations under the standard and have defined behavior (i.e. rust's basic guarantee), memory safety issues can't exist at all.
Ah, so this article invalidates all of the safety guarantees of rust? Since one hole was found the entire boat is shot and should be left at the bottom of the harbor?
C++ has a terrible reputation which is well associated with, say C++98, if you have a good linter you can bop people on the head for using news anywhere outside a few limited locations where you consider it warranted. All working environments have language features or even programming paradigms that are considered detrimental to code ecosystem health and fighting against these is an organizational lift when working in any programming language. Full type security doesn't mean someone can't create an overly generic object and just start breaking code contracts across the code base. C++ has an awful lot of footguns and more warts than most but it can be made to be sane for development and the new language features really bring it on par with other modern languages.
I have worked in C++ (primarily within the Qt framework which pushed hard into const refs instead of pointers) and it's fine. I've also worked in PHP which can also be fine. Rust isn't something I've worked at scale in but it certainly is very attractive if I ever jump to an org working in it - but even in Rust you'll want to restrict style divergence and bad patterns with linting.
The answer depends on how foo() is implemented. You can't reason about it locally, and strictly speaking it's not possible to determine at compile time. Now, I should be declaring this gsl::not_null<std::unique_ptr<int>> to comply with the core guidelines, but I think we can agree that optional support libraries aren't relevant to this discussion.
That's trivially untrue. Nothing about turing machines or lambda calculus requires temporal unsafety. Even this example wouldn't exist if the compiler rejected covariant lifetimes. You already know this of course, so I'm not going to keep beating that dead horse.
The obvious follow-up is to find a minimal set of rules that allow us to express what we want without permitting temporal unsafety. The borrow checker is one set of fairly minimal rules that works pretty damn well. Alternatively you could define away the unsafety by giving it semantics, like fil-C does.
C++ still doesn't have a sane modern pattern for tagged unions. If you want to define a type to represent, say, a simple parse tree, then Rust makes that easy and obvious, whereas C++ offers you a hundred options, all of which suck.
I take your point about it being the default, but IMO std::variant is pretty much unusable for a parse tree. It could work for small unions that you visit once in a while, but traversing a nested tree of std::variant types is just a disaster. It somehow manages to be comprehensively worse than using manually tagged unions in all aspects except safety.
Idk, it also has a nicely expressive typesystem outside of lifetimes, a lot of modern syntactic features like pattern matching and monadic error handling, well-written compiler error messages, a well-designed standard library, and substantially less accrued cruft when compared to its largest competitor. Safety might be the cudgel its evangelists like to beat everyone over the head with, but there are certainly things to recommend it outside of that.
Rust has a lot of things that make it nice to write in. Robust enums and pattern matching are something I miss greatly when I’m back in C++. The trait inheritance system is also very flexible and I miss that. Especially compared to monstrosities like multiple inheritance.
Neither C++ nor Rust is zero cost in many cases. Rust needs unsafe or expensive runtime primitives for doubly linked lists, an lru cache, a tree with parent pointers...
Both patch the language gaps with libraries.
You're right, it is. I did a lot of C#/WinForms development back in the day. I never liked it but I liked the people I worked with and the company I worked for so I tolerated it.
Reasons? OK, this is going back about 20 years but, and without going on a massive ranty screed [EDIT: oops, failed], compare something like Swing's JTable to WinForms' DataGrid. One is a really nicely designed and abstracted component with a fully pluggable architecture and an out of the box capability to deal with an arbitrarily large data model (perhaps within the limits of 32-bit integers) and the other... isn't. I tried with DataGrid, I really did. I thought other developers at my employer were "doing it wrong" by reaching for third party controls from the likes of DevExpress and Actipro but... they weren't: I was wrong. If you wanted a proper table/grid control that was easy to customise and extend and wouldn't chunder on millions and millions of rows of data you forked over the money to DevExpress for their control and then you got on with your day solving your real problems that you could charge customers actual money for.
We leaned hard on third party control libraries from DevExpress (particularly grid and tree), Actipro (wizard), and Syncfusion (again, grid). To me, with WinForms, and bearing in mind I'd come from Java Swing (which is by no means perfect) it was really weird working with a UI toolkit where what came in the box wasn't sufficient to build any arbitrarily complex UI I might desire. Weird. And frustrating. Same for the lack of abstraction/separation of concerns. In my Java days, when I wanted a wizard I ripped the one out of NetBeans: I did that in at least two prior jobs using it as the basis for multiple wizards across the relevant applications.
And WPF... although architecturally a lot better, IIRC it didn't even have a proper table/grid control: you had to build your own, and when you start thinking about how rich a proper table/grid is, taking into account accessibility, keyboard shortcuts, picking up OS level settings (palette, scaling, etc.), making it behave like a table in any other application on Windows, I just couldn't be bothered building all that... so then it's back to third parties again.
I don't know what third party support for these frameworks is like nowadays but, fundamentally, for the sort of independent experiments I'm working on I don't want to either (i) fork over hundreds or thousands of dollars to third parties for (I think) basic functionality that (I think) should be available as part of the framework and should have been there since day one, or (ii) spend time wrangling the framework to implement this basic functionality because it isn't a core part of the problem I'm trying to solve or the value I'm trying to deliver.
I'd rather just use Qt or something, which at least has what I need.
"compare something like Swing's JTable to WinForms' DataGrid"
Do you actually mean the DataGrid? Because the WinForms "DataGrid" was deprecated in 2002 with .NET 2.0 which added the DataGridView. The software I work on is Windows Forms and I can't say I've had any issues like you describe with the DataGridView. I was able to create a control derived from it that does all the heavy lifting for customizations(Visual, interaction, cell spanning, etc.), of which we had a lot. Enough that we were exploring third party controls, but found we would have to customize those ourselves anyway, so I just wrote my own control based on DataGridView to save us the licensing.
WPF had it's own DataGrid control from the start, though I can't comment from experience on it's versatility, I'd assume given WPF's nested-content approach it is surely at least more flexible than the DataGridView.
Yes, I mean DataGrid. .NET 2.0 wasn't released until October 2005 so I think your remembrance of dates is a little bit off (understandable: it's now a long time ago).
In any case that didn't really matter. In mid-2004, when I started, the company was still targeting .NET 1.0 for all apps because it meant we could guarantee customers would have that runtime installed on their machines without the need for another dependency. The business model was download -> try -> buy so we wanted as little friction as possible and having a newer version of .NET that might require another download and install wasn't worth the dropout rate we'd experience.
That being said, .NET 1.0 also meant we were using Visual Studio.NET 2002 which was... incredibly painful to work with. I'd come from the world of IntelliJ IDEA which had all manner of code navigation, inspection, refactoring, and testing functionality built in. Not to mention Java already had generics and a much better and more comprehensive framework class library and more mature OSS scene covering whatever was missing from that. .NET 1.0 and VS2002 had none of it and, I forget, was it that VS2002 had no extension model or was it just that ReSharper didn't support it? Either way it felt like stepping back into the mid 1990s and I wasn't happy.
Eventually, sometime in summer or autumn of 2005, I managed to persuade leadership that at least allowing us to use .NET 1.1 and Visual Studio.NET 2003 would be a good idea, and would enable us to use ReSharper, which at least brought us on par with IntelliJ IDEA circa 2003 or so. I can't remember but it might have been that .NET 1.1 had been rolled out over Windows Update or enough service packs for Windows 2000 or Windows XP that we deemed the likely loss of purchases to be negligible.
Our first products developed with .NET 2.0 we didn't start working on until the back half of 2006 and this was really only because we were developing products that plugged in to SQL Server Management Studio which, again IIRC (long time ago), was based on the Visual Studio 2005 shell and required .NET 2.0.
We were always lagging on .NET versions because we wanted to make sure someone could just download, install, and run our products without needing to do anything else.
> Bluesky attracted socialist progressives, furries, and kink-positive folks early on.
> I'm not making any value statements, and there's nothing wrong with the userbase, but this is what dominates the feed for new users.
As someone who's never joined Twitter, Bluesky, Mastodon, etc., I find it weird that this would be the case. If I join as a new user, why would my feed not be empty, until I choose who to follow? If I don't want to see furries and kink, I'll never follow such users, so I'd expect that content will never show up the first place. But if these services pre-populate new users' feeds with random people's posts, well, that's just bizarre to me.
They don't pre-populate the feed, no. I believe they suggest users to follow (on Mastodon that's a per-instance choice based on the administrator), and have sort of generic popular feeds. If you want to see what that looks like on Bluesky, just open up "bsky.app" when you're not logged in. You absolutely do not see a parade of kinky socialist furries.
I think you mean "(Year % 100).version". Or is it "(Year - 2000).version"? Pardon me for being overly pedantic, but ever since Y2K it really bugs me when someone refers to a 2-digit number as "the year".
reply