In Rust, is there any reason at all to make a Option<Vec<Thing>> instead of a Vec<Thing> if the semantics of "None" here just mean "there are no Things"? Like if you create and never populate an empty vec that's never gonna allocate on the heap right?
I guess one way of looking at it might be that Option<Vec<>> might be taking a small performance hit in exchange for the ability to catch None via match {}, but that probably is only ergonomics
@mcc Vec::new()
does not allocate, the inner pointer is set to a dangling pointer so there's no cost creating one
though a vec being zero length doesn't necessary mean it hasn't allocated, if you remove all elements from a vec it'll keep its previous capacity
@rini sure, but my wording was "create and never populate". these vecs are never mutable after creation
@mcc but in your case checking .len() == 0
is the same operation as checking if an Option
is None
, plus I think it might add a word in size for the enum discriminator (this optimization isn't very well defined in rust)
@mcc yeah i think this only makes sense if you want to distinguish a present empty vector from a missing vector, e.g. if you want to distinguish JSON values like `{}` from `{"key": []}`
@fullyabstract @d6 Rust would do this a different way, things can be wrapped both in Option<T> (to indicate "this is absent, as is expected to sometimes be the case") or Result<T, E> (to indicate "something went wrong, and the attached E will detail a specific way in which something went wrong, such as 'element missing')
@mcc things get interesting when you encode those into bytes e.g. ASN.1, send those bytes to a remote host whose interpretation of "semantic" differs.
For the younger readers, replace ASN.1 by cbor.
@buherator @mcc This is exactly why I want to throw every API developer who returns a 4XX from a query with zero returned records into the ocean