I've since seen multiple people express that &{foo} ("option 8") is
the most appealing to them (which may or may not be confirmation bias,
given that it's also the most appealing to me). In either case, one
argument in favor of that route might be that lifetimes are (probably
by far) the most alien and intimidating part of the language, and
anything to make them more accessible is worth pursuing. So *if* there
is a consensus that "option 8" is in fact the nicest option, then it
might be worth biting the bullet. If it were any other part of the
language, I'm not sure, but here if whitespace dependency is the
price, it might be worth the sacrifice.(That said, I agree that &'foo is also better than the current syntax.) On Wed, Jan 23, 2013 at 4:39 AM, Benjamin Striegel <[email protected]> wrote: > Sadly, you should really read this subsequent blog post: > > http://smallcultfollowing.com/babysteps/blog/2013/01/15/lifetime-notation-redux/ > > It turns out that this syntax is ambiguous without introducing a whitespace > dependency. I think it might still be worth it, but I know that a lot of > people tend to shy away from such things on principle. > > > On Tue, Jan 22, 2013 at 2:01 PM, Dean Thompson <[email protected]> > wrote: >> >> Looking at Niko's blog post >> >> >> http://smallcultfollowing.com/babysteps/blog/2012/12/30/lifetime-notation/ >> >> We do, to my eye, get a huge improvement if we both tweak the notation and >> also augment the ref deconstruction syntax to indicate the resulting >> pointer >> timeline. >> >> Doing this with Niko's preferred option 8 gives us: >> >> pure fn each(&self, f: fn(&(&{self}K, &{self}V)) -> bool) { >> match *self { >> Leaf => (), >> Tree(_, ref{self} left, ref{self} key, >> ref{self} maybe_value, ref{self} right) => { >> left.each(f); >> match *maybe_value { >> Some(ref{self} value) => { >> f(&(key, value)); >> } >> None => () >> }; >> right.each(f); >> } >> } >> >> >> FWIW, Niko's ${foo}bar notation helps my mental "parser" a great deal, >> because it >> makes foo look like a modifier to me. When I see &foo/bar, my mind fights >> to make >> it a pointer to foo with a strange trailing bar. >> >> Dean >> >> >> On 1/22/13 9:23 AM, "Graydon Hoare" <[email protected]> wrote: >> >> >On 22/01/2013 6:55 AM, Dean Thompson wrote: >> > >> >> I'm looking at some code that Niko Matsakis updated in >> >> https://github.com/stevej/rustled/commits/master/red_black_tree.rs >> >> >> >> pure fn each(&self, f: fn(&(&self/K, &self/V)) -> bool) { >> >> match *self { >> >> Leaf => (), >> >> Tree(_, ref left, ref key, ref maybe_value, ref right) => { >> >> let left: &self/@RBMap<K,V> = left; >> >> let key: &self/K = key; >> >> let maybe_value: &self/Option<V> = maybe_value; >> >> let right: &self/@RBMap<K,V> = right; >> >> left.each(f); >> >> match *maybe_value { >> >> Some(ref value) => { >> >> let value: &self/V = value; >> >> f(&(key, value)); >> >> } >> >> None => () >> >> }; >> >> right.each(f); >> >> } >> >> } >> >> } >> >> >> >> I understand this code reasonably well. I greatly value the attention >> >> to safety in Rust, and I appreciate the value of pointer lifetimes in >> >> maintaining that safety. >> >> >> >> My gut reaction, though, is that this code is almost as intimidating >> >> as Haskell. Even more worrisome to me, I think most mainstream >> >> programmers would find the *explanation* of this code intimidating. >> > >> >I agree that the cognitive load on this code sample is high. This is the >> >main risk we took (aside from "potential unsoundness", which I didn't >> >really think to be a big risk, judging from Niko's comfort with the >> >semantics) when adopting first class region pointers: that the resulting >> >types would be too complex to understand, and/or require too much >> >chatter when writing out in full. >> > >> >To my eyes the matter is not yet entirely clear. It's complex but it's >> >not quite "impossibly complex"; if you made all the '&self/' symbols >> >into just '&' it would be, I think, not so bad. Compare if you like to >> >the associated bits of code from libc++ required to implement >> >roughly-equivalent "iterate through the treemap" sort of functionality: >> > >> > >> >_LIBCPP_INLINE_VISIBILITY >> >__tree_iterator& operator++() { >> > __ptr_ = static_cast<__node_pointer( >> > __tree_next( >> > static_cast<__node_base_pointer>(__ptr_))); >> > return *this; >> >} >> > >> >template <class _NodePtr> >> >_NodePtr >> >__tree_next(_NodePtr __x) _NOEXCEPT >> >{ >> > if (__x->__right_ != nullptr) >> > return __tree_min(__x->__right_); >> > while (!__tree_is_left_child(__x)) >> > __x = __x->__parent_; >> > return __x->__parent_; >> >} >> > >> >template <class _NodePtr> >> >inline _LIBCPP_INLINE_VISIBILITY >> >bool >> >__tree_is_left_child(_NodePtr __x) _NOEXCEPT >> >{ >> > return __x == __x->__parent_->__left_; >> >} >> > >> >template <class _NodePtr> >> >inline _LIBCPP_INLINE_VISIBILITY >> >_NodePtr >> >__tree_min(_NodePtr __x) _NOEXCEPT >> >{ >> > while (__x->__left_ != nullptr) >> > __x = __x->__left_; >> > return __x; >> >} >> > >> >And keep in mind that there is no memory-safety in that code: if I >> >invalidate a C++ map while iterating, I just get a wild pointer >> >dereference and crash. If I rewrote it in terms of shared_ptr<> it'd be >> >even chattier. >> > >> >> Who is our target audience for Rust? Graydon has said it is >> >> "frustrated C++ developers", but how sophisticated and how "brave" >> >> are we thinking they will be? >> > >> >The target audience is frustrated C++ developers, same as always. If >> >they balk at the syntax for lifetime-bounds on borrowed pointers, then >> >yes, we've blown the cognitive budget, and have failed. >> > >> >It is not clear to me yet that that's true. But it's a risk. One we're >> >all aware of and worried about. >> > >> >> How intimidating do we think Rust is today? Am I just overreacting >> >> to unfamiliarity? >> > >> >I don't know. It's a very hard thing to measure. I know of lots of >> >languages that have failed for this reason. It's a major hazard. >> > >> >> How can we calibrate our "intimidation factor" before language >> >> decisions start getting harder to change? >> > >> >If you search our mailing list, IRC logs or meeting minutes for >> >"cognitive budget", "cognitive load" or "cognitive burden" you will see >> >we have always been keenly aware of this risk and treat it as a primary >> >constraint when doing design work. It's a leading reason why many >> >features have been removed, simplified, minimized or excluded from >> >consideration. >> > >> >> Do we want (and is it feasible) to define a simpler subset of the >> >> language that beginners are encouraged to stick to and that most >> >> libraries don't force clients away from? >> > >> >Personal opinion: no. That just makes the issue even more confusing. The >> >way to approach this is head-on, by looking at the things that cause the >> >most confusion and trying to make them cause less. >> > >> >Thanks for bringing this up. I'm interested to hear others' opinions on >> >whether we're past a reasonable limit of comprehensibility. It's a hard >> >thing to hear, but better to hear now than later, if true. >> > >> >-Graydon >> > >> >_______________________________________________ >> >Rust-dev mailing list >> >[email protected] >> >https://mail.mozilla.org/listinfo/rust-dev >> >> >> _______________________________________________ >> Rust-dev mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/rust-dev > > > > _______________________________________________ > Rust-dev mailing list > [email protected] > https://mail.mozilla.org/listinfo/rust-dev > -- Your ship was destroyed in a monadic eruption. _______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
