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