I have a proposal about library conventions and I'm not sure where is
the right place to pose it. I think that anytime there is a "default"
argument of generic type that may or may not get used, we should offer
two variants, one of which requires the Zero trait, and one of which
takes a closure. This follows precedent from many languages, including
Smalltalk, Scala, and to some extent Haskell, since in Haskell all
evaluation is lazy.
Right now, we typically either (1) only offer a version that takes
the default "by value", as with `option::get_or_default`:
fn get_or_default(self, def: T) -> T;
But I often find in practice I cannot use this because it always
evaluates `def`. Even something as simple as:
let vec = opt_vec.get_or_default(~[]);
allocates unconditionally. I would prefer:
fn get_or_default(self: def: &fn() -> T) -> T;
The only case where I think this pattern is really useful is
something like:
let is_true = opt_bool.get_or_default(false);
let count = opt_counter.get_or_default(0);
Under my proposal, we would have:
fn get_or_default(self, def: &fn() -> T) -> T;
fn get_or_zero(self) -> T; // where T:Zero
Then you could write:
let vec = opt_vec.get_or_default(|| ~[]);
let is_true = opt_bool.get_or_zero();
let count = opt_counter.get_or_zero();
At worst, if the Zero default isn't what you want,
you might to write something like:
let foo = opt_bool.get_or_default(|| true);
But I think our closure syntax is lightweight enough that this
is not a big deal.
Another example is in Hashmaps, where we offer two variants on the
"find-or-insert" pattern:
fn find_or_insert(&mut self, K, V) -> Option<&V>
fn find_or_insert_with(&mut self, K, &fn(&K) -> V) -> Option<&V>
Under my proposal there would just be:
fn find_or_insert(&mut self, K, &fn(&K) -> V) -> Option<&mut V>
fn find_or_insert_zero(&mut self, K) -> Option<&mut V> // where V:Zero
Thoughts?
Niko
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev