[HN Gopher] The Registers of Rust
       ___________________________________________________________________
        
       The Registers of Rust
        
       Author : todsacerdoti
       Score  : 169 points
       Date   : 2023-03-08 17:01 UTC (6 hours ago)
        
 (HTM) web link (without.boats)
 (TXT) w3m dump (without.boats)
        
       | stathibus wrote:
       | [flagged]
        
         | sockaddr wrote:
         | No. But I'll readily admit to upvoting stuff like this
         | submission.
        
         | steveklabnik wrote:
         | Hacker News attempts to prevent bot upvotes, last I heard. So
         | even if there were, it would not work, and if it did, I'm sure
         | the hacker news team would work towards fixing that.
         | 
         | This is simply a high-quality, very technical blog post from
         | someone who's had a tremendous impact on a popular project.
         | Hence upvotes.
        
         | Dowwie wrote:
         | It's an army of Rust evangelists. We have a lot of time on our
         | hands waiting for compiles.
        
       | brundolf wrote:
       | This helped congeal a thing I've been thinking about in my Rust
       | usage for a long time, but didn't know how to express:
       | 
       | > In Rust, this distinction in register can look like this:
       | 
       | > - Will I use references and borrowing, or will I liberally use
       | clone to avoid it?
       | 
       | > In general, Rust strives to have an obvious register which to
       | operate which is still going to be performant enough (and
       | hopefully accessible enough!), while allowing users to switch
       | register when they need to.
       | 
       | One of the biggest ergonomics problems in Rust, in my experience,
       | is that for certain things (like references vs clones, or
       | generics vs enums vs dynamic dispatch), it can be very hard to
       | change registers once you realize you need a different one. Often
       | it means making changes throughout your entire codebase
       | 
       | I don't have an easy solution but I feel like I at least have
       | words for the problem now
        
         | zamubafoo wrote:
         | I think Rust is actually pretty good at this. If you do have to
         | do a change that will affect your entire code base (or at least
         | will be pervasive), the compiler will be able to tell you where
         | things are wrong with a good degree of precision.
        
         | drewtato wrote:
         | The strong typing in rust definitely helps with this, though.
         | For most problems, you can encapsulate a refactor into
         | something that, at each occurrence, either works automatically
         | (with things like generics and deref) or fails to compile.
        
       | tel wrote:
       | I'm very curious about this statement, does anyone know more
       | detail
       | 
       | > Futures combinators are not used because the combinator model
       | suffered some specific problems with state sharing in futures
        
         | withoutboats3 wrote:
         | It's exactly the problem that led us to Pin in designing
         | async/await.
         | 
         | Futures need to own all of their state. If you want to use that
         | state across multiple combinators (in async/await terms,
         | "across an await point"), given that rust doesn't have GC, you
         | have to somehow make it available to both closures. This meant
         | Arc<Mutex<_>> around things even though they were being used in
         | sequence, because both closures needed to own the state and the
         | compiler doesn't know the closures will only be called in
         | sequence. It was a mess, and was a big hurdle for adoption of
         | futures before async/await was added.
        
           | tel wrote:
           | That makes sense, thank you.
           | 
           | I had been a little confused as I'd seen the combinators
           | available in the futures crate (along with Stream) and it's a
           | little tricky to figure out the status and review of
           | techniques that are implemented there but not standardized.
        
       | wyldfire wrote:
       | > Will I use references and borrowing, or will I liberally use
       | clone to avoid it?
       | 
       | I haven't written much Rust but when I did I was very liberal
       | with calls to .clone().
        
         | steveklabnik wrote:
         | That is, in my opinion, the way it should be.
        
           | wyldfire wrote:
           | Really? I felt like I was just punting because I didn't take
           | time to understand and resolve potential dependencies.
           | 
           | In my case the data was relatively small and I just wanted
           | functionality. But I felt like if I could have worked out
           | borrowing it would've generated more efficient code and less
           | memory consumption.
        
             | lordnacho wrote:
             | I'm undecided. I feel it's a bit like when you .unwrap()
             | everything. Either I take the time to match all the
             | potential results, or I do it quick and dirty. But also
             | when it comes to cloning if you don't do it you get a lot
             | of lifetime annotations.
        
             | steveklabnik wrote:
             | We put this aside in the book for this exact reason:
             | https://doc.rust-lang.org/stable/book/ch12-03-improving-
             | erro...
             | 
             | > But I felt like if I could have worked out borrowing it
             | would've generated more efficient code and less memory
             | consumption.
             | 
             | That is possible! But while you're learning, this isn't the
             | most important thing to focus on. And depending on what
             | you're trying to do, using borrowing may be easy, or may be
             | hard, and while you're trying to learn, you don't know
             | enough to evaluate the tradeoff on that basis, so in my
             | humble opinion, it is absolutely okay to clone, and is
             | probably even what you _should_ do in most cases.
             | 
             | Once you're feeling good enough about Rust to start digging
             | deeper, working on trying to not do this is a valuable
             | skill. But imho it's a waste of time when you're starting,
             | _and_ may lead you into a pit of despair.
        
               | tptacek wrote:
               | The aside in the book says the opposite of what you claim
               | it to be saying. Here, you suggest that liberal cloning
               | is the way it should be; there, you say it's fine for
               | beginner code, which is a very unsubtle nudge. Which is
               | it?
        
               | withoutboats3 wrote:
               | I think the confusion comes from the fact that Steve
               | would consider code written by someone who "hasn't
               | written much Rust" to be "beginner code," so he meant
               | exactly what the book says. I would agree that people
               | getting the hang of Rust shouldn't worry too much about
               | this, but that production code that deep clones buffers
               | when it could use references is badly written (then
               | again, it may not matter at all!).
        
               | steveklabnik wrote:
               | I am a little offput by how aggro this comment is, but I
               | really like you and so will give you the benefit of the
               | doubt here.
               | 
               | I wrote this text years ago. It is possible I didn't do
               | as good of a job as I could have. This was added directly
               | in response to situations' like the OPs, people saying
               | that they felt bad using clone while they were learning
               | Rust, and so the comment, coming early in the book, and
               | as a text for learners, focuses on that case.
               | 
               | It's also the same as in this thread, I thought I was
               | being pretty clear that I'm talking about people learning
               | Rust?
               | 
               | However, just because I say one thing doesn't mean I'm
               | implying something else; for non-beginners, I don't think
               | clone is a moral issue either way. If you are trying to
               | get ultimate performance, clone may be an issue. It also
               | may not. Some clones are more expensive than others.
               | Furthermore, not everyone needs to get ultimate
               | performance, and that's okay too. It is up to you. The
               | point is that I don't think this question is a useful one
               | for someone to engage with as a beginner. It _is_ a
               | useful question for intermediate programmers to engage
               | with, but so that they can make the right call for them,
               | not because one or the other is the correct answer in all
               | situations.
        
               | tptacek wrote:
               | As a Rust programmer, I have the exact same lived
               | experience of the language that the parent commenter
               | does: that Rust can be relatively straightforward to
               | write if you liberally clone things, but that the
               | prevailing community norm strongly suggests that cloning
               | is a code smell, or something you do in tooling-grade
               | code.
               | 
               | The parent commenter was surprised that you suggesting
               | liberal cloning was the way Rust code should be --- that,
               | like, the median Rust crate should probably be written in
               | the "clone liberally" register. You said that was the
               | reason you wrote the Rust book aside. But I read that
               | book and that aside and reached the opposite conclusion,
               | and I think people who follow your link will mostly see
               | why.
               | 
               | You haven't exactly cleared things up here, either. "For
               | non-beginners, clone isn't a moral issue". Well, that's
               | not what you just said upthread. I'm pressing you on this
               | because it would be helpful to get an actual clear signal
               | on this. Should most code be written with liberal clones,
               | or should most beginner code be written with liberal
               | clones? Like the previous commenter, I just want to
               | understand what you're trying to say.
               | 
               | (A sibling comment here says the exact thing that I'm
               | saying creates the mixed message here: that cloning is
               | fine... in beginner code, but not in serious code.)
               | 
               | This is not, as we both know, a minor distinction in
               | Rust; it is maybe the biggest stylistic distinction in
               | actually writing Rust? Moreso maybe even than async?
        
               | mplanchard wrote:
               | It's weird to me the degree to which you're pressing an
               | offhand comment into being some kind of Statement.
               | 
               | I'd expect anyone writing Rust regularly to know that the
               | impact of Clone is context-dependent, and whether or not
               | you should be fine with using it liberally is also
               | context-dependent. Big object? Hot loop? Avoid cloning.
               | Not worried about performance? Clone all you want if it
               | makes the code easier and faster to write. You can always
               | optimize later.
               | 
               | Sometimes it's easy to avoid clones, and if you're
               | writing a lot of Rust it often feels like you might as
               | well, just in case. But at least for my team, "you could
               | get rid of this clone" is generally a take-it-or-leave-it
               | kind of comment in code review.
               | 
               | There's no easy way to express "it's a trade-off between
               | performance and ease of use that you'll get better at
               | with time" in a way that is instructive in any meaningful
               | way, which is why I imagine it's more useful to push
               | people to err on the side of what's going to be faster to
               | get them to the amount of experience they need to engage
               | meaningfully with the question within their own context.
        
               | tptacek wrote:
               | Well, if I can mostly ignore fussy ownership and
               | borrowing stuff and just clone everything, all the time,
               | getting rid of clones exclusively in places that I
               | profile and learn to be in the hot path, and the
               | resulting code will be idiomatic Rust, that would be
               | welcome news to me. That's where I'm coming from.
               | 
               | My impression from Klabnik's most recent comment is that
               | this isn't the case. Which is fine! It lines up with my
               | previous assumptions about Rust idiom.
        
               | steveklabnik wrote:
               | > My impression from Klabnik's most recent comment is
               | that this isn't the case.
               | 
               | Okay last comment in this sub-thread because I have to
               | get back to my job here, which hilariously is adding some
               | boxing and possibly cloning in order to improve a
               | codebase.
               | 
               | I feel like I'm going crazy. I feel like this:
               | 
               | > if I can mostly ignore fussy ownership and borrowing
               | stuff and just clone everything, all the time, getting
               | rid of clones exclusively in places that I profile and
               | learn to be in the hot path, and the resulting code will
               | be idiomatic Rust
               | 
               | is exactly what my last comment said. This whole chain,
               | in my experience, is me saying "clone is not a moral
               | issue" and you saying "why are you saying that people
               | that use clone should feel bad." So I need to bow out. I
               | wish I could figure out where this disconnect is, but
               | it's clear that this thread is not achieving that.
        
               | Serow225 wrote:
               | <3
        
               | burntsushi wrote:
               | I'm not quite sure where the disconnect is either, but
               | yeah, "should I clone everywhere" or "is cloning
               | everywhere idiomatic" is just one of those models that is
               | useful, but like all models, is invariably wrong in some
               | cases.
               | 
               | Just as one example, consider a function I wrote. It
               | accepts a &str as a parameter. Internally, among other
               | things, it clones that &str into a String. If you asked
               | me whether that was "idiomatic" devoid of any other
               | context, I would say, "probably not? Why not just ask for
               | the String or a Into<String> instead?" But it's not a
               | certainty. Just a likelihood.
               | 
               | But now let's add context. The context is that that
               | function I mentioned is Regex::new. Does that change my
               | answer? You bet your ass it does. Because cloning that
               | pattern string has now turned into a definitively
               | negligible cost. (By many orders of magnitude.) And there
               | is upside to accepting a &str: it's non-generic, a little
               | easier to understand and is unlikely to ever run afoul of
               | type inference. Those aren't huge upsides, but there is
               | actually no downside here _because_ of the context.
               | 
               | As others have pointed out, there is no one-size-fits-all
               | answer to this question. There are models though, and
               | those models (e.g., "don't worry about cloning while
               | you're learning Rust") are very likely to serve you quite
               | well. That might not be every path that everyone learning
               | Rust always takes. But it's a decent bet in my
               | experience.
        
               | tptacek wrote:
               | This makes sense! (Also, even if I was deliberately
               | cloning liberally, I'd still pass &str to most things).
        
               | steveklabnik wrote:
               | > that, like, the median Rust crate should probably be
               | written in the "clone liberally" register.
               | 
               | That is not what I understand myself to have said. The
               | parent said that they "do not write much Rust code." That
               | is very different than "the median Rust crate."
               | 
               | > Should most code be written with liberal clones,
               | 
               | I think this question is a category error. There is not
               | enough context to give an opinion. And I think that means
               | you cannot make a broad generalization about clone; some
               | code should have a bunch of clones, and some code should
               | not, _even if they 're the same code_, because they
               | operate in different kinds of contexts or sure,
               | registers, to sort of stick to the vibes of the original
               | post.
               | 
               | If I am presented the exact same code by two people, and
               | one of them started writing Rust yesterday, and says
               | "what do you think of my code?" I would not even give
               | consideration to the number of clones when attempting to
               | give them my opinion about their code. If someone came to
               | me after writing Rust for ten years and said "hey I am
               | struggling to improve performance in this code" and said
               | "what do you think of my code?" and I saw a bunch of
               | clones, I would say "have you profiled? I would suspect
               | that maybe clones are causing your problem but I wouldn't
               | do anything until I had a flame graph or equivalent."
               | Even then that is not a moral question or answer, it is
               | an engineering one.
               | 
               | > or should most beginner code be written with liberal
               | clones?
               | 
               | Even this isn't _exactly_ what I meant, but is closer. I
               | mean what I said in my parent comment to you, beginners
               | should not feel bad if their code uses clone, whatsoever.
               | That does not then imply that non-beginners should feel
               | bad, I said absolutely nothing in this thread about
               | anything other than beginner code (until the paragraph
               | above in this comment and the paragraph in the comment
               | you 're currently replying to).
        
               | Serow225 wrote:
               | There is one tangential thing that I've thought about
               | before--it would be nice if there was some way to encode
               | this into the library ecosystem (ie crates.io) I have no
               | idea how this would be realistically possible though--
               | it's pretty clear that you can rely on categories that
               | are statically verifiable like "no-std/no-alloc". But
               | what mechanism could be used to allow library consumers
               | to distinguish between things like "laser focus on high
               | perf/low-alloc" vs "prioritizes API over perf-at-all-
               | costs" vs "this package is an experiment/Baby's First
               | Crate/shitpost" ?? They're all valid choices for
               | different consumers or usecases.
        
               | tialaramex wrote:
               | I think documentation is the right layer to express what
               | is or is not a goal for the crate. Whether you _met_ the
               | goal is not something you as author can judge reliably.
               | 
               | https://crates.io/crates/misfortunate - is not intended
               | to be used seriously. A redditor pointed out that
               | arguably my Double (a smart pointer where the mutable and
               | immutable references point to separate things and you can
               | swap their places) might actually be useful! But I don't
               | want you to depend on misfortunate::Double in your real
               | software project - if that _is_ useful (and maybe, with
               | careful documentation, it is) you should give it a name
               | suiting its purpose and include it in a crate of stuff
               | that 's intended to be used, not as something like a
               | practical joke or thought experiment.
        
               | steveklabnik wrote:
               | Yeah, there is _something_ in this space for sure. I
               | think one of the issues is time; code can start off as a
               | fun experiment, but transform into one that 's not, which
               | maybe just means that it is metadata associated with a
               | specific release, yadda yadda, but there's a lot here to
               | think about. For sure.
               | 
               | I recently have been accepting some PRs to some Ruby code
               | that I wrote ten years ago that ended up being still in-
               | use today. "Shitpost" or "baby's first crate" isn't
               | accurate, but "hey I was very serious about this before
               | but now it's not as high priority for me but that doesn't
               | mean I abandoned it" is a tough thing to encode.
        
               | Serow225 wrote:
               | Absolutely true re evolution. That's why it would have to
               | probably be crate keywords rather than categories, I'm
               | thinking.
               | 
               | This whole space about encoding library non-technical
               | aspects like intent and status seems like it has a lot of
               | possibilities. I wonder if there's prior art in other
               | language ecosystems?
        
               | steveklabnik wrote:
               | Perl has the Acme namespace for expressly silly projects,
               | that's the first thing that comes to mind...
        
               | biorach wrote:
               | > The aside in the book says the opposite of what you
               | claim it to be saying. Here, you suggest that liberal
               | cloning is the way it should be; there, you say it's fine
               | for beginner code, which is a very unsubtle nudge. Which
               | is it?
               | 
               | That's phrased way too harshly, considering you're
               | talking to someone who has put significant efforts into
               | making Rust accessible to others.
        
               | Serow225 wrote:
               | my interpretation of the "clone is the way to go" comment
               | is that it's in the context of the OP saying "I haven't
               | written much Rust...", which puts a pretty clear frame
               | around the intended applicability of the statement no? I
               | don't taking it at all as being an absolute statement.
        
             | ripley12 wrote:
             | Premature optimization, etc. etc.
             | 
             | I tend to follow a "clone first, figure out lifetimes later
             | _if profiling shows that it would be worthwhile_ " rule. If
             | I always did the optimal thing with lifetimes, I'd never
             | actually finish anything.
        
               | philosopher1234 wrote:
               | It begs the question, why is clone a method and borrowing
               | implicit? Perhaps it should be the opposite. `.borrow` or
               | something like that.
        
               | steveklabnik wrote:
               | Borrowing isn't implicit, as you have an &. But even
               | beyond that, clone is not implicit because it may be an
               | expensive operation, and so Rust wants to expose that to
               | you. It avoids issues like this:
               | https://news.ycombinator.com/item?id=8704318
        
               | colejohnson66 wrote:
               | Technically, it's not implicit; You need to prefix your
               | value with `&` to borrow it.
        
             | kaba0 wrote:
             | Or even the reverse may be true -- copying a block serially
             | is insanely fast on modern processors.
        
           | marcosdumay wrote:
           | What is the way to go is very context sensitive. You may be
           | better with the default references, using clone everywhere,
           | with Rc, with Arc, RefCell, or whatever.
           | 
           | What is important to know is that your program is not
           | automatically bad just because you decided not to use only
           | references.
        
             | steveklabnik wrote:
             | I would agree. See my reply to tptacek.
        
       | saurik wrote:
       | I will claim that the most important thing to understand about
       | all three of the concepts in this article -- Fallibility,
       | Asynchrony, and Iteration (as well as some that aren't discussed,
       | but are to-me relevant, such as "Allocation: holds scoped
       | resources" <- one I feel Rust and C++ reasonably-correctly assume
       | every object / value might one day take part in) -- is that these
       | are all _monads_ (yes: including Iteration /List, which I think
       | took me the longest to fully appreciate from the set of commonly-
       | referenced monads); and, in a language with a more theoretically-
       | sound core (aka, Haskell... and no: I am not a Haskell zealot by
       | any means and in fact have wasted away most of my life for
       | decades using C++ and Python), these "control-flow effects"
       | (which is frankly a better name than "monad") are all supported
       | using the same typeclass and rely on the same syntax, which not
       | only ensures that every such "register" is correctly analogous
       | with the others but even allows for end developers to extend the
       | set of similar primitives without resorting to increasingly-
       | fraught language modifications.
        
         | Rusky wrote:
         | This is something that came up constantly while Rust was
         | working on `async`, and the main reason Rust doesn't use this
         | approach is that the usual low-level concerns around
         | allocation/memory layout get in the way of just plopping a
         | `Monad` trait in there.
         | 
         | (There's a secondary reason which is that Rust does not have
         | higher-kinded types and thus cannot even express `Monad` to
         | begin with. It recently got GATs which can _encode_ it, but
         | that feature was designed as an intentional alternative to full
         | complexity of higher-kinded types.)
         | 
         | The author of TFA wrote this thread on the subject:
         | https://twitter.com/withoutboats/status/1027702531361857536
        
           | saurik wrote:
           | FWIW, most of the arguments in that thread are "you can't add
           | monads to Rust", which seems like a perfectly fine thing to
           | say and is quite likely true. I am not saying "you should add
           | monads to Rust" and I certainly am not saying "it would be
           | trivial to just drop a Monad trait in right now _why aren 't
           | they doing that_" ;P.
           | 
           | I do believe, however, that there is a different design for a
           | programming language that solves Rust's core needs (efficient
           | and safe) and yet which supports something akin to generic
           | "control-flow effects"... which, to be clear, might not fit
           | the specific definition of Monad.
           | 
           | Maybe, for example, such a language simply doesn't support
           | early return (a feature I can do without). Maybe it has
           | linear types (which I maintain are missing from Rust, and
           | yes: I have read the article that claims it is difficult and
           | will note that that same article also firmly admits it is
           | possible).
           | 
           | Maybe, instead of using Monad, the right interface for a
           | control-flow effect is somehow designed around the concept of
           | how optimizing compilers need to reify these effects into
           | actual efficient code, or maybe the way to get them feels
           | more like an unhygienic macro... the design space isn't
           | limited here.
           | 
           | To that end, the one bit of this thread that I personally
           | find valuable is the argument that borrowing is somehow
           | totally incompatible with the idea of a yield point that is a
           | function, which I find both surprising but also possible... I
           | certainly haven't put a ton of thought into it and am so
           | tired right now I likely couldn't even appreciate a trivial
           | and complete proof of such :(.
           | 
           | Regardless: I also am not claiming that Rust shouldn't exist
           | with its current trade offs (at least, for this reason... I
           | _do_ think its non-monadic design should have exceptions and
           | am almost entirely sure they would be compatible with the
           | rest of the language; I am extremely disappointed that they
           | weren 't provided).
           | 
           | However, to see this article talking about these three things
           | and only using the word "monad" a single time buried in some
           | table near the end was quite shocking as it is trying to lay
           | out a ton of unusual terminology for something the author
           | _clearly_ understands deeply... it almost feels like they are
           | actively avoiding speaking the word  "monad" ;P.
        
             | Rusky wrote:
             | Sure- I didn't read your comment that way, my point was
             | primarily just that there is no clear path to such a
             | language yet. It's an open question of whether it is
             | possible and how to accomplish it, and TFA is already
             | another very small step toward answering that question.
             | 
             | (I suspect their reason for avoiding the word "monad" was
             | that it is totally alien and obfuscatory to a significant
             | part of the target audience, and it's relatively easy for
             | those who are familiar to connect the dots themselves, as
             | you clearly did.)
        
             | zozbot234 wrote:
             | Aren't effect types generally related to Lawvere theories,
             | as opposed to monads? AIUI the two differ most promimently
             | in the way they compose; composition of monads being very
             | much ad hoc. I didn't read OP as relating to monads
             | specifically.
        
         | c54 wrote:
         | I think you're making a good point that I probably agree with,
         | but I can't tell partially because your writing style is hard
         | to follow. Your whole comment could be improved by separating
         | into multiple sentences and moving the asides out of the main
         | body of thought
        
           | saurik wrote:
           | It could certainly be improved for reading at a glance...
           | but, if you just pay attention to the punctuation, I kind of
           | think inlining the "asides" there is better than simply
           | trying to tree them out (which would be the fast way to fix
           | it). Like: this is a comment, not an article... I am lying in
           | bed (deeply wishing I were asleep) trying to quickly type a
           | train of thought into my phone (a smaller one than I normally
           | even use) and am even feeling forced to do so under a time
           | pressure (as once a post gets enough comments you won't ever
           | find anything). Often, I will even type such a comment at
           | first and then--after posting it--take the next 20 minutes to
           | "clean it up" into some paragraphs (but am not going to do
           | that this time as I am hurting my elbow). You are welcome to
           | just ignore my comment for today; and, maybe one day, I will
           | have more than a few minutes to allocate to writing yet-
           | another-article-on-monads that no one will want to read (and
           | likely won't help anyone understand... see "the monad
           | tutorial fallacy", one of my favorite articles / concepts
           | ;P).
        
         | withoutboats3 wrote:
         | I also think monads are elegant, and you're write that effects
         | can all be modeled with monads, but I think the notion of a
         | monad abstraction is a poor fit for a systems language as I
         | elaborated years ago in the twitter thread Rusky linked to.
        
       | harikb wrote:
       | The article talks about options (english meaning) as in the
       | developer is choosing to model his program to use a combination
       | of these registers. Unfortunately, that is exactly my problem.
       | __There should be one-- and preferably only one --obvious way to
       | do it.__
        
         | steveklabnik wrote:
         | That is a useful design maxim, but the problem is that in a
         | "systems language," it is difficult if not impossible, in my
         | opinion, to achieve.
         | 
         | The closer you get to physical reality, the harder it is to be
         | able to fit the world into your model, and you need to fit your
         | model to the world. In Rust, unsafe is the way to manage this
         | difficult set of tradeoffs
        
       | phab wrote:
       | I found this article enlightening; an example of where a little
       | formalism/structure (in the notion of the four registers) really
       | helps identify the missing pieces in the wider picture.
       | 
       | I did find the use of the term "register" slightly jarring given
       | its somewhat overloaded nature between its natural language
       | meaning, used here, and also the sense of "a specific place in
       | which to store a datum". Reading the Wikipedia page on the term,
       | I came across "diatype", which to me seemed to convey the same
       | meaning without the potential confusion from the polysemantics of
       | "register"...?
        
         | steveklabnik wrote:
         | "register" is often used in the sense boats uses it in like
         | a... let's say English graduate student sense?
         | 
         | Given that "withoutboats" is a Foucault reference, this
         | shouldn't surprise anyone who's familiar with that intellectual
         | tradition.
         | 
         | For a bit more discussion on this, there's a fantastic comment
         | on the Reddit discussion
         | https://www.reddit.com/r/rust/comments/11m0j30/comment/jbflz...
        
           | iviv wrote:
           | Now I'm interested in the Foucault reference :)
        
             | steveklabnik wrote:
             | It's right there in the header, "Without boats, dreams dry
             | up."
             | 
             | The full quote is "In civilizations without boats, dreams
             | dry up, espionage takes the place of adventure and the
             | police take the place of pirates," from his work "Of Other
             | Spaces, Heterotopias."
        
         | PaulDavisThe1st wrote:
         | "Dialect" seems more appropriate me.
        
           | withoutboats3 wrote:
           | Programming languages already have dialects, but there is a
           | distinction between dialects and registers, even in
           | linguistics. They blur in some cases (AAVE for example), but
           | dialects are usually thought of more as a variety of language
           | used by people in geographic or cultural grouping; registers
           | are used by users in different social situations. For
           | example, when I give a presentation I use a very different
           | register from when I have a drink with my friends.
        
             | PaulDavisThe1st wrote:
             | Right. All of which is why I find "dialect" more
             | appropriate.
             | 
             | The sorts of language/library constructs that are used are
             | likely to vary across "people in (programming task)
             | grouping".
        
               | vlthr wrote:
               | That example actually highlights why I think _register_
               | is a helpful name. Dialects vary across people, but
               | registers vary across situations for each person.
               | 
               | In the programming language context, _dialect_ can be
               | applied on varying levels but usually signifies the
               | former, where each individual or group has a persistent
               | preference for some language or style. Within a single
               | programming language, dialects are usually a bad thing
               | because they risk splintering the community into mutually
               | incompatible subgroups (e.g. scala fp styles, c++ boost).
               | 
               | Part of the reason why evolving a language is hard is
               | because every time you introduce a new way to do
               | something which could be done before, users have to
               | choose. If that choice divides users into groups that
               | persistently pick one over the other based on style or
               | community affiliation, you've introduced a new dialect.
               | If the choice flows more naturally from the situation the
               | user finds themselves in, you've introduced a new
               | register.
        
           | throwawaymaths wrote:
           | I would have called it "mood"/"mode"
           | 
           | Like the subjunctive mood. I imagine not super helpful for
           | English speakers where we have exactly one verb that takes a
           | change on subjunctive mood.
           | 
           | In most languages with it, entering the subjunctive mood
           | requires a prefixing context/preposition which is analogous
           | to function coloring system/async keyword
        
         | withoutboats3 wrote:
         | This dual meaning definitely crossed my mind as I was writing..
         | it's unfortunate.
         | 
         | Whenever I encounter a dual like this I like to investigate the
         | etymology. I assume the use in linguistics is by metaphor to
         | its use in music, "the range of a voice or instrument." More
         | broadly, the term register comes to us from the Latin for a
         | list of items recorded, ultimately from a word for carrying.
         | Maybe there's something to make of that in connection to each
         | of these very different meanings, I don't know.
         | 
         | The problem with diatype is that register, although not an
         | extremely common word, is I thought somewhat well known,
         | whereas I've never heard of diatype. I've been known to
         | overestimate how familiar words of this sort are to other
         | people, though, so maybe they're equally obscure to most of my
         | readers.
        
           | dllthomas wrote:
           | I don't know that it would have been better, but an option
           | would have been to use one of the less ambiguous but less
           | familiar terms, and define it in terms of the more familiar
           | term early on. Something like, "diatype (register, in the
           | sociological sense)".
        
           | burntsushi wrote:
           | My brain immediately jumped to musical register from your
           | title, FWIW. So in my case, it worked well.
        
             | rob74 wrote:
             | Funny... after I read about the registers of (natural)
             | languages, that reminded me of the "registers" of pipe
             | organs, which are quite similar in a way: it's still the
             | same instrument, but sounds different depending on what
             | register(s) you use. Except that in English these are
             | called "stops" for some reason (as in "pull out all the
             | stops" - which in the programming sense introduced in the
             | article would mean a wild mix of programming styles,
             | probably not something you'd want to see). Oh, well...
        
             | bqmjjx0kac wrote:
             | I immediately assumed the post would discuss some algorithm
             | that rustc uses to allocate CPU registers, but I was
             | puzzled because I thought that would be abstracted away by
             | LLVM.
        
             | karmakaze wrote:
             | I first thought CPU register, ruled it out and then vocal
             | registers, and finally formal speech registers in some
             | foreign languages.
        
       | satvikpendem wrote:
       | The author mentions a pattern emerging, and I do too, which, as
       | he mentions, motivates keyword generics, but perhaps we should go
       | all the way and have full algebraic effects in Rust? I know OCaml
       | 5 has them, one of the first, so perhaps Rust might adopt
       | something similar. Then again, I'm not sure how it'd work with
       | the borrow checker.
        
         | zozbot234 wrote:
         | > full algebraic effects in Rust?
         | 
         | Isn't that what the "keyword generics" initiative is all about?
         | The Rust dev team seems to be quite aware that algebraic
         | effects in Rust might be desirable, but coming up with a good
         | design might involve quite a bit of work. It took a long time
         | for even the async MVP to shape up properly, and supporting
         | full effects might be even more complicated.
        
       | nazka wrote:
       | Every time withoutboat drops something it's crazy. I don't know
       | how people can know all that and have the intuition of it. Hard
       | not to be a fanboy of the Rust community. :)
       | 
       | Awesome post! I hope things like that will move forward.
        
       | ezekiel68 wrote:
       | I'm still only really a rust dabbler, but I was very happy to see
       | your blog, boats. I always found your writings, talks, and online
       | meeting contributions to be very thoughtful when you were more
       | involved. I hope the current leadership team will reach out to
       | you from time to time, as you offered at the end of this piece.
        
       | zabzonk wrote:
       | i really don't like the "f"s in that font in the section titles.
       | every time i came across one, it brought my reading to a
       | juddering stop.
        
         | dang wrote:
         | I completely understand the feeling but the site guidelines ask
         | us not to convert such feelings into HN posts:
         | 
         | " _Please don 't complain about tangential annoyances--e.g.
         | article or website formats, name collisions, or back-button
         | breakage. They're too common to be interesting._"
         | 
         | https://news.ycombinator.com/newsguidelines.html
        
         | withoutboats3 wrote:
         | I like the f's a lot actually but I think there's a clear
         | problem with the spacing when a title is two lines, and the f's
         | really exacerbate it. But I also don't want to fiddle with my
         | CSS.
        
         | Narishma wrote:
         | Use the reader mode of your browser.
        
       | jenadine wrote:
       | That mean even more colours for our functions?
        
       | munificent wrote:
       | This is an excellent, very insightful post.
       | 
       | When Erik Meijer worked with Gilad Bracha and others on the Dart
       | team to bring async to Dart, he approached with a very similar
       | "lets look at the table of all the combinations and make sure we
       | didn't leave any holes". In this case, the two axes (effects) he
       | considered were asynchrony and iteration. So Dart supports all
       | four combinations:
       | 
       | * Synchronous single-value functions are just normal function
       | declarations. Within one, you use `return` to yield the one
       | value.
       | 
       | * Synchronous multi-value functions are generators, marked `sync
       | _`, which return a `Iterable <T>`. Within one, you use `yield`
       | and `yield_` to emit values.
       | 
       | * Asynchronous single-value functions are marked `async` and
       | return a `Future<T>`. Within on, you use `await` to pause on
       | asynchronous operations and consume values. A `return` valued is
       | implicitly wrapped in a future.
       | 
       | * Asynchronous multi-value functions are marked `async _` and
       | return a `Stream <T>`. Within one, you can use both `yield` and
       | `yield_` to emit values and `await` to suspend and consume
       | asynchronous values.
       | 
       | We also have an asynchronous `await for` statement that can be
       | used to imperatively consume a stream.
       | 
       | There's no third axis for fallibility, because Dart chooses to
       | comprehensively use exceptions for operations that fail (which I
       | quite like).
       | 
       | Overall, it's a really rich, comprehensive approach to the
       | problem. I have mixed feelings about it. It really does cover all
       | the bases. But, in practice, `async _` functions and `await for`
       | are_ very* rarely used but add a _lot_ of complexity to the
       | language and engineering burden to the implementations.
        
         | couchand wrote:
         | > There's no third axis for fallibility, because Dart chooses
         | to comprehensively use exceptions for operations that fail
         | (which I quite like).
         | 
         | Can you catch exceptions? Can you catch them when thrown
         | iterating an Iterable, awaiting a Future, or iteratively
         | awaiting values from a Stream?
         | 
         | It doesn't seem like you can get around needing fallibility.
         | What if I have an asynchronous operation that can fail? What if
         | I need a sequence of possibly-empty values?
        
           | munificent wrote:
           | As klodolph says, there's no axis for fallibility because the
           | language doesn't offer different _choices_ of fallibility
           | strategy. There 's just one: exceptions.
           | 
           | You can catch exceptions. If an iterator throws, you can
           | catch that by surrounding the for loop in a try catch block.
           | 
           | Futures are sort of like Result types in that a Future can
           | complete with either a value or an error. Exceptions inside
           | asynchronous functions are automatically caught and wrapped
           | into error futures, which then propagate out through the
           | returned future object. When you await a future, if the
           | future completes with an error, that then gets unwrapped back
           | into a thrown exception.
        
             | steveklabnik wrote:
             | > Futures are sort of like Result types in that a Future
             | can complete with either a value or an error.
             | 
             | Incidentally, for curious readers, the first version of the
             | Future trait in Rust always returned a Result<T, E> from
             | its poll method. The second version decided to instead
             | return T directly, since T could be Result<T, E> too,
             | making things a bit more general, but also leading to a
             | tiny bit of type tetris.
             | 
             | Doesn't mean that I'm saying anything about whatever Dart
             | does here, just that I also think there's a connection here
             | :)
        
           | klodolph wrote:
           | > It doesn't seem like you can get around needing
           | fallibility.
           | 
           | There's no axis for fallability because all operations are
           | fallible. Yes, you can catch exceptions when iterating,
           | awaiting, or iteratively awaiting. You have fallibility. What
           | you don't have is a way of marking operations as non-
           | fallible.
        
           | satvikpendem wrote:
           | If you use something like fpdart, you have the more
           | functional Either type (called Result in Rust).
           | 
           | https://pub.dev/packages/fpdart#eitherlibsrceitherdart
        
         | withoutboats3 wrote:
         | Thanks for the nice comment.
        
           | howinteresting wrote:
           | Hi Saoirse, I've admired you for a long time. Thanks for all
           | you've done and this blog post, which I emphatically agree
           | with.
        
         | saurik wrote:
         | I believe you can use a backslash to escape stars, but either
         | way: it took me a while to realize there were a ton of missing
         | stars in this comment that has been parsed as italics (in case
         | this doesn't get fixed before the edit window times out).
        
           | munificent wrote:
           | Oops, sorry about that.
           | 
           | Still waiting for the day that HN supports Markdown for
           | inline code. :(
        
           | Jtsummers wrote:
           | \*       **
           | 
           | Either one works to get an * into your non-code block text.
        
         | Serow225 wrote:
         | Now I'm interested to make the chart to compare that list to
         | C#, given the common Erik influence/heritage :) It has
         | IAsyncEnumerable now
        
       ___________________________________________________________________
       (page generated 2023-03-08 23:01 UTC)