Live data from Hacker News

Thoughts on Rust, a few thousand lines in

rcoh.me

81–90 of 183 posts

Re: Thoughts on Rust, a few thousand lines in

#81

Earlier quoted context omitted.

Every string is checked. But UTF8 is a multi-byte encoding, and slicing works per bytes, so you if you slice in the middle of a multi-byte character, you may get nonsense. The error happens because of this checking, not in spite of it. String always assumes full UTF-8. You could make an AsciiString type if you wanted, but it's not provided by the standard library.

The obvious follow up question would be: so why is slicing a string a byte-wise operation and not a character-wise operation? If a string is an array of characters, why does it let me refer to individual bytes without explicitly casting it to a byte array? How often comparatively do you want the nth byte compared to the nth character? I would suspect that's pretty rare.

As stated below, indexing is an O(1) operation, and that is a O(n) operation.

> If a string is an array of characters

It is not, it is an array (technically vector) of bytes.

Re: Thoughts on Rust, a few thousand lines in

#82

Earlier quoted context omitted.

Every string is checked. But UTF8 is a multi-byte encoding, and slicing works per bytes, so you if you slice in the middle of a multi-byte character, you may get nonsense. The error happens because of this checking, not in spite of it. String always assumes full UTF-8. You could make an AsciiString type if you wanted, but it's not provided by the standard library.

The obvious follow up question would be: so why is slicing a string a byte-wise operation and not a character-wise operation? If a string is an array of characters, why does it let me refer to individual bytes without explicitly casting it to a byte array? How often comparatively do you want the nth byte compared to the nth character? I would suspect that's pretty rare.

> How often comparatively do you want the nth byte compared to the nth character? I would suspect that's pretty rare.

It's exactly the opposite of what you expect. Getting the nth codepoint is often (not always) semantically incorrect since a codepoint isn't necessarily one character. Multiple codepoints might combine to form one character. (In Unicode, these are called grapheme clusters.)

Byte offsets are used a ton because you might often have the index to a position in the string from some routine, like, say, a search[1].

I've been working on text related things in both Rust and Go for several years. Both languages got this part of their strings exactly right given that their representation in memory is always a sequence of bytes.

[1] - https://doc.rust-lang.org/std/primitive.str.html#method.find

Re: Thoughts on Rust, a few thousand lines in

#83

Earlier quoted context omitted.

What's the point of the [] version then? It seems inherently more dangerous, and Rust emphasizes safety. I know it wants to be pragmatic as well as safe, but this seems like a strange default.

There's a few things that come into play here: First of all, panics are perfectly safe. None of this has to do with safety guarantees. Second, the [] syntax is controlled by the Index trait, which returns an &T, not an Option . It does this due to Rust's error handling philosophy. There's two kinds of errors: recoverable and unrecoverable errors. When something shouldn't fail, unless there's a bug, you shouldn't be u…

Does Rust support a monadic coding style (like Haskell "do" blocks or F# computation expressions)? That would allow you to work with Options without having to explicitly unwrap them.

Re: Thoughts on Rust, a few thousand lines in

#84

> Unlike nearly every language I’ve ever used, Rust actually encourages variable shadowing. Haskell does it too, for the same reason/purpose / with the same effect.

F# supports it, too, although it doesn't seem very popular. Personally, I'm still on the fence and usually avoid it in practice.

Re: Thoughts on Rust, a few thousand lines in

#85

Earlier quoted context omitted.

There's a few things that come into play here: First of all, panics are perfectly safe. None of this has to do with safety guarantees. Second, the [] syntax is controlled by the Index trait, which returns an &T, not an Option . It does this due to Rust's error handling philosophy. There's two kinds of errors: recoverable and unrecoverable errors. When something shouldn't fail, unless there's a bug, you shouldn't be u…

Does Rust support a monadic coding style (like Haskell "do" blocks or F# computation expressions)? That would allow you to work with Options without having to explicitly unwrap them.

Yes, there are a bunch of methods that let you do this, though with a bit more syntax than do notation; for example, and_then is pretty much bind.

Re: Thoughts on Rust, a few thousand lines in

#86

One thing I don't like about Rust is how taking a slice of a string can cause a runtime panic if the start or end of the slice ends up intersecting a multi-byte UTF-8 char. I would prefer it if this feature didn't exist at all rather than cause runtime panics. https://play.rust-lang.org/?gist=e02ce5e9aacfee3a2b4917d5624...

Go indexes bytes on strings, even though there's a builtin type called Rune which delimits utf-8 codepoints. This is yet another footgun. Is there a language that doesn't handle this poorly? https://play.golang.org/p/CkBp0w8T621

Go allows slicing UTF8 strings just fine: https://play.golang.org/p/eUQ5L58KwZy

Re: Thoughts on Rust, a few thousand lines in

#87
post #70

Earlier quoted context omitted.

Slicing on characters is a linear time operation and indexing is meant to be cheap.

That seems like taking it too far. It's like using pointer arithmetic to index a linked list on the assumption that the nodes happen to be allocated contiguously in memory. I mean, I guess the thinking is, indexing a Unicode string isn't cheap, but indexing strings used to be cheap once upon a time, when strings were encoded in fixed one-byte-per-character representations, so let's pretend that's still the case and p…

Panics are not unsafe. Panic exists in Rust because they are safe. If you don't want a panic on index, just don't index.

Indexing into a UTF-8 string doesn't serve any reasonable consistent purpose anyway, because it is an abstraction of text that doesn't provide support to the notion that a "character" is more fundamental than a word or paragraph, etc. Rust's string slicing exists solely to make ASCII text easy to handle. If your text is not ASCII, then you shouldn't be slicing it at all. Thus the panic.

Re: Thoughts on Rust, a few thousand lines in

#88

I'm a network engineer, and I've done C++ for over a decade now. One of the nice things about Rust is that they decided to go with async over fibers, which is in line with how most high performance C++ is written. The Rust team also isn't rushing Future out the door, so it's coming along much nicer than the C++ Future, which is usually replaced because it's not monadic. Rust is great, and I highly recommend learning…

i admire you: you change your occupation every couple of days, as well as the languages you've replaced rust for :)

Re: Thoughts on Rust, a few thousand lines in

#89
One thing Rust doesn't seem to be doing very well yet is guard clauses, specifically when handling Option.

I've seen and appreciated the use of guard clauses in many languages, as a good way to quickly check for a few conditions at the top of a function, and return early if those conditions aren't met.

Since it seems that Option are recommended in Rust, there's a lot of time you want to quickly return if `Some(x)` is not here (i.e. it's `None`), and if it's here, continue through the function, without having an unnecessary indentation from an extra brackets.

There seem to be a good amount of smart discussion into handling those [1][2]. some threads are more than a year old, but it seems to be making progress.

[1] https://github.com/rust-lang/rust/issues/45978 [2] https://internals.rust-lang.org/t/pre-rfc-allow-pattern-matc...

Re: Thoughts on Rust, a few thousand lines in

#90
post #89

One thing Rust doesn't seem to be doing very well yet is guard clauses, specifically when handling Option . I've seen and appreciated the use of guard clauses in many languages, as a good way to quickly check for a few conditions at the top of a function, and return early if those conditions aren't met. Since it seems that Option are recommended in Rust, there's a lot of time you want to quickly return if `Some(x)` i…

I'm using `.ok_or(SomeError)?` which converts Option into Result and opens Ok() for the rest of the scope, short-circuiting on Err(). I know about Swift's `guard` statement, but I never had a case yet when I didn't want to return Result in such kind of code, so ok_or was working for me well.
Post reply on HN