6 ms·
A Look at Rust from 2012
- assbuttbuttass 11mo agoVery interesting to see the ML influences like ~ for unary minus, unscoped enums, mut on specific struct fields... It seems like over time, a lot of that was replaced with C++-style syntax and semantics. Presumably to make the language appeal more to C++ devs
- ahoka 11mo agoPeople wanted a new C++ and they made Rust into it.
- echelon 11mo agoRust looks nothing like C++. It looks like Ruby. The generics look like Java.
- dhosek 11mo agoJava Generics look like C++ templates and Rust generics act much more like C++ Templates than Java Generics.
- dhosek 11mo agoAlso, “new C++” refers less to syntax and more to role in the development ecosystem.
- tialaramex 11mo agoHow do you feel the generics "look like" Java ? Implementation-wise they're the same trick as C++, monomorphization. Stylistically they're not very like either, however the effect is more like C++ because Rust idiomatically prefers to constrain functions not types so e.g. it's fine to talk about HashMap<f32, f32> a hypothetical hash table of floating point numbers mapped to other floating point numbers - even though we can't use such a type because if we try to insert into it we'll be told that insert requires its key parameter to implement Eq and Hash, which f32 doesn't because of NaN. In both C++ and Java as I understand it these constraints live on the type not the functions associated with that type, although C++ does not have the same constraint here and is perfectly willing to try to make a hash table of floats... but where a constraint lives on a function in C++ it would behave similarly to Rust due to SFINAE - the function won't match so your diagnostics say there's no such function, probably worse diagnostics than Rust but that's par for the course in C++.
- echelon 11mo agoAnd here I was thinking we were talking about the syntax. My Ruby claim doesn't hold much weight either if we're talking about the actual implementation. C++ templates look like an entirely new language within the language. Rust and Java make generics fit within the aesthetics and ergonomics of the language. If anything feels "bolted on" to Rust, it's proc macros and (to a lesser degree) async.
- tialaramex 11mo agoOh I see. Yeah, perhaps slightly for the syntax. I suppose Java's idiom of naming classes (its only user defined types) with capital letters stands out as more similar and so in Java our growable array of geese is ArrayList<Goose>, in Rust it's Vec<Goose> but in C++ std::vector<Goose> or perhaps std::vector<goose> if we're copying the style of the standard library. It doesn't feel like very much, but now that you spell it out I guess I do see it.
- ux266478 11mo ago> C++ templates look like an entirely new language within the language. Templates cover more than just generics. Java full-sale lifted its generics syntax from sepples. I'm curious how you draw the line between the two, when all 3 of them use the angle bracket declaration lists bolted onto the symbol name, a unique style invented by CFront 3. Compare with the generics syntax found in contemporaries like ML, Miranda, Ada, Modula-3 and so on.
- ninkendo 11mo agoOther than the `|var|` syntax in closures, I can't think of a single way Rust looks like Ruby. I mean that seriously, there is almost no other similarities.
- jjtheblunt 11mo agoi suspect the example was syntax like a.b().c().d(10)
- echelon 11mo agoDon't forget expressions and block expressions, and all of the Ruby-esque syntax sugar around them. How expressions work with functional methods. I write a lot of chains with block expressions that almost look 1:1 with Ruby.
- nicoburns 11mo agoThere's definitely some Ruby influence (closures syntax in particulary), but I think I'd argue that Rust syntax is closer to JavaScript/TypeScript than anything else.
- deleted 11mo ago[deleted]
- nine_k 11mo agoAFAICT the need to resolve unscoped enum values, combined with type inference, is one of the things that makes the Swift compiler so slow.
- ux266478 11mo agoWhich is funny, because as a C++ developer it makes it less appealing.
- mkornaukhov 11mo ago> I’m happy with how Rust turned out. I agree, with the possible exception of perplexing async stuff.
- vablings 11mo agoI feel async is in a very good place now (apart from async trait :[ ) As a regular user who isn't developing libraries async is super simple to use. Your function is async = it must be .await and must be in an async runtime. Probably as simple and straightforward as possible. There are no super annoying anti-patterns to deal with. The ecosystem being tokio centric is a little strange though
- leshow 11mo agoI love Rust and async Rust, but it's not true that there aren't annoying things to deal with. Anyone who's written async Rust enough has run into cancel-safety issues, the lack of async Drop and the interaction of async and traits. It's still very good, but there are some issues that don't feel very rust-y.
- bryanlarsen 11mo agoI was really hoping that there'd be movement on a comment without-boats made in https://without.boats/blog/why-async-rust/ https://without.boats/blog/why-async-rust/ to bring a pollster like API into the standard library. Rust has very good reasons for not wanting to bless an executor by bringing it into the standard library. But most of those would be moot if pollster was brought in. It wouldn't stifle experimentation and refinement of other approaches because it's so limited in scope and useless to all but the simplest of use cases. But it does in practice solve what many mislabel as the function coloring problem. Powerful rust libraries tend to be async because that's maximally useful. Many provide an alternate synchronous interface but they all do it differently and it forces selection of an executor even if the library wouldn't otherwise force such a selection. (Although to be clear such libraries do often depend on I/O in a manner that also forces a specific executor selection). Pollster or similar in standard library would allow external crates to be async with essentially no impact on synchronous users.
- steveklabnik 11mo agoFun trivia fact: this is basically the exact moment I first encountered Rust. I’m also generally very glad at where it went from here. It took a tremendous amount of work from so many people to get there.
- ramon156 11mo agoHey, I remember your "Rust 1.0, ten years later" post. Good stuff!
- ramon156 11mo agoI actually liked @T because you would pronounce it as "At T". You could say "The address at T". Curious why people hated it, I might be missing something.
- steveklabnik 11mo ago@T had a number of issues. The first was just that it was weird. People tend to not like weird things. Rust developed a reputation for "that language with a bunch of pointer types that are all weird." The real reason it was removed in the end was just that it elevated a library concept into syntax. Today's Arc<T>/Rc<T> split isn't really possible in an @T world, for example. Shared ownership is a good concept, but you don't need special syntax to indicate it.
- zozbot234 11mo ago> The real reason it was removed in the end was just that it elevated a library concept into syntax. Rust still does this in all sorts of silly ways, such as the ! type. What's the point of wasting an entire symbol that could have plenty of alternate uses on something that's so rarely used and could easily be defined as either a library type (empty enum) or at least be given a custom keyword, such as `never`? (Introduce it over an edition boundary, if you must preserve backwards compatibility.) The fact that it involves some compiler magic is no excuse; that's why Rust uses "langitem" markers within its core library.
- steveklabnik 11mo agoThe standing joke for the last few years is that "the never type is named after its date of stabilization." I certainly don't disagree that Rust has flaws, for sure. I think this particular one is pretty far down the list, though. I'm not sure what else I'd want to use ! for, and by virtue of it not being used so often means that it's much less of a pain than @T would have been, though I would also argue that 2012 Rust used ~T and @T far more than contemporary Rust does (I still remember pcwalton's mailing list post about how you didn't have to use ~ for comparing strings!) and so was even more painful at the time than would be now.
- srott 11mo ago> rest of the post is me trying to make sense of the tutorial on borrowing. It has fried my brain and negatively affected my skills in modern Rust, so be wary I think that tutorial discouraged me from really getting into Rust
- sota_pop 11mo agoI’m no expert in Rust, but have done a couple of very minimal weekend projects. In the time I’ve read up on Rust, I’ve always looked at the borrow mechanism like an extreme/overactive implementation of RAII from C++, that is triggered with every context change. Would be interested to hear where this analogy breaks down from someone more experienced than me.
- steveklabnik 11mo agoBorrowing and RAII are basically separate features, though they do interact. RAII in Rust is like C++, but simpler: there are no constructors, only destructors. The Drop trait gets called like in C++, except that in Rust, moves are the default, and destructors don't get called on moved-from objects, that is, your destructor only runs once. References are, at runtime, the same as a pointer in C++, except they cannot be null. We also say that they "borrow" what they refer to, which means that the compiler keeps track of the lifetime of the referent. This ensures that the referent always outlives its reference, so that its reference is always valid. This is a compile-time analysis on the control-flow graph of your program. Does that make sense?
- Macha 11mo agoI think this was a year or two before I got to rust - some of these things still existed then (bare traits, no NLL, the ecosystem was only halfway onto cargo), while others (the old pointer type syntax) had already gone.
- ravenical 11mo agocontinue was called loop for some reason How strange! Does anyone know why?
- kuresov 11mo agoI could see it… like “loop back around” or “continue loop”. I think good old “continue” is better and more familiar though :)
- steveklabnik 11mo agoThere was an early rule that Rust keywords should be five characters or less. I would guess it's because of this rule. I believe loop turned into cont to satisfy this rule, and then eventually we relaxed the rule, and it became continue.
- iknowstuff 11mo agoWhoa, do you know who and why came up with that? So strange, making it less readable on purpose?
- steveklabnik 11mo agoIIRC it was just a personal preference of Graydon's back then. I'm also not sure it was intended to live forever, just something to try and nudge things in a particular direction. Terseness doesn't inherently mean less readable. I do think that that rule is probably not one that would be good permanently.
- Defletter 11mo agoProbably for the same reason that most new language these days cannot bring themselves to just use "function" and instead have "fn", "fun", "func", etc. It's a headlong pursuit of conciseness for the sake of conciseness.
- OhMeadhbh 11mo agoI encountered Rust sometime around 2010. I was working a couple of blocks away from Mozilla's Mountain View office and would often overhear people talking about it at Dana Street Coffee Roasting. A couple years later I was working at Mozilla trying to unf*ck their TLS and libpkix implementations. The team rocked, but management sucked. The best part about it is I kept bumping into Brendan Eich and having great conversations about Lisp. I can't remember if P. C. Walton worked there, but several occasions he was in the office and gave me a VERY good, VERY succinct description of the language. I wrote a fair amount of Rust code in 2012, none of it on a real project like servo. All of it just code to try to understand what the language was trying to make easy. None of that code compiles any more. (Or enough of it fails that I stopped looking at it.) It's not so much a "critique" as it is a confirmation that when the crustaceans tell you the language definition isn't finished yet, believe them. I like the feel of Rust much more than C/C++, but I have C code I wrote in 1982 that still compiles and does what you think it should do. C++ code from 1990 still seems to compile. I have Rust code from 2014 that won't even compile. Rust is a cool language and I hope it eventually settles down enough to be considered for "real" projects. I've done a little bit of Ada in the last year and I really, really want something better. But... reverse in-compatibility is a deal-breaker for some corners of the commercial world. And yes, I know that (like Python) you can build an environment that lets you continue to compile old code with old compilers and some old code with new compilers. But the projects I'm talking about have life-times measured in decades. Will rustc in 2055 be able to compile a program written today? It doesn't seem to be on the top of minds of most of the Rust community. I'm not saying Rust is ugly. In fact, I really like some aspects of the language. And post 1.0 is MUCH better than pre 1.0. But if we could go for a few years without breaking changes that would be nice.
- steveklabnik 11mo agoRust achieved 1.0 in 2015, three years after you wrote that code in 2012. Stability wasn't guaranteed until then. Afterwards, it has been. Code from 2015 still compiles today. It's no surprise that 2014 code doesn't compile, as it came before those suggestions. > I hope it eventually settles down enough to be considered for "real" projects. Rust is being deployed for real projects at pretty much every major tech company at this point, and is used on the critical path of real infrastructure. > Will rustc in 2055 be able to compile a program written today? It doesn't seem to be on the top of minds of most of the Rust community. This has been a very strong focus of the Rust project for a long time; the reason you saw so much breakage from 2010-2015 was to make sure that it was in the state that we'd be okay with making it stable, and then the track record from 2015 to now has been excellent. There have been a few exceptions, but they've generally been quite small, and needed for soundness fixes.
- pton_xd 11mo agoI was really excited about the idea of a modern statically typed language with green threads ala Erlang / BEAM. I lost interest when Rust moved away from that direction and became focused on zero-cost abstractions instead.
- steveklabnik 11mo agoIt certainly was a big shift, a lot of people both had your opinion and had the opposite, for sure. Do you think Go fulfills that for you today or do you think there's still space for a new language here?
- pdimitar 11mo agoAs a person who actively uses Elixir, Rust and Go (in that priority order) to me there is a maddening gap between Rust and Go. While Go has the goroutines and they have made concurrent and parallel programming accessible to many, they are a rather raw material that's easy to abuse and use wrongly (leaks, deadlocks, and don't even get me started on writing to a closed channel -- instant panic and program abort). Rust async is also too raw but in another way: gets wordy / verbose and too implementation-oriented way too quickly -- I never wanted to care about Pin<Box<???>> or what must this or that Future implement in order to be eligible for usage in `select` and whatnot. Those things should have been hidden behind a DSL much like `select` and `async` itself are a DSL / macros / state-machines of sorts. Rust's async just seems... I don't know... unfinished. Zero disrespect is intended (and I do recognize you by your username), I love Rust and I never pass an opportunity to whip up an internal CLI tool with it and my most consulting engagements have resulted in teams highly appreciating such tools, but I can't shake the feeling that Rust's async could be more... polished. Both Rust's and Go's async mechanics leave me with the impression that somebody thought that they gave the devs enough LEGO building blocks and called it a day. I don't judge. I understand. But as a user of the languages I also have the right to find their async facilities less than ideal. Erlang / Elixir / Gleam / LFE on the other hand stand on a runtime that has exhaustively analyzed a ton of async scenarios and cover them very well (minus stuff like filesystem operations being centralized through a singleton runtime agent, something you can opt out of, thankfully). So I'd say both Rust and Go are ripe for either disruption or courageous backwards-incompatible modifications. Their async implementations simply did not go far enough. And don't get me wrong, I love both and do my best to use them regularly. But it's a sad reality that their "unfinishedness" led to a plethora of footguns that became a badge of honor if you get to know most or all of them, as in: know how to avoid them. Which I don't know why many see as a desired state of affairs. Job security, I suppose. I would kill for something as terse and explicit as Go but as super strict as Rust but that also has 100% finished async semantics, and has a faster compiler than Rust but optimizing as aggressively as it as well. Yeah, I know: what color do I like my dragon? All that being said, Rust is the closest we have to a perfect language currently. And that's kind of sad because it has a few things that it really needs to fix if it wants to keep gaining mind-share. I personally find myself reluctant trying to build a career with it. But I'll not digress further.
- junon 11mo agoI see now why my first attempt at Rust around this time failed miserably. I had forgotten about a lot of this, and remember trying to make liblua bindings at the time for something I was working on. I wrote Rust off as too cryptic to get anything done with. I'm really, really glad I've since picked it back up post-1.0.