Hacker News new | ask | show | jobs
by wtetzner 1954 days ago
> Turned out, strings are not that cheap to clone if all you have is a bunch of strings.

Yeah, if you're doing a lot of cloning, you'll probably run into performance issues at some point. A common way to solve that problem is usually to use references instead of cloning.

Of course, writing your code that way takes more work/thought/planning.

2 comments

>A common way to solve that problem is usually to use references instead of cloning.

Right. I think, we ended up with having everything from the list:

1. String 2. &str 3. Cow<str> 4. Arc<str>, for interned strings (thin Arc would be even better & there is probably a crate for this) 5. Something like owning_ref::ArcRef<Owner, str> 6. One-off tricks where you actually need to construct a new string, but don't want to really construct it (for example, for hash lookup).

#5 I think is undervalued, actually; it's amazing for "enterprise" kind of stuff where you have large trees of data you need to pass around & you don't want to use straight borrowing (like &'a Whatever) because lifetimes are too infectious. And you don't want to use Arc at every corner (like, say, Java would do, not quite, but in semantics).

My problem, though, was to explain all the nuances given that they usually have nothing to do with the "business" part of the problem somebody was solving.

> My problem, though, was to explain all the nuances given that they usually have nothing to do with the "business" part of the problem somebody was solving.

Yeah, I completely agree. A GC provides a lot of benefits in terms of clarifying the intention of business logic.

Unless, of course, performance/memory usage is an important part of your business logic, in which case Rust is exactly what you want.

Maybe I'm weird, but I find the explicit ownership, mutability and lifetime information encoded in Rust definitions very helpful at understanding a new code-base. Something that otherwise needs to be documented in comments / external documentation in Java, but most often it is missing, and then recovering such information from the code is similarly hard to recovering the types in a dynamic language.

Lack of GC in makes it harder to write but easier to read.

It gives you a lot more information, but a lot of that information is more about lower-level mechanics than "business logic". I think it really depends on what you're writing and what's important to it.
It can be actually tied pretty well to business logic. You can explicitly model some business rules, e.g. a subscription cannot exceed the lifetime of the user account, etc. Similar to how you can use static type system to prohibit invalid states. Here Rust gives more tools of this kind, than other languages.

Another one I really love is ability to destroy objects on final operation. E.g you close something and it can't be used any more. Most other languages can protect using such closed object only with runtime exceptions.

Some languages like Java don't even make a distinction between "object A is composed of B and C" vs "uses B and C" (in both cases they'd be references)

Or, to get the computational equivalent of what Java is doing (immutable, interned strings), use a Rust string interning library like what servo uses [1], or just `Arc<str>`

[1]: https://docs.rs/string_cache/