I think convention (snake case for function names) suggests get_foobar ; but I am increasingly thinking that get_FooBar makes more sense.
Anyone with strong opinions on this ? (Either direction is fine; but please keep it polite; and definitely do not accuse people of wanting to "fork the rust compiler" ).
But you wouldn't use get either. That's usually for when the method name would otherwise not work and there's no meaningful name to use, like fn get(&self) or fn get_1(&self).
// If FooBar is a member of Dog
pub fn foo_bar(&self) -> &FooBar
// If FooBar can be constructed from Dog
pub fn to_foo_bar(&self) -> FooBar
// If FooBar is a representation of Dog (like AsRef)
pub fn as_foo_bar(&self) -> &FooBar
// If Dog can be converted to FooBar (like From/Into)
pub fn into_foo_bar(self) -> FooBar
There's some wiggle room here, but you wouldn't use get or non-snake-case.
You might also forgo this method completely and use AsRef<FooBar> or From<Dog> for FooBar. No case issues with those.
I'm not sure I agree with this. I think of Struct names as a single token. Adding "_" and changing it to lower case, when it appears in a function name, seems somewhat arbitrary.
FooBar is two words: a capital letter begins a new word in CamelCase. Converted to snake_case it is indeed foo_bar (that would be the name of the type as well if type names were snske_case as is common in eg. C). You might not agree but that’s the documented convention in Rust. For instance, AsRef has a method called as_ref, not asref.
(Numbers are an interesting edge case; would, say, Vec3d be vec_3d or vec3d snake_cased? I’d weakly prefer the latter, but it could go either way.)
The return type already appears in the function signature, so there isn't a great need to repeat it verbatim in the name. Given that, something like generate_connection_graph just is more pleasant to read than generate_ConnectionGraph.
Another way of thinking of it: both struct FooBar and fn foo_bar() embody the concept of "foo bar". From this perspective, both are inheriting a name from the concept and not from each other.
I see the casing as the kind, while the words themselves are the idea.
I don't think we can speak of name formatting as making more or less sense. It's pretty arbitrary and the compiler does not care. We can however talk of consistency and conventions.
As such I have a number of objections to your suggestion:
If we made the rules that:
a) All type names are to be coloured pink
b) All function names are to be coloured blue.
Then clearly your "get" function would be coloured blue. Making it half pink and half blue, the equivalent of your suggestion, would break rule b).
"get_FooBar" suggests getting the type "FooBar". But you don't want the type definition, which would be "pub struct FooBar{...}", you want an actual instance of FooBar with some actual data in it not just a type.
All of which makes more "sense" to me.
How ugly and confusing do you want to make your code?
Yes, arbitrary. Could have been the other way around. Could have been something different. As I said, the compiler does not care.
But any other suggestion, including yours, is also arbitrary.
"FooBar" is a name of a type. Your function does not return the name of a type or the description of the type. It returns actual data of type FooBar. That is a different thing. So all is well with "get_foobar".
What if your get function could fail? Would you call your get function:
FooBar is a type name, you don't need to repeat a type name verbatim in a function name. if you insist the type name FooBar must appear at the call site, you can just (ab-)use type parameters.
e.g. instead of
let foobar = dog.get_FooBar();
you can make it
let foobar = dog.get::<FooBar>();
//or
let foobar = FooBar::get_from(&dog);
convention is always arbitrary, and what makes sense is always subjective, so you choose what you like. this is a non-problem to begin with. just remember to be consistent, otherwise future self will hate you.
The naming convention should be simple and easy to understand. I don't think there is any way to mix snakes and camels without making the rules complex and with lots of gray areas to argue over.
Recently, clippy told me that acronyms in type names should also be cameled, like Dna or Rna, which looks weird, but at least there is simple consistency.
I have a similar complaint about some of Rust std naming. BTreeSet and BTreeMap APIs don't expose anything related to B-trees in particular, they could be implemented as red-black trees. They should be called OrderedSet and OrderedMap.
BinaryHeap's API doesn't expose whether it's binary or a heap. It should be called PriorityQueue.
I'd even go as far as to say that Hash doesn't have anything to do with hashing (that's Hasher's job). Its job is to convert a data structure into a stream of bytes, so it should be called Serialize or something like that (and indeed, notice how serde's Serialize trait is similar to Hash, and Serializer to Hasher).
And similarly HashMap should be called simply Map (or UnorderedMap).
The name XMLHttpRequest is worse in that it suggests an API property that isn't true: one might think it requires the content to be XML, but in fact you can use it for other content, too.
With regards to std collections, I imagine there are performance characteristics, too. I've been assuming that hash-based collections are more optimized for larger collections. Also, maybe in the future, we might add more collections.
In my mind, Hash and Serialize are quite different. Hash should be something that can be quickly turned into a number that is always the same, while Serialize means it can be turned into something that represents its entire information.
Well yes -- BTreeMap (aka "ordered map") has to maintain an ordering, whereas HashMap (aka "unordered map") doesn't, so the latter can be faster. It's already implied by the "ordered" adjective.
Hash implementations don't compute the hash. Hash converts anything into a stream of bytes (more-less) that is supposed to represent its relevant data. Then a Hasher implementation takes that stream of bytes and turns it into a number according to some hashing algorithm. So Hasher is the right name, but Hash is basically a serialization trait, it doesn't involve any hashing.