Re: [rust-dev] rustpkg, package identifiers, filename conventions
:-) Ok -- that's quite a convincing argument against Python! My experience with it is casual. However, I still believe the following: - Rust should have a standard build tool that is able to handle complex cases. - This build tool needs a programming language. - This programming language should not be Rust (to avoid the complexity of recursive builds) and indeed should be interpreted. Any similarly convincing arguments against those beliefs? Dean On 2/20/13 7:31 AM, d...@ucore.info d...@ucore.info wrote: On Wed, Feb 20, 2013 at 2:50 PM, Dean Thompson deansherthomp...@gmail.com wrote: My suggestion: Python. Please. Not Python. Everything but not this. I admit: I hate Python with passion, so I may be biased. I hate not so much the language itself but all it's tooling and constant problems with it and people constantly putting it everywhere because the only language they grasp or assume everyone else should know it to. (No intention to offend the original poster, it's just a fact of life that Python is quite easy to learn and university courses often pick it and ,,when hammer is all you got, everything looks like a nail''. In 2011, I've spent 2 weeks rewritting (removing or decoupling, really) the `scons`-based build system that was meant to be flexible, powerful, fast, easy to use, with interactive features, etc.. An in reality it was unmaintenable, complex, big and slow and the 3rd-party components used to build it were becoming abandoned. Python : * Is not designed for handling dependencies from groundup like eg. `make`. So it needs some custom foundation code to handle it, probably with 3rd party dependencies. * Is not really efficient for gluing external tools like shell scripts are. * Is not solid (things break in runtime, and many times just because newer minor Python version came out). * It's not providing support for ancient tools like autotools, neither Rust needs this, as there will be no legacy software using Rust yet. Besides I don't understand why normal projects in Rust would require anything more to be built other than: rustc main.rs or something similarly simple. As long as Rust building system support the mentioned escape hatch, with complex project people will be able to build using any complex logic they like, written in any language, using any 3rd-party software they choose. For 99.9% mainstream projects though any simple solution will be fine, and the less potential problems and dependencies it introduces, the best for all of us. Imagine the scenario: Why did this Rust package failed to build? Some weird Python error... . Should I use different version of Python? Which one: 1.x, 2.5, 2.6, 2.7, 3.x, 4.x, 5.x ? Because programs breaks randomly (in runtime!) between Python versions. Must I use `virtualenv` (or what's the current/best version of this idea ATM)? Are all the pips installed and configured correctly? Maybe one of these many funny python environment varibles is wrong for some reason... ? So let's not import Pythons problems into Rust world. Regards, -- Dawid Ciężarkiewicz ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Lifetime notation
I expect it would, but at the expense of no longer being able to make as simple a statement in the language tutorial as this: The notation 'foo means a lifetime called foo. To me, it seems nicer for a newbie to wonder how is that lifetime being used? than to wonder what's that thing after the dot? Dean From: Ziad Hatahet hata...@gmail.com Date: Thursday, January 31, 2013 6:53 AM To: Benjamin Striegel ben.strie...@gmail.com, Niko Matsakis n...@alum.mit.edu Cc: rust-dev@mozilla.org rust-dev@mozilla.org Subject: Re: [rust-dev] Lifetime notation Would using a dot '.' instead of a quote ' also resolve the ambiguity, without introducing an extra sigil into the language? {.lt}T T{.lt} -- Ziad On Thu, Jan 31, 2013 at 6:33 AM, Benjamin Striegel ben.strie...@gmail.com wrote: +1 to this. Option 8 was always the best-case syntax, and prefixing an apostrophe on lifetime names is entirely inoffensive. On Thu, Jan 31, 2013 at 8:58 AM, Niko Matsakis n...@alum.mit.edu wrote: Interesting. That would indeed address the ambiguity issue. Niko Sanghyeon Seo wrote: UtherII on Reddit /r/rust suggested an idea I like: {'lt} T T{'lt} Basically option 8 of http://smallcultfollowing.com/babysteps/blog/2012/12/30/lifetime-notation/ http://smallcultfollowing.com/babysteps/blog/2012/12/30/lifetime-notation/ with ' from https://mail.mozilla.org/pipermail/rust-dev/2013-January/002942.html https://mail.mozilla.org/pipermail/rust-dev/2013-January/002942.html This does need a lookahead but as far as I can tell unambiguous and manageable. More on: http://www.reddit.com/r/rust/comments/17ka3b/meeting_weekly_20130129_region_ syntax_impl_type/c86t7wg http://www.reddit.com/r/rust/comments/17ka3b/meeting_weekly_20130129_region _syntax_impl_type/c86t7wg ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Lifetime notation
On 1/31/13 12:56 PM, Malte Schütze malte.schue...@fgms.de wrote: I really prefer Foo{'lt}X,Y over Foo'ltX,Y - the former makes it visually clearer to me where each section of the declaration starts and ends. The non-curly choice is Foo'lt,X,Y. How does that grab you? Dean ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Lifetime notation
Makes sense. One counter point though, which I find more persuasive: the more common case by far is surely a single lifetime parameter and a single type parameter. In which case Foo'lt,X seems less noisy than Foo{'lt}X. Having said that, Graydon gently invoked BDFL rights to push against using the curlies. :-) So that ship has presumably sailed. On 1/31/13 1:37 PM, Malte Schütze malte.schue...@fgms.de wrote: On 01/31/2013 09:58 PM, Dean Thompson wrote: On 1/31/13 12:56 PM, Malte Schütze malte.schue...@fgms.de wrote: I really prefer Foo{'lt}X,Y over Foo'ltX,Y - the former makes it visually clearer to me where each section of the declaration starts and ends. The non-curly choice is Foo'lt,X,Y. How does that grab you? Dean I'm worried that it might be confusing to read when it becomes longer. Foo'lt,X,Y still is readable, but Foo'lt,'xy,X,Y,Z isn't anymore. Having it in curly braces (Foo{'lt,'xy}X,Y,Z) breaks it down in smaller parts and makes it easier to understand in my opinion. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] intimidation factor vs target audience
It just occurred to me that the 'lt syntax for lifetimes does (I think) provide an unambiguous way keep the pointed-to type right next to the sigil: 'ltT Here, the usual sigil becomes 'lt, which taken together is a prefix on the type T. In this notation, there is still a clear distinction between Niko's examples below, which become 'bT 'bT I'm not sure whether I like it better or worse than the prevailing alternative 'bT (with the opposite meaning!) 'b T I believe it does address James Boyden's goals (below) 2a and 2b, although not 2c, and this issue is orthogonal to 2d. Since I resonate with 2a and 2b myself, I lean toward thinking I like this alternative approach a little better. Dean James Boyden had written: For the above reasons, is there any way that the lifetime syntax could be moved *after* the type? The current proposal of `'lt Foo` does address the ambiguity described in point 2b, but not 2a or 2c. (The `/` sigil itself actually doesn't faze me that much.) Niko Matsakis had written: We considered this, but it's very hard to mix prefix and postfix notation like this without ambiguity. Consider: T/b Is this: 'b T or 'b T I suppose we could just resolve it arbitrarily, like if-else-if chains. More completely (for reference), James Boyden had written: For what it's worth, here's my 2 cents: 1. Borrowed pointer lifetimes are a very interesting concept. I think they definitely enrich Rust. However... 2. The current syntax of `lifetime/type` completely threw me when I first saw it in the wild (before reading up on the topic in the tutorials). I'm concerned that this could be something that might push Rust slightly too far towards obscure academic theory language for many C++ programmers. Specifically: 2a. I'm used to seeing the pointed-to type right next to the pointer. I can mentally reverse C++'s `int p` to `p: int` without problems, but having extra line-noise in there seems to stretch my on-the-fly language-parsing capability beyond its limits -- particularly so when the identifiers both before and after the `/` look like types, and there's no whitespace breaks to guide my mental tokeniser. 2b. I found the `p: r/float` syntax especially confusing in that sometimes, without any prior or intervening warning, the next token after the borrow-pointer sigil `` was a lifetime instead of a type (but of course, not all the time). When you're mentally parsing it, you don't get any explanation of what you're reading until *after* you've read those tokens. 2c. I care more about the pointed-to type than the lifetime (at least on my first scan through the function parameters), so I'd strongly prefer to have the pointed-to type closer to the front, and closer to the parameter name and pointer sigil (i.e., before the lifetime name). This has the additional benefit that now all the parameter type info is together, followed by the lifetime info. 2d. `` means pointers or (occasionally) bitwise-AND. Please don't use it for any other plumbing! (I'm thinking of Lifetime parameter designated with in the previous notation.) For the above reasons, is there any way that the lifetime syntax could be moved *after* the type? The current proposal of `'lt Foo` does address the ambiguity described in point 2b, but not 2a or 2c. (The `/` sigil itself actually doesn't faze me that much.) ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] intimidation factor vs target audience
Alexander, Thanks that's a good exercise! Niko has indicated that the sequences like this: Some(ref value) = { let value: self/V = value; are working around a current bug in ref. The let should be unnecessary. All in all, my feeling after trying to understand the code is that it is too verbose, and that especially the 'self/' thing should be in some sort of type inference part of the compiler. Yes, the Rust team is trying to balance good defaults with allowing the programmer to exercise control when needed. Here's a good stream-of-consciousness blog post from Niko exploring the options: http://smallcultfollowing.com/babysteps/blog/2013/01/15/lifetime-notation-re dux/ I'd be interested in how you react to the syntax Niko is currently experimenting with: 'lt Foo Foo'lt In this syntax, a lifetime named foo is always written as 'foo. Dean From: Alexander Kjeldaas alexander.kjeld...@gmail.com Date: Thursday, January 24, 2013 2:10 AM To: Graydon Hoare gray...@mozilla.com Cc: rust-dev@mozilla.org Subject: Re: [rust-dev] intimidation factor vs target audience On Tue, Jan 22, 2013 at 6:23 PM, Graydon Hoare gray...@mozilla.com 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/@RBMapK,V = left; let key: self/K = key; let maybe_value: self/OptionV = maybe_value; let right: self/@RBMapK,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: And with this clue, I think I can jump into the discussion because I know *nothing* about the semantics you are discussing. This is my wild guess at what is happening in this function, and what is not obvious, line by line: pure fn each(self, f: fn((self/K, self/V)) - bool) { There is some difference between and 'ref', but they are both some sort of reference. 'fn' is a callback function that takes a tuple with the key and value. The self/K syntax is impossible to understand, but given your clue that I could just assume it doesn't exist, I will guess that self/K means that the lifetime of K is somehow bound to self, so that the callback function must copy K and V if they should be retained. I am pretty familiar with the concept of alias analysis in a compiler. It is not obvious why there is a 'self/' instead of 'self/' though. match *self { I'm not sure why we need *self here, but it looks like dereferencing so we're matching on the structure of the tree. Leaf = (), Tree(_, ref left, ref key, ref maybe_value, ref right) = { As I said earlier, why this is 'ref' and not '' is not clear, but it is obvious that they are both some kind of reference. let left: self/@RBMapK,V = left; let key: self/K = key; let maybe_value: self/OptionV = maybe_value; let right: self/@RBMapK,V = right; The above is sort of straight forward, but I am a little disappointed that the self/ stuff isn't inferred, given that we have f((key, value)) below. I mean, if my intuition on self/ is correct, then in Haskell at least, the 'self/' part of the 'key' and 'value' would be inferred by the compiler because of the restriction in the type of 'fn'. left.each(f); This tells me that the first parameter to the function is special. I am not sure whether each(left, f) would be valid or not. match
Re: [rust-dev] intimidation factor vs target audience
Benjamin Striegel writes: Sadly, you should really read this subsequent blog post: http://smallcultfollowing.com/babysteps/blog/2013/01/15/lifetime-notation-r edux/ Ok, here's another suggestion: pure fn each/f/(self, f: fn((/f/K, /f/V)) - bool) { ... } Lifetimes are always written in slashes. We drop the convention of using a /self/ lifetime. We require the explicit lifetime parameter on the function, to minimize magic. --- struct StringReader/s/ { value: /s/str, count: uint } struct Foo/f/, T: Reader+Eq { value: /f/T, count: uint } We treat the lifetime as a type parameter, in We stick to requiring that it be explicit on the struct and the field, to minimize magic. I believe this meets Niko's goal of recognizing lifetimes in the parser. - struct RefPair/fst/, /snd/, T { first: /fst/T, second: /snd/T } Multiple lifetime parameters on a struct work fine. It is clear both to the human reader and to the parser that /snd/ is another lifetime while T is a type. - impl StringReader { fn new/f/(value: /f/str) - StringReader/f/ { StringReader { value: value, count: 0 } } } fn value/f/(s: /f/StringReader/f/) - /f/str { return s.value; } Lots of characters, yes, but the author of the code is intentionally exercising great control, so I feel it is worth spelling out what is going on. To my eye, the consistency of always writing the lifetime in the same way, /f/, helps tie the mentions of it together. Although /f/str is less concise than today's syntax f/str, I feel that /f/str alerts the C++-trained reader that something special is going on, and perhaps even suggests that f is a modifier of some kind. --- fn remaining(s: StringReader) - uint { return s.value.len() - s.count; } Here, the author has chosen to exercise less control. We default to scoping the lifetimes across the function declaration. --- It's a thought! Dean ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] intimidation factor vs target audience
Lol I like 'lt Somehow it makes me laugh compared to the ML usage, but I like it. Perhaps it plays off my brain's wiring for reading something like I think 's are pretty. (Or for reading brain's, for that matter.) I like the {lt} approach ok, too, although not as much. I hadn't noticed that the ambiguity in your original Option 8 went away when we put the lifetime in the angle brackets, even if we then used curlies. But yeah, it feels heavier. Dean From: Niko Matsakis n...@alum.mit.edu Date: Wednesday, January 23, 2013 1:44 PM To: Dean Thompson deansherthomp...@gmail.com Cc: rust-dev@mozilla.org Subject: Re: [rust-dev] intimidation factor vs target audience Dean Thompson wrote: Personally, though, I find myself increasingly attracted to the idea of having a consistent notation for writing a lifetime everywhere one appears, independently of the symbol. (/lt/ is the only such notation I've found yet that seems reasonable.) I like this idea too, I just don't like /lt/ for that role. Maybe `'`? (shades of ML) 'lt Foo Foo'lt That actually doesn't look half bad to me. Maybe `.`? .lt Foo Foo.lt I don't like Foo.lt, but .lt Foo and Foolt might be ok, though it doesn't adhere to the principle (in that lifetime names are just like any other identifier). Another option: {lt} Foo Foo{lt} But the latter form feels pretty sigil heavy. Niko ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] intimidation factor vs target audience
I am new to Rust, but quite excited about it. I have read most of the docs carefully. 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/@RBMapK,V = left; let key: self/K = key; let maybe_value: self/OptionV = maybe_value; let right: self/@RBMapK,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. 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? (I'd like to think of myself as a team member who is just getting started, so while deferring to the senior folks, I'll say we.) How intimidating do we think Rust is today? Am I just overreacting to unfamiliarity? How can we calibrate our intimidation factor before language decisions start getting harder to change? 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? Dean Dean Thompson https://github.com/deansher ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] intimidation factor vs target audience
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 gray...@mozilla.com 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/@RBMapK,V = left; let key: self/K = key; let maybe_value: self/OptionV = maybe_value; let right: self/@RBMapK,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