From dteller at mozilla.com Fri Jun 1 02:59:39 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Fri, 01 Jun 2012 11:59:39 +0200 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: <4FC4E3F6.1080201@alum.mit.edu> References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> <4FBE34B3.9060102@mozilla.com> <4FC483B0.9010004@mozilla.com> <4FC4E3F6.1080201@alum.mit.edu> Message-ID: <4FC8928B.4060104@mozilla.com> On 5/29/12 4:57 PM, Niko Matsakis wrote: > This code seems wrong... what if an error occurs as part of the call to > `copy()`, for example? The idea is to simply propagate errors that take place as part of `copy`, in a ML/C++/Java/Haskell manner. [...] > In general it seems there are three classes of errors > > - globally unrecoverable (just call `fail`) > - locally unrecoverable (return a `result` type) > - recoverable (pass in handler or error reporter) > > Globally unrecoverable means that the whole task cannot continue (this > is clearly not appropriate for libraries). Locally recoverable means > that some subset of the program must abort, but some outer handler could > possibly catch it. Recoverable means that it's the sort of error where > the procedure could carry on, but the caller may still want to know > about it. These two are suitable for general purpose libraries, > depending on the case. We certainly use all three in the compiler, > though primarily the first and the third. > > This whole scheme isn't terribly composable, though. Code must be > written differently depending on whether it may abort due to errors and > so forth. This is precisely what exceptions were aiming to solve, I > suppose (Java's checked exceptions representing a kind of middle > ground). It may be that error propagation is too important to be > papered over entirely, though. Indeed, I suspect that achieving composability without sacrificing safety or performance is the big issue here. The other problem is that the function may not have enough information to determine what is "locally unrecoverable". I believe that `remove` is a good example of issues whose recoverability depend on the context. Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From dteller at mozilla.com Fri Jun 1 03:16:10 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Fri, 01 Jun 2012 12:16:10 +0200 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> Message-ID: <4FC8966A.8040607@mozilla.com> On 5/29/12 5:52 PM, Benjamin Striegel wrote: >> * The system _must_ not prevent, some day, developers from calling Rust >> from JavaScript. >> * The system _must_ not prevent, some day, developers from calling >> JavaScript from Rust. > > I'm not aware of any precedents for calling out of or into Javascript, > in any language. What specific constraints does this impose? Well, in Firefox, we have been calling out of/into JS for ages, first with XPConnect and now with js-ctypes. Neither is fully satisfactory, but they are both useful. XPConnect connects the C++ subset used at Mozilla (in particular, C++ witout exceptions) and JavaScript (and possibly other languages). Calls can only be placed through well-defined interfaces. JavaScript exceptions are converted to C++ error return value, with two rules: - throwing an integer from JavaScript passes that integer to C++; - throwing any other value from JavaScript converts it to a default error value. Conversely, returning an error value from C++ is converted to throwing the corresponding integer in JS. js-ctypes connects C to JavaScript. As C has no exceptions, this simplifies things (although decoding 64-bit C return values in JS is a bit messy). I do not know the semantics of throwing an exception from JS to C, but I suspect this is messy. Now, in Rust, I do not know exactly how to best do this, but I suspect that we would want calls to JavaScript to return a sum type result/error. Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From dteller at mozilla.com Fri Jun 1 03:38:52 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Fri, 01 Jun 2012 12:38:52 +0200 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> <4FBE34B3.9060102@mozilla.com> <4FC483B0.9010004@mozilla.com> <4FC4E3F6.1080201@alum.mit.edu> Message-ID: <4FC89BBC.3000909@mozilla.com> On 5/30/12 5:35 AM, Joe Groff wrote: > On Tue, May 29, 2012 at 7:57 AM, Niko Matsakis wrote: >> In general it seems there are three classes of errors >> >> - globally unrecoverable (just call `fail`) >> - locally unrecoverable (return a `result` type) >> - recoverable (pass in handler or error reporter) > > If you have closures with nonlocal returns, callback handlers could > work in both the locally unrecoverable and recoverable cases. It is my understanding that we really do not want closures with nonlocal returns, as they cause the exact same kind of implementation issues as exceptions, in terms of both performance, semantics and typing (at least if they are not "almost-local" returns). Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From dteller at mozilla.com Fri Jun 1 05:47:56 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Fri, 01 Jun 2012 14:47:56 +0200 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: <4FC57AE2.8080606@mozilla.com> References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> <4FBE34B3.9060102@mozilla.com> <4FC483B0.9010004@mozilla.com> <4FC57AE2.8080606@mozilla.com> Message-ID: <4FC8B9FC.1020009@mozilla.com> On 5/30/12 3:41 AM, Graydon Hoare wrote: > Hi! > > Sorry I've been away, I wanted to talk about this issue, or, well, kinda > just remind you and others in this conversation that there is (in my > mind at least, and in the bug tracker[1]) "a plan" for how to do this. > I've been continuing to assume this is something we'd handle with > per-task dynamic-scoped values, just haven't got around to implementing > them yet. Should be almost entirely library code. Ah, great! My main concern is that we would end up with a Rust used in-the-wild without either guidelines, library or mechanism for handling non-fatal issues. > Here's a sketch of your 'move' function written in this style: > > https://gist.github.com/1f9c8fe1debd9a504eef Let me rephrase your code to be sure that I understand it correctly. I will keep using "issue" for the moment instead of error/exception/failure/... to avoid projecting too much semantics. * Function `handler::try` prepares for execution a block (let's call it the "action block") and lets the developer registers closures to handle various issue cases that may arise during the execution of that action block. * Function `?.handle(some_issue)` registers a block to handle one specific kind of issue. * Execution of the handler block takes place locally, without any stack unwinding. * Execution of the action block starts at the end of the chain of `?.handle(...)`. Is there a way to do this in Rust or does this require the addition of some kind of terminator? * A call to `signal` gives a chance to other issue handlers to execute. Do I understand correctly that this actually somehow pops the issue handler to avoid cycles? * I also have the impression that a call to `signal` also performs some form of non-local return. Am I right? By the way, if I understand correctly, I believe that type name `handler<...>` is a little counter-intuitive. > > I think a sufficiently gnarly implementation that's allowed to hang a > special-variable list off the side of each task should be able to work > given that, just keying off the different addresses of the various > consts in memory. A bit of a hack but I think it might work. > > Note as discussed earlier, in that example the handling all happens _at_ > the dynamic site of signalling (via a call to a passed-down closure, > accessed through the handler library) not by unwinding. Unwinding still > only happens on failure and is still idempotent, unrecoverable. > > Does this not sit well with you currently? I will reply once I am sure that I understand the example :) Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From garethdanielsmith at gmail.com Sat Jun 2 06:30:34 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Sat, 02 Jun 2012 14:30:34 +0100 Subject: [rust-dev] Doc-comment syntax Message-ID: <4FCA157A.8040905@gmail.com> Dear Rust developers/users, I want to convince you that the current syntax for doc-comments in rust is sub-optimal and should be re-worked. Here is an example of a doc-comment in various languages: Rust: #[doc = "Some short description of what this function does"] fn my_fun (x: int) -> int { ... } Python: def my_fun(x): """ Some short description of what this function does """ Java: /** * Some short description of what this function does */ int myFun (int x) { ... } I feel that the syntax for Rust is more complex than in Python/Java. The programmer has more rules to follow when reading/writing it. The difference is small, only a paper-cut, but please consider that: 1. Compared to Python/Java, it takes more effort to read/write Rust's doc-comments and therefore fewer people will do so. 2. When people are spending less effort on doc-comments then they can spend more effort on their real job. Tasks that take less effort feel more fun. 3. doc-comments are a frequently used part of the language, so a special syntactic form is justified over using the generic attribute syntax. Proposed solution: I suggest that the current doc-comment syntax be replaced with: /// ... (three slashes instead of two) for single line doc-comments /** ... */ (two initial stars instead of one) for multi-line doc-comments In this scheme doc-comments are just normal comments with some - very lightweight - marker syntax that lets the programmer/text-editor know that they are special. It is similar to Java and some C++ commenting standards. Does this proposal have any hope? Thanks Gareth From pwalton at mozilla.com Sat Jun 2 08:17:36 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 02 Jun 2012 08:17:36 -0700 Subject: [rust-dev] Doc-comment syntax In-Reply-To: <4FCA157A.8040905@gmail.com> References: <4FCA157A.8040905@gmail.com> Message-ID: <4FCA2E90.2020301@mozilla.com> On 06/02/2012 06:30 AM, Gareth Smith wrote: > Does this proposal have any hope? I agree completely and have thought the exact same thing in the past. I will bring this up at the next meeting. Patrick From niko at alum.mit.edu Sat Jun 2 09:06:57 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 02 Jun 2012 09:06:57 -0700 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: <4FC8928B.4060104@mozilla.com> References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> <4FBE34B3.9060102@mozilla.com> <4FC483B0.9010004@mozilla.com> <4FC4E3F6.1080201@alum.mit.edu> <4FC8928B.4060104@mozilla.com> Message-ID: <4FCA3A21.9080504@alum.mit.edu> On 6/1/12 2:59 AM, David Rajchenbach-Teller wrote: > The other problem is that the function may not have enough information > to determine what is "locally unrecoverable". I believe that `remove` is > a good example of issues whose recoverability depend on the context. I'm not sure I understand what the problem is. It seems like it is easy for `remove()` to recover and return a `result<>` type. The caller can then elect to handle the error however it chooses. A couple of potential problems I can see: - if this is a recurse `remove()`, it may be possible to continue and delete other files. This would seem like a good candidate for a Graydon-style handler, so that `remove()` could invoke the handler with the details of which file it failed to remove and why and the handler can indicate whether `remove()` ought to continue. - the caller can easily ignore the return value accidentally and thus not be aware that return has failed. We probably ought to make it so that ignored return values must be explicitly acknowledged, as in O'caml, using the lint pass. I think this will prevent a lot of bugs in general. Therefore, to call `remove()` without caring whether it succeeds or fails you would write: let _ = remove(...); This would raise a red flag during code review, just as `try { remove(); } catch (Exception e) {}` ought to raise a red flag. Are there other complications I have not considered? Niko From pwalton at mozilla.com Sat Jun 2 09:08:21 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 02 Jun 2012 09:08:21 -0700 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: <4FCA3A21.9080504@alum.mit.edu> References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> <4FBE34B3.9060102@mozilla.com> <4FC483B0.9010004@mozilla.com> <4FC4E3F6.1080201@alum.mit.edu> <4FC8928B.4060104@mozilla.com> <4FCA3A21.9080504@alum.mit.edu> Message-ID: <4FCA3A75.5000107@mozilla.com> On 06/02/2012 09:06 AM, Niko Matsakis wrote: > - the caller can easily ignore the return value accidentally and thus > not be aware that return has failed. We probably ought to make it so > that ignored return values must be explicitly acknowledged, as in > O'caml, using the lint pass. I think this will prevent a lot of bugs in > general. Agreed. Note that we should probably change the return value of hashmap::insert if we do this. Patrick From niko at alum.mit.edu Sat Jun 2 12:12:17 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 02 Jun 2012 12:12:17 -0700 Subject: [rust-dev] replacing bind with lightweight closure syntax Message-ID: <4FCA6591.2060208@alum.mit.edu> Hello Rusters, I want to remove bind. It's a pain to maintain and a significant complication in the language semantics (both problems caused by having two kinds of closures with subtle distinctions). Nobody really objects to this, but the fact remains that bind serves a role that is otherwise unfilled: it provides a (relatively) lightweight closure syntax. For example, I can write: foo.map(bind some_func(_, 3)) which is significantly less noisy than: foo.map({|x| some_func(x, 3)}) I previously tried to address this through the introduction of `_` expressions as a shorthand for closures. This proposal was eventually rejected because the scope of the closure was unclear. I have an alternative I've been thinking about lately. The basic idea is to introduce a new closure expression which looks like: `|| expr`. The expression `expr` may make use of `_` to indicate anonymous arguments. The scope of the closure is basically greedy. So `|| _ + _ * _` is unproblematic. The double bars `||` should signal that this is a closure. Therefore, you could write the above example: foo.map(|| some_func(_, 3)) This also makes for a nice, lightweight thunk syntax. So, a method like: map.get_or_insert(key, || compute_initial_value(...)) which would (presumably) return `key` if it is present in the map, but otherwise execute the thunk and insert the returned value. The same convention naturally extends to named parameters, for those cases where anonymous parameters do not work. For example, if you wish to reference the parameter more than once, as in this example, which pairs each item in a vector with itself ([A] => [(A,A)]): foo.map(|x| (x, x)) In fact, we *could* do away with underscores altogether, although I find them more readable (they highlight those portions of the function call that come from arguments vs the environment). The immediate motivation for this is that I am having troubles with some code due to complications introduced by bind. I'd rather not fix those bugs. I'd rather just delete bind. NIko From matthieu.monrocq at gmail.com Sat Jun 2 16:21:22 2012 From: matthieu.monrocq at gmail.com (Matthieu Monrocq) Date: Sun, 3 Jun 2012 01:21:22 +0200 Subject: [rust-dev] replacing bind with lightweight closure syntax In-Reply-To: <4FCA6591.2060208@alum.mit.edu> References: <4FCA6591.2060208@alum.mit.edu> Message-ID: On Sat, Jun 2, 2012 at 9:12 PM, Niko Matsakis wrote: > Hello Rusters, > > I want to remove bind. It's a pain to maintain and a significant > complication in the language semantics (both problems caused by having two > kinds of closures with subtle distinctions). Nobody really objects to > this, but the fact remains that bind serves a role that is otherwise > unfilled: it provides a (relatively) lightweight closure syntax. For > example, I can write: > > foo.map(bind some_func(_, 3)) > > which is significantly less noisy than: > > foo.map({|x| some_func(x, 3)}) > > I previously tried to address this through the introduction of `_` > expressions as a shorthand for closures. This proposal was eventually > rejected because the scope of the closure was unclear. I have an > alternative I've been thinking about lately. > > The basic idea is to introduce a new closure expression which looks like: > `|| expr`. The expression `expr` may make use of `_` to indicate anonymous > arguments. The scope of the closure is basically greedy. So `|| _ + _ * > _` is unproblematic. The double bars `||` should signal that this is a > closure. > > Therefore, you could write the above example: > > foo.map(|| some_func(_, 3)) > > This also makes for a nice, lightweight thunk syntax. So, a method like: > > map.get_or_insert(key, || compute_initial_value(...)) > > which would (presumably) return `key` if it is present in the map, but > otherwise execute the thunk and insert the returned value. > > The same convention naturally extends to named parameters, for those cases > where anonymous parameters do not work. For example, if you wish to > reference the parameter more than once, as in this example, which pairs > each item in a vector with itself ([A] => [(A,A)]): > > foo.map(|x| (x, x)) > > In fact, we *could* do away with underscores altogether, although I find > them more readable (they highlight those portions of the function call that > come from arguments vs the environment). > > The immediate motivation for this is that I am having troubles with some > code due to complications introduced by bind. I'd rather not fix those > bugs. I'd rather just delete bind. > > > NIko > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > Hello, I must admit I find the latter example quite pleasing: foo.map(|x| (x, x)) and (unlike you it seems) finds that it could completely replace _. The problem with _ is that though it seems nice enough if there is one, but it is not as immediate for the reader to determine how many parameters the resulting function has. We could number them (_0, _1, _2) but it makes maintenance painful (if you remove _1, you have to remain all those which followed). I find that explicitly naming the arguments in between the pipes really help making it clear how many arguments the created function has. Of course, it still does nothing with the problem of shadowing an outer element meant to be captured. Not sure if there is a way to deal with that at the same time... -- Matthieu -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Sat Jun 2 19:00:36 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 02 Jun 2012 19:00:36 -0700 Subject: [rust-dev] replacing bind with lightweight closure syntax In-Reply-To: References: <4FCA6591.2060208@alum.mit.edu> Message-ID: <4FCAC544.9070002@alum.mit.edu> On 6/2/12 4:21 PM, Matthieu Monrocq wrote: > The problem with _ is that though it seems nice enough if there is > one, but it is not as immediate for the reader to determine how many > parameters the resulting function has. We could number them (_0, _1, > _2) but it makes maintenance painful (if you remove _1, you have to > remain all those which followed). I guess each has its downsides. With named parameters, you can easily see how many there are at a glance but it's hard to see where they are used. With anonymous parameters, you can easily see where they are used but now how many there are. To be honest, I'd be satisfied with just having named parameters. But I thought I'd go for broke and get `_` expressions, which I happen to really like. Also, this idea for `|| expr` as a closure was born as part of a larger syntax tweak for closures that pcwalton was tossing around the other day (though the anonymous parameters are my addition). In retrospect, I probably ought to have waited for him to write that up. I know he wants to focus on fixing bugs right now, which is absolutely right. Sorry Patrick. My bad. I just got annoyed at supporting bind and excited at the thought of underscores and there weren't many people around on IRC to discuss the idea with. So anyway, let's table this idea for now. I think I'll perhaps just pursue removing bind (issue #2189) even without a specific replacement, confident that one will come along (if we decide we need one; perhaps `{|| ... }` is good enough). Niko From graydon at mozilla.com Sat Jun 2 23:45:01 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Sat, 02 Jun 2012 23:45:01 -0700 Subject: [rust-dev] replacing bind with lightweight closure syntax In-Reply-To: <4FCAC544.9070002@alum.mit.edu> References: <4FCA6591.2060208@alum.mit.edu> <4FCAC544.9070002@alum.mit.edu> Message-ID: <4FCB07ED.80001@mozilla.com> On 02/06/2012 7:00 PM, Niko Matsakis wrote: > So anyway, let's table this idea for now. I think I'll perhaps just > pursue removing bind (issue #2189) even without a specific replacement, > confident that one will come along (if we decide we need one; perhaps > `{|| ... }` is good enough). That's my feeling. Given we seem to have consensus that the "eager aspect" of currying is actually an antifeature / usability hazard, I think the residual quest to shave 1-2 characters off a lambda-that-directly-delegates isn't worth the added combinatorial cost / effort. At least not obviously, or not obviously _now_; we have other things higher on the list, and just getting rid of bind is the easiest path forward. Removed code carries no bugs :) -Graydon From banderson at mozilla.com Sun Jun 3 17:52:33 2012 From: banderson at mozilla.com (Brian Anderson) Date: Sun, 03 Jun 2012 17:52:33 -0700 Subject: [rust-dev] Doc-comment syntax In-Reply-To: <4FCA157A.8040905@gmail.com> References: <4FCA157A.8040905@gmail.com> Message-ID: <4FCC06D1.1030706@mozilla.com> On 06/02/2012 06:30 AM, Gareth Smith wrote: > Dear Rust developers/users, > > I want to convince you that the current syntax for doc-comments in rust > is sub-optimal and should be re-worked. > > Does this proposal have any hope? Agreed on all points. The current syntax was just an expedient to get rustdoc working, and the intent has been to revisit exactly how we feed that information into rustdoc. Attaching docs via attributes is very easy because attributes are actually associated with specific AST nodes, whereas comments are just whitespace. Implementing doc comments with the current parser will require a (relatively simple) heuristic to associate comments with AST nodes, which could then be plugged into a new rustdoc pass. I also came up with an attirbute syntax that is one character shy of python's docstrings while being relatively easy to fit into the existing attribute syntax: #""" Docs go here """ fn foo() { ... But probably doc comments are the right way to go. -Brian From banderson at mozilla.com Sun Jun 3 18:23:43 2012 From: banderson at mozilla.com (Brian Anderson) Date: Sun, 03 Jun 2012 18:23:43 -0700 Subject: [rust-dev] Doc-comment syntax In-Reply-To: <4FCA157A.8040905@gmail.com> References: <4FCA157A.8040905@gmail.com> Message-ID: <4FCC0E1F.10507@mozilla.com> On 06/02/2012 06:30 AM, Gareth Smith wrote: > Dear Rust developers/users, > > I want to convince you that the current syntax for doc-comments in rust > is sub-optimal and should be re-worked.> > Does this proposal have any hope? > I opened the issue https://github.com/mozilla/rust/issues/2498 If anybody wants to work on it I can point them in the right direction. From zackcorr95 at gmail.com Mon Jun 4 04:31:11 2012 From: zackcorr95 at gmail.com (Zack Corr) Date: Mon, 4 Jun 2012 21:31:11 +1000 Subject: [rust-dev] Cargo proposal - thinking about better ways to represent sources Message-ID: Hello everyone, I have committed myself to add dependency support for Cargo. The way Cargo sources are currently implemented isn't right in my eyes and I have discussed this with Brian and he said we would re-discuss it tomorrow, but I live in a different time zone so I probably won't get hold of him. So I have written up a rough proposal here because I feel this should be proposed before I start trying to implement dependencies in the current system. It's a bigger document than it should be because I go on a bit.. but I'll summarise the general gist of it. > Currently, each source contains a packages.json file. Whenever a new package is added, the user would need to cargo sync the packages.json file. This would also need to be done, if dependencies were implemented, whenever a package has a new version. Coupled with the extremely bad usability of this, with lots of packages, there could be quite large package.json files if there are eventually thousands of packages. @brson suggested that it could do a git pull so it only grabs changes, but this would not apply for sources that don't run on git. The alternative is to not have a central package and instead an API that sources follow (not really an API, as it can be implemented with static files just like the current system can be hosted on Github). I propose the following: /source.json - access to a source's information (such as signing keys) /crates.json - access to a an array of all packages in the source (by name), used by the cargo list feature /crates/.json - access to a certain crate's information by name (equivalent to the objects inside packages.json OPTIONAL: /crates/.json - access to a certain crate's information by uuid (will probably change) OPTIONAL: all of the above files have a .sig file each. Only require if the source.json file specifies a key. This way it can still be used on Github, but can also be implemented dynamically, so it's pretty much an `API`. e.g. we could still use https://raw.github.com/mozilla/cargo-central/master as the source URL, and then have a source.json file, a crates.json file and then have crates/rustray.json files. tl;dr - I am proposing that Cargo does not have a single packages.json as this requires syncing every time there is a version or other info change for a single package. Instead, the information for a package is accessed when it is being installed. This document also discusses how I intend to implement dependencies and correct un-installation (it does weak pattern matching now). I am willing to meet halfway and implement both `offline` (old) and `online` (mine), but I don't think it would be a good idea. -------------- next part -------------- An HTML attachment was scrubbed... URL: From dteller at mozilla.com Mon Jun 4 04:56:21 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Mon, 04 Jun 2012 13:56:21 +0200 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: <4FCA3A21.9080504@alum.mit.edu> References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> <4FBE34B3.9060102@mozilla.com> <4FC483B0.9010004@mozilla.com> <4FC4E3F6.1080201@alum.mit.edu> <4FC8928B.4060104@mozilla.com> <4FCA3A21.9080504@alum.mit.edu> Message-ID: <4FCCA265.1030700@mozilla.com> On 6/2/12 6:06 PM, Niko Matsakis wrote: > On 6/1/12 2:59 AM, David Rajchenbach-Teller wrote: >> The other problem is that the function may not have enough information >> to determine what is "locally unrecoverable". I believe that `remove` is >> a good example of issues whose recoverability depend on the context. > > I'm not sure I understand what the problem is. It seems like it is easy > for `remove()` to recover and return a `result<>` type. The caller can > then elect to handle the error however it chooses. I actually meant the functions called by the implementation of `remove`. For instance, `copy` generally does not have to return anything meaningful. So if we assume that it is locally recoverable, in this design, it should return a `result<>` type ? but chances are that users will forget to pattern-match it, since they do not care about that result. If we assume that it is generally irrecoverable, well, we have to use a failure as an exception in the implementation of `remove`. > A couple of potential problems I can see: > > - if this is a recurse `remove()`, it may be possible to continue and > delete other files. This would seem like a good candidate for a > Graydon-style handler, so that `remove()` could invoke the handler with > the details of which file it failed to remove and why and the handler > can indicate whether `remove()` ought to continue. > > - the caller can easily ignore the return value accidentally and thus > not be aware that return has failed. We probably ought to make it so > that ignored return values must be explicitly acknowledged, as in > O'caml, using the lint pass. I think this will prevent a lot of bugs in > general. Therefore, to call `remove()` without caring whether it > succeeds or fails you would write: > > let _ = remove(...); Good point, I had not thought about that. > This would raise a red flag during code review, just as `try { remove(); > } catch (Exception e) {}` ought to raise a red flag. Do I understand correctly that you mean actual reviews and not lint-style warnings? Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From garethdanielsmith at gmail.com Mon Jun 4 11:02:08 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Mon, 04 Jun 2012 19:02:08 +0100 Subject: [rust-dev] Doc-comment syntax In-Reply-To: <4FCA2E90.2020301@mozilla.com> References: <4FCA157A.8040905@gmail.com> <4FCA2E90.2020301@mozilla.com> Message-ID: <4FCCF820.5070505@gmail.com> On 02/06/12 16:17, Patrick Walton wrote: > I agree completely and have thought the exact same thing in the past. > I will bring this up at the next meeting. On 04/06/12 01:52, Brian Anderson wrote: > Agreed on all points. The current syntax was just an expedient to get > rustdoc working, and the intent has been to revisit exactly how we > feed that information into rustdoc. Thats great. Thanks. Gareth From graydon at mozilla.com Mon Jun 4 17:23:05 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 04 Jun 2012 17:23:05 -0700 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: <4FC8B9FC.1020009@mozilla.com> References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> <4FBE34B3.9060102@mozilla.com> <4FC483B0.9010004@mozilla.com> <4FC57AE2.8080606@mozilla.com> <4FC8B9FC.1020009@mozilla.com> Message-ID: <4FCD5169.3070502@mozilla.com> On 12-06-01 5:47 AM, David Rajchenbach-Teller wrote: > My main concern is that we would end up with a Rust used in-the-wild > without either guidelines, library or mechanism for handling non-fatal > issues. Yeah. We'll have to pin down a technique and use it widely through the stdlib when we're comfortable with it. Similar to the matter of classes / objects / ifaces. We're still doing some late-stage design work here. Shouldn't be much longer, a few months and we'll have to pick something and commit to it. > I will keep using "issue" for the moment instead of > error/exception/failure/... to avoid projecting too much semantics. Ok. > * Function `handler::try` prepares for execution a block (let's call it > the "action block") and lets the developer registers closures to handle > various issue cases that may arise during the execution of that action > block. Yes. Might not be necessary to write in this form, but it scopes the push/pop of new handlers. This was just a sketch and I'm sure there are some conceptual / implementation bugs we'd need to iron out to make it just right. > * Function `?.handle(some_issue)` registers a block to handle one > specific kind of issue. Yes. > * Execution of the handler block takes place locally, without any stack > unwinding. Yes. > * Execution of the action block starts at the end of the chain of > `?.handle(...)`. Is there a way to do this in Rust or does this require > the addition of some kind of terminator? Not sure I understand. The handler that gets run is the head of a list held in a task-local variable indexed by the constant in question (a hack: every constant has a unique address in the process, so is effectively a key you can use as per-process global unique value). Different constants refer to different handler lists, hence have no relationship. The .handle(...){...}.handle(...){...} chain is just pushing new entries on multiple handler lists simultaneously so they all get popped off at the same time when the try{...} block completes. > * A call to `signal` gives a chance to other issue handlers to execute. > Do I understand correctly that this actually somehow pops the issue > handler to avoid cycles? It'll have to do so, yes. > * I also have the impression that a call to `signal` also performs some > form of non-local return. Am I right? No. It just picks the head of the handler list, call that H, then shifts the task-local handler list down by one so H can call outer handlers, then invokes H. > By the way, if I understand correctly, I believe that type name > `handler<...>` is a little counter-intuitive. Ok. Other suggestions welcome. > I will reply once I am sure that I understand the example :) Please do follow up with further questions. If you want to drop by IRC and do some interactive Q&A that's also likely to help. I want to make sure we develop something here that at least *conceptually* sits well with everyone; it's a larger question whether it feels good in practice. -Graydon From banderson at mozilla.com Mon Jun 4 20:30:20 2012 From: banderson at mozilla.com (Brian Anderson) Date: Mon, 4 Jun 2012 20:30:20 -0700 (PDT) Subject: [rust-dev] Cargo proposal - thinking about better ways to represent sources In-Reply-To: Message-ID: <415975294.2406647.1338867020766.JavaMail.root@mozilla.com> ----- Original Message ----- > From: "Zack Corr" > To: rust-dev at mozilla.org > Sent: Monday, June 4, 2012 4:31:11 AM > Subject: [rust-dev] Cargo proposal - thinking about better ways to represent sources > > > Hello everyone, > > > I have committed myself to add dependency support for Cargo. Yay! > The way > Cargo sources are currently implemented isn't right in my eyes and I > have discussed this with Brian and he said we would re-discuss it > tomorrow, but I live in a different time zone so I probably won't > get hold of him. So I have written up a rough proposal here because > I feel this should be proposed before I start trying to implement > dependencies in the current system. It's a bigger document than it > should be because I go on a bit.. but I'll summarise the general > gist of it. > > > > Currently, each source contains a packages.json file. Whenever a > > new package is added, the user would need to cargo sync the > > packages.json file. This would also need to be done, if > > dependencies were implemented, whenever a package has a new > > version. Coupled with the extremely bad usability of this Why is this extremely bad for usability? Would it be bad if we automatically synced the sources? > > lots of packages, there could be quite large package.json files if > > there are eventually thousands of packages. @brson suggested that > > it could do a git pull so it only grabs changes, but this would > > not apply for sources that don't run on git. The alternative is to > > not have a central package and instead an API that sources follow > > (not really an API, as it can be implemented with static files > > just like the current system can be hosted on Github). > > > I propose the following: > > > > /source.json - access to a source's information (such as signing > keys) What other information? The packages.json file on cargo-central doesn't appear to contain any information that belongs here. > /crates.json - access to a an array of all packages in the > source (by name), used by the cargo list feature > /crates/.json - access to a certain crate's information by > name (equivalent to the objects inside packages.json > OPTIONAL: /crates/.json - access to a certain crate's > information by uuid (will probably change) Can we put the uuid in crates.json so we don't have to list the crate's information in two files? Presumably the uuid never changes. > OPTIONAL: all of the above files have a .sig file each. Only require > if the source.json file specifies a key. Making Graydon sign so many files is asking a lot. An entry in the current packages.json file looks like this: { "name": "rustray", "uuid": "c89c5834-63db-4a6e-8e0a-d75985b1730e", "url": "git://github.com/brson/rustray", "tags": ["example", "graphics"], "method": "git", "description": "A raytracing proof-of-concept in Rust." }, Under the proposed scheme I would imagine 'name', 'uuid' 'tags' and 'description' still need to go into crates.json so that they can be discovered from the UI. The other two are details that could be left to the package-specific file and only retrieved during install. Is that right? > > This way it can still be used on Github, but can also be implemented > dynamically, so it's pretty much an `API`. e.g. we could still use > https://raw.github.com/mozilla/cargo-central/master as the source > URL, and then have a source.json file, a crates.json file and then > have crates/rustray.json files. Do you have scenarios in mind where we might want to implement this API instead of leaving it up to static file serving? > tl;dr - I am proposing that Cargo does not have a single > packages.json as this requires syncing every time there is a version > or other info change for a single package. Instead, the information > for a package is accessed when it is being installed. This document > also discusses how I intend to implement dependencies and correct > un-installation (it does weak pattern matching now). I don't want to discourage you, because I really, really want you to improve cargo! That said, I am not convinced of this scheme as laid out because it adds a lot of pieces without a clearly proportional amount of win. How we do dependency resolution looks orthogonal to how we represent the metadata, and we aren't yet encountering any performance problems in this area since we only have 2 dozen or so packages. Do we know how npm organizes its package index? I consider npm to be pretty rad and would be inclined to do anything that they do. -Brian From zackcorr95 at gmail.com Mon Jun 4 21:23:15 2012 From: zackcorr95 at gmail.com (Zack Corr) Date: Tue, 5 Jun 2012 14:23:15 +1000 Subject: [rust-dev] Cargo proposal - thinking about better ways to represent sources In-Reply-To: <415975294.2406647.1338867020766.JavaMail.root@mozilla.com> References: <415975294.2406647.1338867020766.JavaMail.root@mozilla.com> Message-ID: > > Why is this extremely bad for usability? Would it be bad if we > automatically synced the sources? > Well, I just consider having to type `cargo sync` whenever a package changes bad usability. We could have a compromise to make it automatic (see the bottom of the message). > > /crates.json - access to a an array of all packages in the > > source (by name), used by the cargo list feature > > /crates/.json - access to a certain crate's information by > > name (equivalent to the objects inside packages.json > > OPTIONAL: /crates/.json - access to a certain crate's > > information by uuid (will probably change) > > Can we put the uuid in crates.json so we don't have to list the crate's > information in two files? Presumably the uuid never changes. OK. That was a compromise in order to be able to install by uuid with one fetch. If it was in crates.json, it would need to fetch crates.json and then the crate file. I guess that is a bad setup. > > OPTIONAL: all of the above files have a .sig file each. Only require > > if the source.json file specifies a key. > > Making Graydon sign so many files is asking a lot. That's why I was suggesting it be a dynamic website. But yeah, I understand that suggestion was pretty silly. Under the proposed scheme I would imagine 'name', 'uuid' 'tags' and > 'description' > still need to go into crates.json so that they can be discovered from the > UI. > The other two are details that could be left to the package-specific file > and > only retrieved during install. Is that right? Yes. But description isn't even used in searching yet. The crates.json file really shouldn't even need to be there, it was just so there could still be static support and still have searching / listing. > Do you have scenarios in mind where we might want to implement this API > instead of leaving it up to static file serving? There is reasons to switch from the Github repo, but not reasons to not use static files. You have a point. If you were to have a dynamic website, we could have submission by means other than Github and an online index of files without having to fetch the packages.json files from Github to index packages. > > Do we know how npm organizes its package index? I consider npm to be pretty > rad and would be inclined to do anything that they do. It works like I am proposing. Whenever something is installed it fetches information from the API for a certain package. `npm install blah` => https://registry.npmjs.org/blah (json file of information about the package) However, it does have a local list of packages. When it fetches the package list it is incremental only. So it works halfway between what we have and what I am proposing. If everyone wants to stick with the packages.json file setup, we could make it automatic by having a checksum of the packages.json file that is downloaded every time something is calling upon remote packages to and automatically `cargo sync`s if the checksum is not the same as the local one. Maybe even make it so Git sources don't need this and it just does a git pull everytime you try to install / search / list. However, I think we should include my `cargo sources add` (inc. sources.json and source.json files) idea so we can have source management, because there's really no use having sources built in if the user can't manage them from the CLI. What do you think? -------------- next part -------------- An HTML attachment was scrubbed... URL: From zackcorr95 at gmail.com Mon Jun 4 22:44:49 2012 From: zackcorr95 at gmail.com (Zack Corr) Date: Tue, 5 Jun 2012 15:44:49 +1000 Subject: [rust-dev] Cargo proposal - thinking about better ways to represent sources In-Reply-To: References: <415975294.2406647.1338867020766.JavaMail.root@mozilla.com> Message-ID: O.K, so after a talk with Brian in #rust, I think we've found a good solution that keeps the reliability and simplicity of the current setup but can also automatically sync and update the local package list without downloading an (eventually) massive file. Every source has a packages.json file. There are 3 types of sources: - "git": a source hosted in a git repository - cargo handles incremental changes by simply `git pull`ing whenever the list, search or install command is called and then using the new package information for the command. - "http" | "ftp" | "curl": a source hosted via some curl supported transfer (e.g. http) - cargo handles incremental changes by appending `?from=` to the URL where `timestamp`is a generic unix timestamp for the last update it did. If the source supports the from command, it will only provide the packages that have been updated since `timestamp`, otherwise it provides the entire packages.json file. Whenever the list, search or install command is called it requests the packages.json file with the last timestamp it did and merges it's local package list with it, and then uses the information for the command. - "file" - a source hosted locally, self explanatory Then a source can optionally contain a source.json file which contains the same stuff as a single source in sources.json does now (minus name and url fields) and sources.json becomes: ``` { "central": "git://github.com/mozilla/cargo-central" } ``` I think this turns out better. Any thoughts? -------------- next part -------------- An HTML attachment was scrubbed... URL: From elly+rd at leptoquark.net Tue Jun 5 08:01:45 2012 From: elly+rd at leptoquark.net (Elly Jones) Date: Tue, 5 Jun 2012 10:01:45 -0500 Subject: [rust-dev] Cargo proposal - thinking about better ways to represent sources In-Reply-To: References: <415975294.2406647.1338867020766.JavaMail.root@mozilla.com> Message-ID: <20120605150145.GJ31414@leptoquark.net> On Tue, Jun 05, 2012 at 03:44:49PM +1000, Zack Corr wrote: > O.K, so after a talk with Brian in #rust, I think we've found a good > solution that keeps the reliability and simplicity of the current setup but > can also automatically sync and update the local package list without > downloading an (eventually) massive file. > > Every source has a packages.json file. > > There are 3 types of sources: > > > - "git": a source hosted in a git repository - cargo handles incremental > changes by simply `git pull`ing whenever the list, search or install > command is called and then using the new package information for the > command. > - "http" | "ftp" | "curl": a source hosted via some curl supported > transfer (e.g. http) - cargo handles incremental changes by appending > `?from=` to the URL where `timestamp`is a generic unix timestamp > for the last update it did. If the source supports the from command, it > will only provide the packages that have been updated since `timestamp`, > otherwise it provides the entire packages.json file. Whenever the list, > search or install command is called it requests the packages.json file with > the last timestamp it did and merges it's local package list with it, and > then uses the information for the command. > - "file" - a source hosted locally, self explanatory > > Then a source can optionally contain a source.json file which contains the > same stuff as a single source in sources.json does now (minus name and url > fields) and sources.json becomes: > > ``` > { > "central": "git://github.com/mozilla/cargo-central" > } > ``` > > I think this turns out better. Any thoughts? This seems legit, but I still don't understand what problem is being solved very well. Central (which is our biggest source right now) is 6130 bytes total, and gzipped it's 1632 bytes. Downloading it incrementally instead of in its entirety each time is not saving a whole lot. The incremental-fetch approach also worries me because, as it works now, source signing is based on a signature across the entire packages.json file. If we're fetching only part of that file (or just those packages new since time t), we won't be able to check the signature. I would not have the same objection to git for incremental fetches, from which we are guaranteed to get the same file the author uploaded. > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -- elly -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 490 bytes Desc: Digital signature URL: From niko at alum.mit.edu Tue Jun 5 09:09:05 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 05 Jun 2012 09:09:05 -0700 Subject: [rust-dev] Back to errors, failures and exceptions In-Reply-To: <4FCCA265.1030700@mozilla.com> References: <4FBA0B78.2080304@mozilla.com> <4FBA22B4.2070901@mozilla.com> <4FBCDC68.9020205@mozilla.com> <4FBE34B3.9060102@mozilla.com> <4FC483B0.9010004@mozilla.com> <4FC4E3F6.1080201@alum.mit.edu> <4FC8928B.4060104@mozilla.com> <4FCA3A21.9080504@alum.mit.edu> <4FCCA265.1030700@mozilla.com> Message-ID: <4FCE2F21.7090904@alum.mit.edu> On 6/4/12 4:56 AM, David Rajchenbach-Teller wrote: > I actually meant the functions called by the implementation of `remove`. > For instance, `copy` generally does not have to return anything > meaningful. I see. However, I'm not sure I agree. I think `copy` ought to return something that indicates whether it succeeded and---if not---why not. >> This would raise a red flag during code review, just as `try { remove(); >> } catch (Exception e) {}` ought to raise a red flag. > Do I understand correctly that you mean actual reviews and not > lint-style warnings? Yes. I meant that the compiler would flag an error for ignored return values. If the programmer insisted on ignoring the return value, it's suggests that a comment is warranted explaining why. Niko From erick.tryzelaar at gmail.com Tue Jun 5 14:27:45 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Tue, 5 Jun 2012 14:27:45 -0700 Subject: [rust-dev] Cargo proposal - thinking about better ways to represent sources In-Reply-To: <20120605150145.GJ31414@leptoquark.net> References: <415975294.2406647.1338867020766.JavaMail.root@mozilla.com> <20120605150145.GJ31414@leptoquark.net> Message-ID: On Tue, Jun 5, 2012 at 8:01 AM, Elly Jones wrote: > > This seems legit, but I still don't understand what problem is being solved very > well. Central (which is our biggest source right now) is 6130 bytes total, and > gzipped it's 1632 bytes. Downloading it incrementally instead of in its entirety > each time is not saving a whole lot. For what it's worth, the Mac packaging system, homebrew, uses git to store their packaging information: https://github.com/mxcl/homebrew. It seems to work pretty well for them. From pwalton at mozilla.com Tue Jun 5 18:20:04 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 05 Jun 2012 18:20:04 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak Message-ID: <4FCEB044.1010204@mozilla.com> Hi everyone, Here's a revised lambda syntax tweak proposal. It's gotten feedback from several, so I think it's time to present it more generally. I don't think we should do this now; we should remain focused on bugs for 0.3. I'm just interested in getting feedback. Executive summary of the proposal: 1. Change the block lambda syntax from { |x| x + 3 } to |x| x + 3. 2. In general, remove the special case of "pulling the last argument out and turning it into a block" from the language. However, it is still supported, and in fact required, as part of the "for" construct and the new "do" construct. 3. Change this: for [ 1, 2, 3 ].map { |x| ... } To this: for [ 1, 2, 3 ].map |x| { ... } 4. Add a new form, `do`, in order to support block syntax for constructs that aren't strictly loops. Also remove the mandatory || for zero-argument lambda blocks. Thus instead of: spawn { || ... } We have: do spawn { ... } Rationale: * Removing the ability for the last argument of a function call to be pulled out in the general case significantly decreases the complexity of the language grammar. This feature simply becomes a mandatory part of the "for" or "do" expressions. * Removing the pipes around zero-argument functions in "do" or "for" constructs improves readability. In particular "do spawn" reads naturally. * Having the opening brace be at the end of the line increases familiarity for programmers accustomed to the C language family. * Removing the mandatory braces around lambdas decreases visual noise for small lambda expressions. Consider the closing parentheses on this line: log([ 1, 2, 3 ].map(|x| x + 1)) Versus the sequence '}))' on this line: log([ 1, 2, 3 ].map({ |x| x + 1 })) * Having only one way to get the block syntax iteration ("for" or "do") provides an incentive for library authors to ensure that their blocks follow the iteration protocol. At the same time, it minimizes surprises when people try to put "break"/"continue"/"ret" in blocks intended for iteration and discover it doesn't work. Now it always works for iterators. * The "do" block allows "continue" for early returns, which is something that cannot be done at the moment with block lambdas. Here are the technical details: Pseudo-BNF: PrimaryExpr ::== ... | BlockLambda | ForExpr | DoExpr BlockLambda ::== AbbreviatedArgs Expr AbbreviatedArgs ::== '||' | '|' (ModeSigil Identifier)* '|' ForExpr ::== 'for' (CallExpr | PrimaryExpr) AbbreviatedArgs? Block DoExpr ::== 'do' (CallExpr | PrimaryExpr) AbbreviatedArgs? Block If the "for" expression or "do" expression head is a primary expression that is not a call expression, then it's treated as a call expression with an empty argument list. The block lambda in a "for" expression is treated as returning bool, while the block lambda in a "do" expression is treated as returning unit. As such, "break"/"continue"/"ret" all work in "for" loops, while only "continue" works in "do" expressions (which effects an early return). Thoughts? Patrick From niko at alum.mit.edu Tue Jun 5 19:23:28 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 05 Jun 2012 19:23:28 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FCEB044.1010204@mozilla.com> References: <4FCEB044.1010204@mozilla.com> Message-ID: <4FCEBF20.5030403@alum.mit.edu> On 6/5/12 6:20 PM, Patrick Walton wrote: > > * Removing the ability for the last argument of a function call to be > pulled out in the general case significantly decreases the complexity > of the language grammar. This feature simply becomes a mandatory part > of the "for" or "do" expressions. Also, the semicolon rules become simpler again: the only time that semicolons can be omitted is with special forms, basically. Niko From graydon at mozilla.com Wed Jun 6 10:23:00 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 06 Jun 2012 10:23:00 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FCEB044.1010204@mozilla.com> References: <4FCEB044.1010204@mozilla.com> Message-ID: <4FCF91F4.2080807@mozilla.com> On 05/06/2012 6:20 PM, Patrick Walton wrote: > Thoughts? Very nice. Though I do like the current {|x| ...} in the sense that it has an explicit scope-end for the binder, and I'll be sad to lose that, but the rest is clever. Grammar simplifications are good. And I guess the scope-end issue is in inherent tension with the desire to have short lambdas in argument lists. I'd also possibly prefer "break" rather than "continue" to get an early-exit from a 'do'. But then, we're still debating what to do for the word "continue" in the grammar anyway (#2229, I still prefer "loop;" there!) (Does slightly make me think again to the no-scope-end fat-arrow lambdas that were proposed last time we discussed this -- "(x) => expr" -- but I'm not sure if the symmetry with pattern fat-arrow syntax is worth the chattiness cost nor the need for the parser to suspend judgment on tuple-of-ident expressions while parsing. Thoughts?) -Graydon From pwalton at mozilla.com Wed Jun 6 10:37:47 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 06 Jun 2012 10:37:47 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FCF91F4.2080807@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FCF91F4.2080807@mozilla.com> Message-ID: <4FCF956B.5090903@mozilla.com> On 6/6/12 10:23 AM, Graydon Hoare wrote: > I'd also possibly prefer "break" rather than "continue" to get an > early-exit from a 'do'. But then, we're still debating what to do for > the word "continue" in the grammar anyway (#2229, I still prefer "loop;" > there!) Sure, either one works for me. I don't actually mind whether it's break or continue, as long as there's some way to do it :) > (Does slightly make me think again to the no-scope-end fat-arrow lambdas > that were proposed last time we discussed this -- "(x) => expr" -- but > I'm not sure if the symmetry with pattern fat-arrow syntax is worth the > chattiness cost nor the need for the parser to suspend judgment on > tuple-of-ident expressions while parsing. Thoughts?) Yeah, I think the parsing will become really hairy there, especially if the block lambda arguments grow into patterns. Not to shoot it down, of course, just mentioning that it's an (LA)LR hazard. Patrick From sebastian.sylvan at gmail.com Wed Jun 6 10:52:31 2012 From: sebastian.sylvan at gmail.com (Sebastian Sylvan) Date: Wed, 6 Jun 2012 10:52:31 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FCEB044.1010204@mozilla.com> References: <4FCEB044.1010204@mozilla.com> Message-ID: On Tue, Jun 5, 2012 at 6:20 PM, Patrick Walton wrote: > Hi everyone, > > Here's a revised lambda syntax tweak proposal. It's gotten feedback from > several, so I think it's time to present it more generally. Just a quick question: Can I pass in a multi-statement lambda to a function without using "do" or "for", and if so what does it look like? I'm guessing something like this, but I didn't see it spelled out: foo( |x| { let y = x+1; y+1 }); Seb -- Sebastian Sylvan From pwalton at mozilla.com Wed Jun 6 10:53:37 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 06 Jun 2012 10:53:37 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: References: <4FCEB044.1010204@mozilla.com> Message-ID: <4FCF9921.10107@mozilla.com> On 6/6/12 10:52 AM, Sebastian Sylvan wrote: > Just a quick question: Can I pass in a multi-statement lambda to a > function without using "do" or "for", and if so what does it look > like? > > I'm guessing something like this, but I didn't see it spelled out: > > foo( |x| { > let y = x+1; > y+1 > }); Yep, that's exactly how it works. It falls out of blocks being expressions. Patrick From niko at alum.mit.edu Wed Jun 6 11:07:08 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 06 Jun 2012 11:07:08 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FCF91F4.2080807@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FCF91F4.2080807@mozilla.com> Message-ID: <4FCF9C4C.4060000@alum.mit.edu> On 6/6/12 10:23 AM, Graydon Hoare wrote: > (#2229, I still prefer "loop;" there!) +1 From graydon at mozilla.com Wed Jun 6 11:38:14 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 06 Jun 2012 11:38:14 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FCF956B.5090903@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FCF91F4.2080807@mozilla.com> <4FCF956B.5090903@mozilla.com> Message-ID: <4FCFA396.7070303@mozilla.com> On 12-06-06 10:37 AM, Patrick Walton wrote: > Sure, either one works for me. I don't actually mind whether it's break > or continue, as long as there's some way to do it :) Agreed. > Yeah, I think the parsing will become really hairy there, especially if > the block lambda arguments grow into patterns. Not to shoot it down, of > course, just mentioning that it's an (LA)LR hazard. Oh, yeah, it all goes sideways if/when we permit patterns in there. Ok, musing revoked; '|pat-list| expr' is a perfectly fine lambda :) -Graydon From garethdanielsmith at gmail.com Thu Jun 7 13:41:08 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Thu, 07 Jun 2012 21:41:08 +0100 Subject: [rust-dev] I am confused regarding implicit copies Message-ID: <4FD111E4.2020608@gmail.com> Hi Rust-Dev, I have recently (using the latest rust from github) encountered some new warnings about "implicitly copying a non-implicitly-copyable value". I believe this is due to the fix for https://github.com/mozilla/rust/issues/2450. This warning seems to pop up all over the place because, as the bug points out, vecs/strs are in-fact copied rather a lot (at least in the rust I have written). I think that in some places I can restructure the code to avoid copies, but that still leaves many places where I guess I need to either add a `copy` or just ignore the warning (or turn it off). I am worried that I will have to litter my code with `copy`. The bug above mentions that the warning has been disabled for [Mozilla's] existing projects. So my question is: what is the long-term plan here? Will Mozilla's projects be restructured to avoid copying strs/vecs, or to add `copy` where it is not possible? Will the new vecs/strs make this a non-issue somehow (are vecs/strs still unique in the new scheme?)? Please help me be less confused. Thanks Gareth From garethdanielsmith at gmail.com Thu Jun 7 14:20:49 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Thu, 07 Jun 2012 22:20:49 +0100 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FCEB044.1010204@mozilla.com> References: <4FCEB044.1010204@mozilla.com> Message-ID: <4FD11B31.8060109@gmail.com> On 06/06/12 02:20, Patrick Walton wrote: > 1. 2. 3. ... These look very nice to me. > 4. Add a new form, `do`, ... I think that allowing an early exit with a break/continue from lambdas that use this special form is confusing, because "breaking" may or may-not actually resume the code that follows the do-call. The lambda might be put into a data structure for later execution, or, like in your spawn example, executed in a new task. I would prefer that instead of having a special `do` form, all `|| expr` lambdas could have early returns using `ret`. This makes sense because lambdas are functions (but when used with a for-loop they are special). The other kind of rust functions (i.e. non-lambdas) can have early returns, so allowing `ret` in lambdas means that one is able to use the same early-exit style in lambdas as in fn-functions, which is symmetric and therefore nice. Thanks Gareth From pwalton at mozilla.com Thu Jun 7 14:27:51 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 07 Jun 2012 14:27:51 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD11B31.8060109@gmail.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> Message-ID: <4FD11CD7.80104@mozilla.com> On 6/7/12 2:20 PM, Gareth Smith wrote: > I think that allowing an early exit with a break/continue from lambdas > that use this special form is confusing, because "breaking" may or > may-not actually resume the code that follows the do-call. The lambda > might be put into a data structure for later execution, or, like in your > spawn example, executed in a new task. > > I would prefer that instead of having a special `do` form, all `|| expr` > lambdas could have early returns using `ret`. If you allow all block lambdas to have early returns with "ret", then this: fn f() { for int::range(1, 10) |i| { ret i; } } Has a very different meaning from: fn f() { int::range(1, 10) |i| { ret i; } } IMHO this is likely to be pretty confusing. Also, eliminating "do" makes this ambiguous: spawn() || { ... } Is ambiguous with bitwise-or. This is also ambiguous: spawn || { ... } In any case, I think this looks nicer: do spawn { ... } Patrick From pwalton at mozilla.com Thu Jun 7 14:28:48 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 07 Jun 2012 14:28:48 -0700 Subject: [rust-dev] I am confused regarding implicit copies In-Reply-To: <4FD111E4.2020608@gmail.com> References: <4FD111E4.2020608@gmail.com> Message-ID: <4FD11D10.1010703@mozilla.com> On 6/7/12 1:41 PM, Gareth Smith wrote: > Hi Rust-Dev, > > I have recently (using the latest rust from github) encountered some new > warnings about "implicitly copying a non-implicitly-copyable value". I > believe this is due to the fix for > https://github.com/mozilla/rust/issues/2450. > > This warning seems to pop up all over the place because, as the bug > points out, vecs/strs are in-fact copied rather a lot (at least in the > rust I have written). I think that in some places I can restructure the > code to avoid copies, but that still leaves many places where I guess I > need to either add a `copy` or just ignore the warning (or turn it off). > I am worried that I will have to litter my code with `copy`. Use @[int] instead of [int] or the new dvec to avoid copies. You can also use region pointers (&). In practice copies hurt Rust performance a *lot*. Copies of vectors and strings are extremely expensive, and often make our performance drop way below even dynamically typed, interpreted languages. > The bug above mentions that the warning has been disabled for [Mozilla's] existing projects. So my question is: what is the long-term plan here? Will Mozilla's projects be restructured to avoid copying strs/vecs, or to add `copy` where it is not possible? Will the new vecs/strs make this a non-issue somehow (are vecs/strs still unique in the new scheme?)? The long term plan is: * Introduce the new vectors and strings and make stack vectors the default, drastically reducing the number of unique vectors and strings. * Only use unique vectors for vectors that are designed to cross from task to task. * Clean up all copies from the existing Rust projects. Patrick From erick.tryzelaar at gmail.com Thu Jun 7 15:03:23 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Thu, 7 Jun 2012 15:03:23 -0700 Subject: [rust-dev] I am confused regarding implicit copies In-Reply-To: <4FD11D10.1010703@mozilla.com> References: <4FD111E4.2020608@gmail.com> <4FD11D10.1010703@mozilla.com> Message-ID: On Thu, Jun 7, 2012 at 2:28 PM, Patrick Walton wrote: > > Use @[int] instead of [int] or the new dvec to avoid copies. You can also > use region pointers (&). Given this, should we replace things like std::map::str_hash to take boxed strings? That's one of my big source of warnings. From pwalton at mozilla.com Thu Jun 7 15:11:41 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 07 Jun 2012 15:11:41 -0700 Subject: [rust-dev] I am confused regarding implicit copies In-Reply-To: References: <4FD111E4.2020608@gmail.com> <4FD11D10.1010703@mozilla.com> Message-ID: <4FD1271D.1070609@mozilla.com> On 6/7/12 3:03 PM, Erick Tryzelaar wrote: > Given this, should we replace things like std::map::str_hash to take > boxed strings? That's one of my big source of warnings. Hmm, that might well be a good idea. Might even speed up rustc a lot! It does make sense to *allow* hashmaps to take unique strings, I think, for performance-critical code or for hashmaps that need to be sent between threads. Usually you'd want to move in the strings when doing lookups in this case. But clearly that's inconvenient for most use cases. Patrick From erick.tryzelaar at gmail.com Thu Jun 7 15:14:06 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Thu, 7 Jun 2012 15:14:06 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD11CD7.80104@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> Message-ID: On Thu, Jun 7, 2012 at 2:27 PM, Patrick Walton wrote: > On 6/7/12 2:20 PM, Gareth Smith wrote: > > If you allow all block lambdas to have early returns with "ret", then this: > > ? ?fn f() { > ? ? ? ?for int::range(1, 10) |i| { > ? ? ? ? ? ?ret i; > ? ? ? ?} > ? ?} > > Has a very different meaning from: > > ? ?fn f() { > ? ? ? ?int::range(1, 10) |i| { > ? ? ? ? ? ?ret i; > ? ? ? ?} > ? ?} > > IMHO this is likely to be pretty confusing. > > Also, eliminating "do" makes this ambiguous: > > ? ?spawn() || { > ? ? ? ?... > ? ?} > > Is ambiguous with bitwise-or. This is also ambiguous: > > ? ?spawn || { > ? ? ? ?... > ? ?} > > In any case, I think this looks nicer: > > ? ?do spawn { > ? ? ? ?... > ? ?} To throw one other option out there, we do support breaking out of a closure with the "fn@" closure syntax: ``` fn foo(x: int, f: fn(int)) { f(x); } fn main() { foo(5, fn@(x: int) { #error("%?", x); if x == 5 { ret } #error("%?", x); }); foo(6, fn@(x: int) { #error("%?", x); if x == 5 { ret } #error("%?", x); }); } ``` (As an aside, it sure would be nice if the fn@ closures inferred their types...) From niko at alum.mit.edu Thu Jun 7 15:32:40 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 07 Jun 2012 15:32:40 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> Message-ID: <4FD12C08.8060505@alum.mit.edu> On 6/7/12 3:14 PM, Erick Tryzelaar wrote: > (As an aside, it sure would be nice if the fn@ closures inferred their types...) I wrote this code. I only didn't push it because I couldn't decide what to do with unspecified return types. i.e., should `fn@() { 3 }` have an inferred return type of `int`, or be an error (because the return type is `()`)? Niko From erick.tryzelaar at gmail.com Thu Jun 7 15:47:51 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Thu, 7 Jun 2012 15:47:51 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD12C08.8060505@alum.mit.edu> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD12C08.8060505@alum.mit.edu> Message-ID: On Thu, Jun 7, 2012 at 3:32 PM, Niko Matsakis wrote: > > I wrote this code. ?I only didn't push it because I couldn't decide what to > do with unspecified return types. ?i.e., should `fn@() { 3 }` have an > inferred return type of `int`, or be an error (because the return type is > `()`)? Coming from the felix/ocaml world, I'm a big fan of inference :) Any chance we could infer the return type here, and on normal function declarations as well? From graydon at mozilla.com Thu Jun 7 15:52:05 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 07 Jun 2012 15:52:05 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD12C08.8060505@alum.mit.edu> Message-ID: <4FD13095.2080105@mozilla.com> On 12-06-07 3:47 PM, Erick Tryzelaar wrote: > Coming from the felix/ocaml world, I'm a big fan of inference :) Any > chance we could infer the return type here, and on normal function > declarations as well? The return type when used as an expression, maybe. When declared as an item, I'd like to keep the signatures mandatory. That was a very intentional choice. Both for keeping inference function-at-a-time (fewer ways to go wrong, more locality of errors, easier to make parallel) and for keeping the text reasonably explanatory of the types flowing through functions. I believe the whole-program-inference systems go a bit too far, make life too hard for maintenance programmers. -Graydon From erick.tryzelaar at gmail.com Thu Jun 7 15:57:17 2012 From: erick.tryzelaar at gmail.com (Erick Tryzelaar) Date: Thu, 7 Jun 2012 15:57:17 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD13095.2080105@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD12C08.8060505@alum.mit.edu> <4FD13095.2080105@mozilla.com> Message-ID: On Thu, Jun 7, 2012 at 3:52 PM, Graydon Hoare wrote: > > The return type when used as an expression, maybe. When declared as an item, > I'd like to keep the signatures mandatory. That was a very intentional > choice. Both for keeping inference function-at-a-time (fewer ways to go > wrong, more locality of errors, easier to make parallel) and for keeping the > text reasonably explanatory of the types flowing through functions. I > believe the whole-program-inference systems go a bit too far, make life too > hard for maintenance programmers. That sounds reasonable to me. From dteller at mozilla.com Thu Jun 7 22:27:46 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Fri, 08 Jun 2012 07:27:46 +0200 Subject: [rust-dev] Syntax tweak: Alt without pattern Message-ID: <4FD18D52.9080805@mozilla.com> Dear Rusties, I am currently writing in C++ code that involves long strings of `if ... else if ... else if ... else if ...` and it dawns to me that we can certainly sightly tweak the syntax of Rust to make such code much nicer. Consider the following extract: if (f()) { // ... } else if (g()) { // ... } else if (h()) { // ... } else { // ... } It is quite easy to get lost in such long strings of `if...else if...`. Fortunately, in Rust, this can be rewritten with more structure as alt true { true if f(): ... true if g(): ... true if h(): ... _: ... } or alt true { _ if f(): ... _ if g(): ... _ if h(): ... _: ... } However, the pattern-matching on `true` is a little confusing, and we could certainly make it nicer by allowing `alt` expressions with no condition expression and only the `if` part, as follows: alt { if f(): ... if g(): ... if h(): ... _: ... } I believe that this snippet has a more immediately visible structure than the original and is easier to read, while the syntax tweak is trivial to compile. What do you think? Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From pwalton at mozilla.com Thu Jun 7 22:30:14 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 07 Jun 2012 22:30:14 -0700 Subject: [rust-dev] Syntax tweak: Alt without pattern In-Reply-To: <4FD18D52.9080805@mozilla.com> References: <4FD18D52.9080805@mozilla.com> Message-ID: <4FD18DE6.7030009@mozilla.com> On 6/7/12 10:27 PM, David Rajchenbach-Teller wrote: > I believe that this snippet has a more immediately visible structure > than the original and is easier to read, while the syntax tweak is > trivial to compile. > > > What do you think? How about a Scheme-like "cond" macro? Patrick From graydon at mozilla.com Fri Jun 8 11:25:02 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 08 Jun 2012 11:25:02 -0700 Subject: [rust-dev] DNS Message-ID: <4FD2437E.8080608@mozilla.com> Hi, As part of some ongoing infrastructure work, I changed rust-lang.org and related DNS from one registrar to another yesterday. This was substantially less smooth a transition than I had hoped. DNS for these domains is presently disrupted. Sorry for the inconvenience. IRC, the mailing list and github are still online; just the bot, website, and (sadly) snapshot host are not resolving. I'm attempting to restore service and will post an update when it has returned. -Graydon From graydon at mozilla.com Fri Jun 8 12:43:02 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 08 Jun 2012 12:43:02 -0700 Subject: [rust-dev] DNS In-Reply-To: <4FD2437E.8080608@mozilla.com> References: <4FD2437E.8080608@mozilla.com> Message-ID: <4FD255C6.1080002@mozilla.com> On 12-06-08 11:25 AM, Graydon Hoare wrote: > I'm attempting to restore service and will post an update when it has > returned. Service appears to be restored. Let me know if you see any further hiccups. -Graydon From garethdanielsmith at gmail.com Sat Jun 9 14:24:44 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Sat, 09 Jun 2012 22:24:44 +0100 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD11CD7.80104@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> Message-ID: <4FD3BF1C.6020702@gmail.com> On 07/06/12 22:27, Patrick Walton wrote: > If you allow all block lambdas to have early returns with "ret", then > this: > > fn f() { > for int::range(1, 10) |i| { > ret i; > } > } > > Has a very different meaning from: > > fn f() { > int::range(1, 10) |i| { > ret i; > } > } > > IMHO this is likely to be pretty confusing. Fair enough, I can see where you are coming from. > > Also, eliminating "do" makes this ambiguous: > > spawn() || { > ... > } > > Is ambiguous with bitwise-or. This is also ambiguous: > > spawn || { > ... > } As I understand it, given point 2 of the proposal, the above code would not be valid. Instead it would look like: spawn(|| { ... }); Is that correct? If so, would the semantics of the directly above be identical to: do spawn { ... } ? -Gareth From pwalton at mozilla.com Sat Jun 9 15:43:39 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 09 Jun 2012 15:43:39 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD3BF1C.6020702@gmail.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD3BF1C.6020702@gmail.com> Message-ID: <4FD3D19B.8020101@mozilla.com> On 06/09/2012 02:24 PM, Gareth Smith wrote: > As I understand it, given point 2 of the proposal, the above code would > not be valid. Instead it would look like: > > spawn(|| { > ... > }); > > Is that correct? If so, would the semantics of the directly above be > identical to: > > do spawn { > ... > } > > ? Yes, except that continue/break/ret would be valid in the latter but not the former. Patrick From tjpalmer at tjpalmer.com Sat Jun 9 15:58:39 2012 From: tjpalmer at tjpalmer.com (Thomas Palmer) Date: Sat, 9 Jun 2012 17:58:39 -0500 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD3D19B.8020101@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD3BF1C.6020702@gmail.com> <4FD3D19B.8020101@mozilla.com> Message-ID: Hello, I'm new here, just someone trying to like Rust but not fully convinced yet. That makes me a nobody, but I figured I'd throw in my two cents. The recent 'do' discussion reminds me of some of my own favorite syntax ideas on this matter. While Ruby's |args| syntax is somewhat recognizable by now, I think the following is nice: whatever(do(args) { ... }); Or that could be used like so as a trailing argument: whatever do(args) { ... } Or some variation on that theme. This would give fn@ blocks and do blocks (stack closures) both with keywords. This makes syntax differences lest jarring, as in this example from the tutorial. Original: fn call_twice(f: fn()) { f(); f(); } call_twice({|| "I am a stack closure"; }); call_twice(fn@() { "I am a boxed closure"; }); fn bare_function() { "I am a plain function"; } call_twice(bare_function); Proposed syntax: fn call_twice(f: fn()) { f(); f(); } call_twice(do() { "I am a stack closure"; }); call_twice(fn@() { "I am a boxed closure"; }); fn bare_function() { "I am a plain function"; } call_twice(bare_function); In addition to eliding the {} for single expressions, perhaps empty parens could also be elided, as in 'call_twice do {"I am a stack closure";}' or something like that. I think 'do' is prettier, carries an automatic name, and would be more consistent than the current (do plus ||) proposals. Anyway, I agree with ret/break/continue treating things as blocks only for the trailing {} case. Well, as I said, I'm just a many-year migrant trying to figure out what I'd really like to use while failing to have the commitment/time to make something of my own. Just wanted to give my two cents (or maybe just half a cent) on this syntax. - Tom On Sat, Jun 9, 2012 at 5:43 PM, Patrick Walton wrote: > On 06/09/2012 02:24 PM, Gareth Smith wrote: > >> As I understand it, given point 2 of the proposal, the above code would >> not be valid. Instead it would look like: >> >> spawn(|| { >> ... >> }); >> >> Is that correct? If so, would the semantics of the directly above be >> identical to: >> >> do spawn { >> ... >> } >> >> ? >> > > Yes, except that continue/break/ret would be valid in the latter but not > the former. > > Patrick > > ______________________________**_________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev > -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Sat Jun 9 16:22:15 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 09 Jun 2012 16:22:15 -0700 Subject: [rust-dev] agenda for next tuesday meeting Message-ID: <4FD3DAA7.5000105@alum.mit.edu> I guess you've all figured out the pattern by now: https://etherpad.mozilla.org/Meeting-weekly-2012-06-12 Niko From steven099 at gmail.com Sat Jun 9 22:33:02 2012 From: steven099 at gmail.com (Steven Blenkinsop) Date: Sun, 10 Jun 2012 01:33:02 -0400 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD3D19B.8020101@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD3BF1C.6020702@gmail.com> <4FD3D19B.8020101@mozilla.com> Message-ID: On Saturday, June 9, 2012, Patrick Walton wrote: > On 06/09/2012 02:24 PM, Gareth Smith wrote: > >> As I understand it, given point 2 of the proposal, the above code would >> not be valid. Instead it would look like: >> >> spawn(|| { >> ... >> }); >> >> Is that correct? If so, would the semantics of the directly above be >> identical to: >> >> do spawn { >> ... >> } >> >> ? >> > > Yes, except that continue/break/ret would be valid in the latter but not > the former. > > Patrick > If you can use break/continue/whatever to return early, does this mean you can break with a return value? How would this interact syntactically with labels if they were ever added? Also, am I correct that ret will only work if the block is passed as a stack closure, since otherwise the continuation could escape? It seems to me like this non-local return could have other issues as well, though I also feel that it's important to be able to do it. It has been pointed out that "break" may be misleading, since you don't actually break from the do expression as might be expected. It seems what you're trying to do is yield a result to the caller and allow it to continue, so something along the lines of "yield" or "continue" might express the idea better. "res" for "result" could work too, but it's similar enough to "ret" to potentially cause confusion. -------------- next part -------------- An HTML attachment was scrubbed... URL: From niko at alum.mit.edu Sun Jun 10 08:08:02 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sun, 10 Jun 2012 08:08:02 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment Message-ID: <4FD4B852.7020903@alum.mit.edu> This was also posted on my blog, but I wanted to make sure people saw it, as I'd like to discuss this on Tuesday, because one of the logical next steps for the regions work is to begin deciding precisely what to do about the types of identifiers in alts. Niko ---- http://smallcultfollowing.com/babysteps/blog/2012/06/10/unifying-patterns-in-alts-and-lets/ This is a proposal to unify the mechanics of `alt` and destructuring assignment. It was born out of discussion between erickt, pcwalton, and I amidst various bugs in the bug tracker but I wanted to float it around to a larger audience. ## Today Currently, `alt` always creates implicit references into the structure you are alting over. For example, in this code: let p = {x:1, y:2}; alt p { {x: x, y: y} { ... } } the bound variables `x` and `y` are actually pointers to the interior of `p`. In addition, one can use let to match infallible patterns: let p = {x: 3, y: 4}; let {x: x, y: y} = p; Here, however, the values are actually not pointers to the interior of `p` but rather are copied out of `p`. ## Shortcomings Sometimes it is useful to get a pointer to the interior of a pattern in a `let` and sometimes it is useful to copy out in an `alt`, but the current system does not let you choose. In addition, it is often very useful to *move* out of the discriminant in an `alt`, but that is not currently an option. The matter of copying out of an `alt` is somewhat more important under the new borrowck rules. This is because the older system would implicitly copy out of the discriminant when it appeared that the value being matched was residing in mutable memory or that it might be invalidated in some way. This is no longer the case, which means that more explicit copies are required in order to match against the contents of an enum or unique pointer that lives in mutable memory (I am actively working on a blog post / tutorial about the details of this new check). ## The proposal The proposal is to distinguish between *copying bindings* and *reference bindings*. A copying binding, indicating by either a variable name alone (`x`) copies/moves the value out of the discriminant. A reference binding, indicated using `*x` (see some notes on syntax below), takes the address of the value within the discriminant. For types that are not implicitly copyable, copying bindings must be preceded by a `copy` keyword (`copy x`). Here is an example of creating references into the interior: let p = {x:1, y:2}; alt p { {x: *x, y: *y} { ... } } And the same example using `let`: let p = {x:1, y:2}; let {x: *x, y: *y} = p; Here is an example of copying the values out: let p = {x:1, y:2}; alt p { {x: x, y: y} { ... } } let {x: x, y: y} = p; And finally an example that requires an explicit `copy` keyword: let p = {x: ~1, y: ~2}; alt p { {x: copy x, y: copy y} { .... } } let {x: copy x, y: copy y} = p; Here, a pattern like `{x: x, y: y}` would result in a warning because a unique value is being copied (which requires memory allocation and is a performance red-flag). ## Moves As a bonus, this idea transparently permits data to be *moved* as part of an `alt` (hat tip to pcwalton for this observation). For example, the function called `option::unwrap()` could be written as follows (here I am assuming a unary move operator; something generally agreed to but not yet implemened): fn unwrap(-opt: option) -> T { alt move opt { some(v) { ret v; } none { fail; } } } Basically, if the discriminant is *moved* into the alt then its pieces can be carved up and moved into the bindings. This is equivalent to lets like the following (which is legal today): let (x, y) = move v; For symmetry, the `move` keyword could be permitted on copying bindings (`move x`). It seems though that this would always be superfluous except in the case of last use, where it could serve as useful documentation: fn unwrap(-opt: option) -> T { alt opt { some(move v) { ret v; } none { fail; } } } ## Syntax I borrowed the `*identifier` syntax from Cyclone. However, I would personally prefer `&identifier`, as it is more reminiscent of the "take the address of" operator. However, I presume that `&P` will eventually become a pattern, like `@P` and `~P` today (currently, there is no pattern to match against an `&T` type). There was some talk at various points of making unsafe pointers be a special kind of lifetime, like `static`, so that one would write `*unsafe T` in which case `*r.T` could replace `&r.T` as the type of safe references. That would in turn permit switching the role of `&` and `*` in patterns. From pwalton at mozilla.com Sun Jun 10 11:30:15 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 10 Jun 2012 11:30:15 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD4B852.7020903@alum.mit.edu> References: <4FD4B852.7020903@alum.mit.edu> Message-ID: <4FD4E7B7.4020904@mozilla.com> On 06/10/2012 08:08 AM, Niko Matsakis wrote: > This was also posted on my blog, but I wanted to make sure people saw > it, as I'd like to discuss this on Tuesday, because one of the logical > next steps for the regions work is to begin deciding precisely what to > do about the types of identifiers in alts. I like this. The only concern, as a comment pointed out, is that "*" might be slightly confusing; maybe "ref" is better. Patrick From graydon at mozilla.com Sun Jun 10 12:14:41 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Sun, 10 Jun 2012 12:14:41 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD4E7B7.4020904@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> Message-ID: <4FD4F221.7040001@mozilla.com> On 10/06/2012 11:30 AM, Patrick Walton wrote: > I like this. The only concern, as a comment pointed out, is that "*" > might be slightly confusing; maybe "ref" is better. I like it too. Though I wonder if the ambiguity between &-as-a-reference-taker and &-as-a-pattern is actually problematic. Consider two cases (assuming we use & here): #1: let foo = {1,2}; let {&a, &b} = foo; #2: let x = 1; let y = 2; let foo = {&x, &y}; let {&a, &b} = foo; It seems to me that in both cases you're introducing two variables, a and b, of type &int. In #1 they point into foo, using the & to "take references" to the record components; in #2 they point to x and y respectively, using the & to "match against" the existing &-types inside the record. I think to a user these are "intuitively" compatible interpretations, and supporting both depending on the type being matched against would not lead to any deep surprises; one could always force the "take a reference" form for #2 by writing it with a double-ampersand (something the user might even guess to do): let x = 1; let y = 2; let foo = {&x, &y}; let {&&a, &&b} = foo; Here a and b are references-to-references, type &&int. Which is, conveniently, just how &&int reads anyway. They could also force the _opposite_ interpretation (that is, "deref the & values") using a type annotation (at least in let-patterns): let x = 1; let y = 2; let foo = {&x, &y}; let {a, b} : {int,int} = foo; The only practical (as in "maybe hard to implement") difference is that the &-symbol _would_ have a syntactically ambiguous denotation in patterns, that would be resolved one way or another during typechecking. But patterns often have type-indeterminate parts they need to pick up from the other variables at play in inference, and it seems to me a plausible special-case in the unification rule on &-patterns, and this might work ok. Maybe I'm being naive though. I don't really know that code. Comments from anyone who does? -Graydon From pwalton at mozilla.com Sun Jun 10 15:24:42 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sun, 10 Jun 2012 15:24:42 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD4F221.7040001@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD4F221.7040001@mozilla.com> Message-ID: <4FD51EAA.6010504@mozilla.com> On 06/10/2012 12:14 PM, Graydon Hoare wrote: > On 10/06/2012 11:30 AM, Patrick Walton wrote: > >> I like this. The only concern, as a comment pointed out, is that "*" >> might be slightly confusing; maybe "ref" is better. > > I like it too. Though I wonder if the ambiguity between > &-as-a-reference-taker and &-as-a-pattern is actually problematic. > Consider two cases (assuming we use & here): > > #1: > > let foo = {1,2}; > let {&a, &b} = foo; > > #2: > > let x = 1; > let y = 2; > let foo = {&x, &y}; > let {&a, &b} = foo; > > It seems to me that in both cases you're introducing two variables, a > and b, of type &int. In #1 they point into foo, using the & to "take > references" to the record components; in #2 they point to x and y > respectively, using the & to "match against" the existing &-types inside > the record. But, as I understand it, in #2 they would actually copy out the values. So in #1, a : &int and b : &int, but in #2, a : int and b : int. cf: let x = 1; // x : int let y = 2; // y : int let foo = (@x, @y); // foo : (@int, @int) let (@a, @b) = foo; // a: int and b: int Patrick From niko at alum.mit.edu Mon Jun 11 15:02:17 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 11 Jun 2012 15:02:17 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD4E7B7.4020904@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> Message-ID: <4FD66AE9.7040609@alum.mit.edu> On 6/10/12 11:30 AM, Patrick Walton wrote: > I like this. The only concern, as a comment pointed out, is that "*" > might be slightly confusing; maybe "ref" is better. Yes, gasche stated that using a keyword like `copy` and a sigil like `*` seemed inconsistent. I can see that, I suppose, though I think that using a keyword like `ref` that appears nowhere else in the language seems even more inconsistent, not to mention heavyweight (who wants to write `let (ref x, ref y) = pair`?). I assume that Cyclone's reasoning with `*x` was that?like other patterns?it's the inverse of what you would do to create the value. That is, if the value is being matched is 3, and the pattern is `*x`, then `x` is bound to something such that writing `*x` gives you 3. This is consistent with other patterns (e.g., if the value is `@3`, and you write the pattern `@x`, then `x` is bound to something where writing `@x` gives you `@3`). Niko From graydon at mozilla.com Tue Jun 12 10:45:21 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 12 Jun 2012 10:45:21 -0700 Subject: [rust-dev] Syntax tweak: Alt without pattern In-Reply-To: <4FD18D52.9080805@mozilla.com> References: <4FD18D52.9080805@mozilla.com> Message-ID: <4FD78031.9000802@mozilla.com> On 12-06-07 10:27 PM, David Rajchenbach-Teller wrote: > What do you think? alt would need to special-case its lookahead to try to figure out if the block was a pattern block or an expresison block. But you can make the 'alt true' a little less weird-looking using unit. I think this reads tolerably, and can be written today: alt () { _ if f() { ... } _ if g() { ... } _ { ... } } I guess we could make the arm-parser assume _ as a pattern, if it sees an 'if' token there where it's expecting a pattern, letting you strip that part. Then you'd get: alt () { if f() { ... } if g() { ... } _ { ... } } Good enough? -Graydon From niko at alum.mit.edu Tue Jun 12 11:09:01 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 12 Jun 2012 11:09:01 -0700 Subject: [rust-dev] Syntax tweak: Alt without pattern In-Reply-To: <4FD78031.9000802@mozilla.com> References: <4FD18D52.9080805@mozilla.com> <4FD78031.9000802@mozilla.com> Message-ID: <4FD785BD.6090504@alum.mit.edu> On 6/12/12 10:45 AM, Graydon Hoare wrote: > alt () { > if f() { ... } > if g() { ... } > _ { ... } > } This looks good to me. I like the idea of alting on `()`. Niko From dteller at mozilla.com Tue Jun 12 12:13:23 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Tue, 12 Jun 2012 21:13:23 +0200 Subject: [rust-dev] Syntax tweak: Alt without pattern In-Reply-To: <4FD78031.9000802@mozilla.com> References: <4FD18D52.9080805@mozilla.com> <4FD78031.9000802@mozilla.com> Message-ID: <4FD794D3.3080009@mozilla.com> On 6/12/12 7:45 PM, Graydon Hoare wrote: > I guess we could make the arm-parser assume _ as a pattern, if it sees > an 'if' token there where it's expecting a pattern, letting you strip > that part. Then you'd get: > > alt () { > if f() { ... } > if g() { ... } > _ { ... } > } > > Good enough? I believe it is. Cheers, David -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From graydon at mozilla.com Tue Jun 12 13:41:55 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 12 Jun 2012 13:41:55 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD66AE9.7040609@alum.mit.edu> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> Message-ID: <4FD7A993.4080005@mozilla.com> On 12-06-11 3:02 PM, Niko Matsakis wrote: > On 6/10/12 11:30 AM, Patrick Walton wrote: >> I like this. The only concern, as a comment pointed out, is that "*" >> might be slightly confusing; maybe "ref" is better. > > Yes, gasche stated that using a keyword like `copy` and a sigil like `*` > seemed inconsistent. I can see that, I suppose, though I think that > using a keyword like `ref` that appears nowhere else in the language > seems even more inconsistent, not to mention heavyweight (who wants to > write `let (ref x, ref y) = pair`?). > > I assume that Cyclone's reasoning with `*x` was that?like other > patterns?it's the inverse of what you would do to create the value. It's not the inverse; the expression and pattern forms are _the same_. That is, to eliminate a record {x:foo} we write a pattern {x:foo} and recover foo. To match a @foo expression, we write the pattern @foo. The operational inverse of @ is * and {x:foo} is .x. But we're not talking inverses. What you're doing is proposing -- a bit of a stretch -- that a user's intuition is that for any expression E, they "effectively" wrote *P for some imaginary pointer P, and they can recover that pointer by matching against the written-the-same-way pattern *P. Which is ... mathematically tidy, certainly hits the correctness note, but it feels to me like a bit of a footgun. Somehow no matter how many times I read it, when I see: let *x = foo; I expect this means that foo is a pointer and x is bound to the pointee. I know that makes no sense. I'll try to inhibit that reflex and see how it goes. I'm also concerned about the perf implication of copying by default. I guess it might be ok if the implicit-copies warning is turned on by default. Which we'll get to. It might slow things down quite a bit until that time... Still, this is important work and these objections are more like uneasy feelings than fixes for same. I'd say go ahead with it and see how it fares. Worst case we have to revisit. -Graydon From niko at alum.mit.edu Tue Jun 12 14:53:56 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 12 Jun 2012 14:53:56 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD7A993.4080005@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> Message-ID: <4FD7BA74.1040901@alum.mit.edu> I don't disagree with you on either point. In fact, when I first saw Cyclone's syntax I thought "Huh?? That looks completely wrong!" When I thought hard enough about it, I kind of figured where they must be coming from, but I wouldn't call it intuitive. As I wrote somewhere, I think what I would like most (consistency be damned) is to 1. Write region pointers as *T, not &T, and hence write region patterns as *P 2. Write unsafe pointers as *unsafe.T (i.e., a special region) 3. Write by-ref bindings as `let (&x, &y) = pair` I also like "by-ref by default" but I don't know a way to combine that with the ability to write patterns in let. I guess we could just let alt and let patterns have different defaults. So you'd write: let (&x, &y) = pair // by ref let (x, y) = pair // copies alt pair { (x, y) ... } // by ref alt pair { (copy x, copy y) ... } // copies In that case, I guess we'd want to add a "move" binding. Probably these two would be equivalent: alt move pair { (move x, move y) ... } // moves That begs the question of what the heck this means: alt move pair { (copy x, copy y) ... } // copies? moves? Here there would never be a need to copy but I suppose we could copy nonetheless. Or else we just move even though they said copy. Niko On 6/12/12 1:41 PM, Graydon Hoare wrote: > On 12-06-11 3:02 PM, Niko Matsakis wrote: >> On 6/10/12 11:30 AM, Patrick Walton wrote: >>> I like this. The only concern, as a comment pointed out, is that "*" >>> might be slightly confusing; maybe "ref" is better. >> >> Yes, gasche stated that using a keyword like `copy` and a sigil like `*` >> seemed inconsistent. I can see that, I suppose, though I think that >> using a keyword like `ref` that appears nowhere else in the language >> seems even more inconsistent, not to mention heavyweight (who wants to >> write `let (ref x, ref y) = pair`?). >> >> I assume that Cyclone's reasoning with `*x` was that?like other >> patterns?it's the inverse of what you would do to create the value. > > It's not the inverse; the expression and pattern forms are _the same_. > That is, to eliminate a record {x:foo} we write a pattern {x:foo} and > recover foo. To match a @foo expression, we write the pattern @foo. > The operational inverse of @ is * and {x:foo} is .x. But we're not > talking inverses. > > What you're doing is proposing -- a bit of a stretch -- that a user's > intuition is that for any expression E, they "effectively" wrote *P > for some imaginary pointer P, and they can recover that pointer by > matching against the written-the-same-way pattern *P. Which is ... > mathematically tidy, certainly hits the correctness note, but it feels > to me like a bit of a footgun. Somehow no matter how many times I read > it, when I see: > > let *x = foo; > > I expect this means that foo is a pointer and x is bound to the > pointee. I know that makes no sense. I'll try to inhibit that reflex > and see how it goes. > > I'm also concerned about the perf implication of copying by default. I > guess it might be ok if the implicit-copies warning is turned on by > default. Which we'll get to. It might slow things down quite a bit > until that time... > > Still, this is important work and these objections are more like > uneasy feelings than fixes for same. I'd say go ahead with it and see > how it fares. Worst case we have to revisit. > > -Graydon > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From graydon at mozilla.com Tue Jun 12 15:05:54 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 12 Jun 2012 15:05:54 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD7BA74.1040901@alum.mit.edu> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> Message-ID: <4FD7BD42.9020004@mozilla.com> On 12-06-12 2:53 PM, Niko Matsakis wrote: > 1. Write region pointers as *T, not &T, and hence write region patterns > as *P > 2. Write unsafe pointers as *unsafe.T (i.e., a special region) > 3. Write by-ref bindings as `let (&x, &y) = pair` Aha. I hadn't seen all these points juxtaposed. It looks .. mostly really good, with one exception: it makes writing C bindings a bit noisy, since they have many unsafe pointers involved. I guess in general a parameter of type *T is implicitly region-variable-qualified so it'll unify with whatever region is supplied, so maybe arg-position is fine; but return-position needs help. Maybe a rule that any pointer returned form an 'extern' function is implicitly in the unsafe region? (Maybe call it the 'extern' region? hmm) Anyway, I like this. This is a good target to aim for. Though perhaps .. given that you're saying you _do_ want & in a pattern to "eventually" mean by-ref binding, maybe just make it mean that from the get-go, and defer region-pointer patterns altogether until they can be written unambiguously as *, as you say here. Thoughts? > I also like "by-ref by default" but I don't know a way to combine that > with the ability to write patterns in let. I guess we could just let alt > and let patterns have different defaults. Yeah .. probably too muddy. I think if we get the above working eventually, along with the implicit-copies warning, it is probably ok. -Graydon From niko at alum.mit.edu Tue Jun 12 15:28:26 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 12 Jun 2012 15:28:26 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD7BD42.9020004@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> Message-ID: <4FD7C28A.7030206@alum.mit.edu> On 6/12/12 3:05 PM, Graydon Hoare wrote: > Anyway, I like this. This is a good target to aim for. Though perhaps > .. given that you're saying you _do_ want & in a pattern to > "eventually" mean by-ref binding, maybe just make it mean that from > the get-go, and defer region-pointer patterns altogether until they > can be written unambiguously as *, as you say here. Thoughts? Seeing as we're not really using region types yet, it seems like NOW is the time to decide if we want to move to writing them as *T and so forth. I agree there is no sense in implement a change in patterns to go to an intermediate state that we already know is suboptimal. It's a good point that *unsafe.T is rather noisy. I thought that was ok, but I wasn't thinking about the fact that it will appear often in FFIs. I am not sure how this would work out in practice. As you say, region ptrs in argument position are ok, but region ptrs in return position would yield inappropriate errors when calling the function. Niko From pwalton at mozilla.com Tue Jun 12 15:31:49 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Tue, 12 Jun 2012 15:31:49 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD7C28A.7030206@alum.mit.edu> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> <4FD7C28A.7030206@alum.mit.edu> Message-ID: <4FD7C355.8060107@mozilla.com> On 6/12/12 3:28 PM, Niko Matsakis wrote: > It's a good point that *unsafe.T is rather noisy. I thought that was ok, > but I wasn't thinking about the fact that it will appear often in FFIs. > I am not sure how this would work out in practice. As you say, region > ptrs in argument position are ok, but region ptrs in return position > would yield inappropriate errors when calling the function. What if pointers in native function signatures were implicitly unsafe? C has no concept of regions anyhow... Patrick From graydon at mozilla.com Tue Jun 12 15:33:35 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Tue, 12 Jun 2012 15:33:35 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD7C28A.7030206@alum.mit.edu> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> <4FD7C28A.7030206@alum.mit.edu> Message-ID: <4FD7C3BF.3010408@mozilla.com> On 12-06-12 3:28 PM, Niko Matsakis wrote: > Seeing as we're not really using region types yet, it seems like NOW is > the time to decide if we want to move to writing them as *T and so > forth. I agree there is no sense in implement a change in patterns to go > to an intermediate state that we already know is suboptimal. Totally agree. Though it'll make my skin crawl to see *foo all over rust code, I'll learn to think of them as "proven-live pointers" eventually :) > It's a good point that *unsafe.T is rather noisy. I thought that was ok, > but I wasn't thinking about the fact that it will appear often in FFIs. > I am not sure how this would work out in practice. As you say, region > ptrs in argument position are ok, but region ptrs in return position > would yield inappropriate errors when calling the function. Try sketching some code in a buffer, see how it looks. Might be possible to come up with an abbreviation (!T perhaps, or the old unused sigil ?T maybe?), might be possible for inference and a couple rules about the boundaries of extern functions to fill in the details. -Graydon From graydon at mozilla.com Wed Jun 13 10:09:19 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 13 Jun 2012 10:09:19 -0700 Subject: [rust-dev] Please read: 'incoming' branch and push policy Message-ID: <4FD8C93F.4030901@mozilla.com> Hi, Yesterday mozilla's staff rust developers agreed to alter the git workflow for the mozilla/rust repository, to help ensure master always remains green (and cut down on the amount of anxious tree-watching and panicked scrambles to unblock others). Until further notice, the policy is outlined here: https://github.com/mozilla/rust/wiki/Note-git-workflow Please ask questions if you have any. We've switched to working this way and ask that anyone else developing against the mozilla/rust repo do the same. Briefly: - Develop against 'master' if you want an always-green baseline. - Develop against 'incoming' if you want a current-during-the-day baseline. It might not work though. - In _both_ cases, rebase and target pull requests against 'incoming' when you are ready for integration. In more detail: - Pushes to 'incoming' are ok even if it's on fire. Check back to see how your work fared. Be prepared to be backed out. - There is a new role, sheriff, who is the only person authorized to push to 'master' during the day. This is informally enforced. - Sheriff's job is to help 'incoming' achieve green-ness regularly (once a day at least) then integrate to 'master'. Current sheriff for the tree will be written in the IRC channel topic. - Pushes to 'master' are only done by the sheriff, when/if there's an all-green checkpoint on 'incoming'. - The sheriff will back out any unaddressed burning on 'incoming' if it sits there for "too long". That is a judgment call. - If you're curious about why the tree is on fire and can't figure it out, ask the sheriff. There may be some other breakage in progress of being fixed-or-backed-out, that will make sense. - The sheriff will inform anyone whose change was backed out, via email. Make sure the email address you commit under goes to you. - At some point we might make the sheriff into a robot, but we don't quite have the logic worked out for that yet. Thanks, -Graydon From garethdanielsmith at gmail.com Wed Jun 13 11:21:51 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Wed, 13 Jun 2012 19:21:51 +0100 Subject: [rust-dev] Syntax tweak: Alt without pattern In-Reply-To: <4FD18D52.9080805@mozilla.com> References: <4FD18D52.9080805@mozilla.com> Message-ID: <4FD8DA3F.9020801@gmail.com> David, On the off-chance that you have not considered this, how about factoring the long if-else chain into a function that uses early returns, like: fn (...) -> .. { if (f()) { // ... ret; } if (g()) { // ... ret; } if (h()) { // ... ret; } // ... } I don't think it is a syntactically pretty as what you propose, but it does avoid adding a possibly rarely-used special case to the syntax. Gareth On 08/06/12 06:27, David Rajchenbach-Teller wrote: > Dear Rusties, > > I am currently writing in C++ code that involves long strings of `if > ... else if ... else if ... else if ...` and it dawns to me that we can > certainly sightly tweak the syntax of Rust to make such code much nicer. > > Consider the following extract: > > if (f()) { > // ... > } else if (g()) { > // ... > } else if (h()) { > // ... > } else { > // ... > } > From niko at alum.mit.edu Wed Jun 13 16:15:33 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 13 Jun 2012 16:15:33 -0700 Subject: [rust-dev] a vision for vectors Message-ID: <4FD91F15.9010108@alum.mit.edu> Hello, I wanted to check something. We are working on the Great Change to a more flexible vector system and I want to outline the design that's in my head. This has some implications for How Efficient Rust Code Is Written, so I wanted to make sure we were all on the same page. *Implications for writing efficient Rust* I figured I'd just start with the implications for writing Rust. Currently, to build up a vector, we rely upon an idiom like: let mut v = []; for some loop { v += [elt]; } Now, often, such loops can (and should) be written using a higher-order function (e.g., map, filter). But sometimes not. In such cases, under the new regime, the recommended idiom would be: let dv = dvec(); for some loop { v.push(elt); } let v = dvec::unwrap(dv); // if necessary, convert to a vector Actually the name `dvec()` (dynamic vector) will probably change?perhaps to vecbuf? mvec? suggestions welcome?but you get the idea. The same would eventually apply to building up strings. Basically, the idea is that we have "builder" types for vectors and strings. These builder types will overallocate and use dirty tricks to achieve reasonable performance. Using convenience operators like `+` will not do such things. *Details* The actual implementation strategy is that the representation of vectors will stay mostly the same as it is now. However, when the compiler allocates vectors, it will always do so for precisely the size they need to be (fill == alloc, in our vector rep). There will be internal functions (vec::alloc_empty_with_capacity() or something) that allocate an empty vector but with a large capacity and unsafe functions that can be used to set the length. These can be used by dvec-like classes but also by routines like `vec::map()`. Most of this exists today. The only real thing that changes is that we take *away* the tricks the compiler does for `+=`. *Motivation* Part of the motivation for this change is that when you have task-local vectors, the tricks we play now where we treat vectors both as values and as things that can be updated in place don't work so well (this is precisely why the move was made to unique vectors in the first place, as I understand it). However, task-local vectors are good for a number of reasons (cheaper copies; easier to ensure memory safety), so I expect we'll wind up using them a fair amount: to obtain reliably good performance, then, a builder like `dvec` can be used that encapsulates the task-local vector pointer until construction is complete, making it safe to append to it in place. Another motivation is that it is part of a general trend to push intelligence out of the compiler and into libraries where possible. We can build vector append using overloaded operators. This also ensures that end-users will be able to design efficient libraries and so forth. Moving things like `vector +` into libraries also simplifies the type checker, as we can draw on impls to handle all the various cases (@ vs ~ vectors, imm vs mut vectors, and so forth). Niko From banderson at mozilla.com Wed Jun 13 16:31:42 2012 From: banderson at mozilla.com (Brian Anderson) Date: Wed, 13 Jun 2012 16:31:42 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FD91F15.9010108@alum.mit.edu> References: <4FD91F15.9010108@alum.mit.edu> Message-ID: <4FD922DE.9090504@mozilla.com> On 06/13/2012 04:15 PM, Niko Matsakis wrote: > Hello, > > I wanted to check something. We are working on the Great Change to a > more flexible vector system and I want to outline the design that's in > my head. This has some implications for How Efficient Rust Code Is > Written, so I wanted to make sure we were all on the same page. > > *Implications for writing efficient Rust* > > I figured I'd just start with the implications for writing Rust. > Currently, to build up a vector, we rely upon an idiom like: > > let mut v = []; > for some loop { v += [elt]; } > > Now, often, such loops can (and should) be written using a higher-order > function (e.g., map, filter). But sometimes not. In such cases, under > the new regime, the recommended idiom would be: > > let dv = dvec(); > for some loop { v.push(elt); } > let v = dvec::unwrap(dv); // if necessary, convert to a vector This method of creating vectors originally had worse performance than the other. Is the performance problem resolved or resolvable or is vector creation just going to be expensive? From eric.holk at gmail.com Wed Jun 13 17:03:05 2012 From: eric.holk at gmail.com (Eric Holk) Date: Wed, 13 Jun 2012 17:03:05 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FD922DE.9090504@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FD922DE.9090504@mozilla.com> Message-ID: <4882A98D-6378-40C2-BF68-C85A5F4D60B1@gmail.com> I've been spending the past couple days working on moving the current vector + operator into libcore, instead of being generated by trans. It's looking like our inlining code is smart enough to make vec::push perform as well as the old += operator did. Of course, now the += operator as implemented in libcore must always do a copy on the left hand side, which means its performance is so bad as to be basically unusable. On Jun 13, 2012, at 4:31 PM, Brian Anderson wrote: > On 06/13/2012 04:15 PM, Niko Matsakis wrote: >> Hello, >> >> I wanted to check something. We are working on the Great Change to a >> more flexible vector system and I want to outline the design that's in >> my head. This has some implications for How Efficient Rust Code Is >> Written, so I wanted to make sure we were all on the same page. >> >> *Implications for writing efficient Rust* >> >> I figured I'd just start with the implications for writing Rust. >> Currently, to build up a vector, we rely upon an idiom like: >> >> let mut v = []; >> for some loop { v += [elt]; } >> >> Now, often, such loops can (and should) be written using a higher-order >> function (e.g., map, filter). But sometimes not. In such cases, under >> the new regime, the recommended idiom would be: >> >> let dv = dvec(); >> for some loop { v.push(elt); } >> let v = dvec::unwrap(dv); // if necessary, convert to a vector > > This method of creating vectors originally had worse performance than the other. Is the performance problem resolved or resolvable or is vector creation just going to be expensive? > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev From niko at alum.mit.edu Wed Jun 13 18:27:29 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 13 Jun 2012 18:27:29 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FD922DE.9090504@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FD922DE.9090504@mozilla.com> Message-ID: <4FD93E01.3040300@alum.mit.edu> On 6/13/12 4:31 PM, Brian Anderson wrote: > This method of creating vectors originally had worse performance than > the other. Is the performance problem resolved or resolvable or is > vector creation just going to be expensive? This would of course get resolved. Actually, I don't think building up vectors with dvec is more expensive (at least by my measurements in the vec_append benchmark, dvec is as fast as the original). What is slower though is smallintmap, which makes heavy use of grow_set_elt(). The current implementation doesn't get inlined as well as the original. I think this can be solved with some tender love and care. Niko From niko at alum.mit.edu Wed Jun 13 18:37:22 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Wed, 13 Jun 2012 18:37:22 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD7C3BF.3010408@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> <4FD7C28A.7030206@alum.mit.edu> <4FD7C3BF.3010408@mozilla.com> Message-ID: <4FD94052.90409@alum.mit.edu> On 6/12/12 3:33 PM, Graydon Hoare wrote: > Try sketching some code in a buffer, see how it looks. Might be > possible to come up with an abbreviation (!T perhaps, or the old > unused sigil ?T maybe?), might be possible for inference and a couple > rules about the boundaries of extern functions to fill in the details. We could use ^T for unsafe ptrs, like Pascal. I've been thinking that the idea of an unsafe region is perhaps not the best thing ever. It's not clear where it fits into the "region" hierarchy. We'd need various weird special-case code to cope with it (it's kind of the longest lived region there is, but illegal to dereference, and illegal to use as the value of a function's region argument, unless you're in an unsafe block...). Probably cleaner to just keep unsafe pointers as their own thing. Niko From pwalton at mozilla.com Wed Jun 13 18:43:30 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Wed, 13 Jun 2012 18:43:30 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD94052.90409@alum.mit.edu> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> <4FD7C28A.7030206@alum.mit.edu> <4FD7C3BF.3010408@mozilla.com> <4FD94052.90409@alum.mit.edu> Message-ID: <4FD941C2.1050709@mozilla.com> On 6/13/12 6:37 PM, Niko Matsakis wrote: > On 6/12/12 3:33 PM, Graydon Hoare wrote: >> Try sketching some code in a buffer, see how it looks. Might be >> possible to come up with an abbreviation (!T perhaps, or the old >> unused sigil ?T maybe?), might be possible for inference and a couple >> rules about the boundaries of extern functions to fill in the details. > > We could use ^T for unsafe ptrs, like Pascal. > > I've been thinking that the idea of an unsafe region is perhaps not the > best thing ever. It's not clear where it fits into the "region" > hierarchy. We'd need various weird special-case code to cope with it > (it's kind of the longest lived region there is, but illegal to > dereference, and illegal to use as the value of a function's region > argument, unless you're in an unsafe block...). Probably cleaner to just > keep unsafe pointers as their own thing. +1 for ^T. There's also precedent in Managed C++ (although ^ is a managed pointer there, while we'd be using it for the opposite). ^ is somewhat ugly, but unsafe pointers are by their very nature ugly and it's at least a lightweight-looking sigil. fn free(^void); vs. fn free(*unsafe.void); fn free(&unsafe.void); fn free(&void); Patrick From bklooste at gmail.com Wed Jun 13 20:06:04 2012 From: bklooste at gmail.com (Bennie Kloosteman) Date: Thu, 14 Jun 2012 11:06:04 +0800 Subject: [rust-dev] a vision for vectors In-Reply-To: References: <4FD91F15.9010108@alum.mit.edu> <4FD951DA.6090904@alum.mit.edu> Message-ID: fwd > > > On 6/13/12 7:50 PM, Bennie Kloosteman wrote: > > let mut v = []; > for some loop { v += [elt]; } > > Now, often, such loops can (and should) be written using a higher-order > function (e.g., map, filter). But sometimes not. In such cases, under the > new regime, the recommended idiom would be: > > let dv = dvec(); > for some loop { v.push(elt); } > let v = dvec::unwrap(dv); // if necessary, convert to a vector In User programs in most cases you would just leave it as dynamic vector ( or better yet some form of collection or enumerable interface depending on whether it will be frequently changed by the user). For hard core systems programming you would often stick to the arrays . > > Actually the name `dvec()` (dynamic vector) will probably change?perhaps > to > vecbuf? mvec? suggestions welcome?but you get the idea. The same would > eventually apply to building up strings. What about Java or C# style Array = immutable array ( I would use ArrayValue or ArrayCopy for non ref arrays) Vector or List /ArrayList for dynamic vectors. Note the list name here matches the IList interface . These are all standard types so any decent editor will autoexpand so no need to shorten the names Note here if your doing a lot of string parsing you are much better of working on the char arrays / dynamic vectors . This is a bit different because other languages with string builder like Java and C# don't really use char arrays much . > Basically, the idea is that we have "builder" types for vectors and > strings. > These builder types will overallocate and use dirty tricks to achieve > reasonable performance. Using convenience operators like `+` will not do > such things. > > *Details* > > The actual implementation strategy is that the representation of vectors > will stay mostly the same as it is now. However, when the compiler > allocates > vectors, it will always do so for precisely the size they need to be > (fill > == alloc, in our vector rep). There will be internal functions > (vec::alloc_empty_with_capacity() or something) that allocate an empty > vector but with a large capacity and unsafe functions that can be used to > set the length. Why bother ? ArrayList / StringBuilder just builds an array of space internally and tracks its own capacity which the user can optionally set in a constructor. When they run out of space which the user didn't allow for you just create a new array of double the size. No need for system functions here. However rust doesn't have encapsulation so the internal type being build is accessible , not sure if this is an issue ? > These can be used by dvec-like classes but also by routines > like `vec::map()`. Most of this exists today. The only real thing that > changes is that we take *away* the tricks the compiler does for `+=`. There was a discussion the bitC list of still allowing stream operators like<< as under some conditions they are better. I cant remember the exact details but I think the biggest issue was formatting eg<< "Write this number ""<< intvalue<<"Today" vs str.format("write this number {1} today" , intvalue ) , with str.format requiring some form of var args which bitc did not have and more indexing.. > *Motivation* > > Part of the motivation for this change is that when you have task-local > vectors, the tricks we play now where we treat vectors both as values and > as > things that can be updated in place don't work so well (this is precisely > why the move was made to unique vectors in the first place, as I > understand > it). However, task-local vectors are good for a number of reasons > (cheaper > copies; easier to ensure memory safety), so I expect we'll wind up using > them a fair amount: to obtain reliably good performance, then, a builder > like `dvec` can be used that encapsulates the task-local vector pointer > until construction is complete, making it safe to append to it in place. Would you want single and multi threaded versions of the builders stringbuilder/ArrayList or just a multi threaded one ? Not much time is spend in builders. BTW how do you encapsulate the pointer in rust ? Performance should be much better with fixed size arrays , still eliminating bounds checks we have discussed and is about a a 14% program wide difference ( and you cant trust LLVM for it - mono with LLVM has poor bounds check removal - java relies on the JIT ) . Ben > > From niko at alum.mit.edu Thu Jun 14 06:31:48 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 14 Jun 2012 06:31:48 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: References: <4FD91F15.9010108@alum.mit.edu> <4FD951DA.6090904@alum.mit.edu> Message-ID: <4FD9E7C4.4010404@alum.mit.edu> On 6/13/12 8:06 PM, Bennie Kloosteman wrote: > In User programs in most cases you would just leave it as dynamic > vector ( or better yet some form of collection or enumerable > interface depending on whether it will be frequently changed by the > user). For hard core systems programming you would often stick to the > arrays . That is my guess as well. Converting to a vector is kind of a "freeze" operation. > What about Java or C# style Array = immutable array ( I would use > ArrayValue or ArrayCopy for non ref arrays) Vector or List > /ArrayList for dynamic vectors. Note the list name here matches the > IList interface . I wanted a name pattern that extends beyond arrays to strings as well and possibly other data structures. `mvec`, `mstr` works but is quite concise. Something like `vec_builder` and `str_builder` might be good, but is rather long. > Why bother ? ArrayList / StringBuilder just builds an array of space > internally and tracks its own capacity which the user can optionally > set in a constructor. When they run out of space which the user didn't > allow for you just create a new array of double the size. No need for > system functions here. However rust doesn't have encapsulation so the > internal type being build is accessible , not sure if this is an issue ? This is ... well, basically what I described, I think? I want to keep the fill/alloc bits but have them be managed by dvec (or whatever it gets called) because that way we can safely leave parts of the vector uninitialized. Then when/if the vector is ultimately "unpacked", we don't have to copy anything. > Would you want single and multi threaded versions of the builders > stringbuilder/ArrayList or just a multi threaded one ? Not much time > is spend in builders. Just single-threaded, seeing as Rust has no mutable shared state. > BTW how do you encapsulate the pointer in rust ? I am not sure what you mean. What I mean by "encapsulate" is just "be sure that it does not escape by careful inspection of the code". That is, `dvec` would be carefully coded so that it always knows whether it has the only pointer to the vector or not (much like StringBuffer in Java). Regions help here because they allow us to give out temporary pointers. Niko From graydon at mozilla.com Thu Jun 14 10:23:41 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 14 Jun 2012 10:23:41 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FD91F15.9010108@alum.mit.edu> References: <4FD91F15.9010108@alum.mit.edu> Message-ID: <4FDA1E1D.3000807@mozilla.com> On 13/06/2012 4:15 PM, Niko Matsakis wrote: > *Implications for writing efficient Rust* > > I figured I'd just start with the implications for writing Rust. > Currently, to build up a vector, we rely upon an idiom like: > > let mut v = []; > for some loop { v += [elt]; } Yeah. After we lost the one-element-append rule, this never really read well anyway. Happy to see it go (at least in that form). > Now, often, such loops can (and should) be written using a higher-order > function (e.g., map, filter). But sometimes not. In such cases, under > the new regime, the recommended idiom would be: > > let dv = dvec(); > for some loop { v.push(elt); } > let v = dvec::unwrap(dv); // if necessary, convert to a vector > > Actually the name `dvec()` (dynamic vector) will probably change?perhaps > to vecbuf? mvec? suggestions welcome?but you get the idea. The same > would eventually apply to building up strings. It's funny, this is pretty clearly a stack (growth is optimized only at one end), so I'm of half a mind to just call it a stack, but something kinda balks at the notion. Not sure why. What disappoints me about all this is that the language is now dependent on unsafe library code in order to do asymptotically fast aggregate types at all. The += optimization and vec doubling-allocation was the "one primitive" related to aggregate types that the compiler was filling in for us safely, before, for the sake of building more-efficient containers on top. Now pretty much every primitive container that has a doubling-store growth pattern is going to involve unsafe code. That's a bitter pill, but I guess it was true before too, it was just unsafe code with an interface curated by the compiler and runtime, not core library :( > Most of this exists today. The only > real thing that changes is that we take *away* the tricks the compiler > does for `+=`. Not ok with the thrust of this. I mean, in terms of the API for dvec or stack or whatever, that may be the right thing; the current += rule actually requires a _companion_ compiler-written optimization in the construction of single-element vectors on the RHS in order to append them w/o allocation, in a type-symmetric way, which is totally over the top and should go. So for now pushing a single element should probably, yes, involve a .push method. At least until (or if) we address the type-level question of doing operator overloading on mixed types. But this general move feels like obscuring a pretty important bug, that I'm inclined to point out: we need to expand operator overloading to have op= forms, in general, such that a user could _define_ a version of += that does what the compiler currently does, when that's reasonable (overload arg-type symmetry aside). Operator overloading is simply incomplete here; likewise, fn [](...) needs to have a 3-arg lval form, not try to "return a mutable ref" or something. Stacks are by no means the only case in which there's a "fast" in-place op= form that users _will_ want to write. Pretty much any nontrivial data structure with operators on it has an "in-place" optimization opportunity for several operations. There's no reason to deny them the opportunity when it appears in a for appropriate for overloaded operators; the operator is already named, reserved, parsed at right precedence, etc. It just needs to dispatch like the others. -Graydon From niko at alum.mit.edu Thu Jun 14 10:57:56 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 14 Jun 2012 10:57:56 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA1E1D.3000807@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> Message-ID: <4FDA2624.9070308@alum.mit.edu> On 6/14/12 10:23 AM, Graydon Hoare wrote: > But this general move feels like obscuring a pretty important bug, > that I'm inclined to point out: we need to expand operator overloading > to have op= forms, in general, such that a user could _define_ a > version of += that does what the compiler currently does, when that's > reasonable (overload arg-type symmetry aside). Operator overloading is > simply incomplete here; likewise, fn [](...) needs to have a 3-arg > lval form, not try to "return a mutable ref" or something. This makes sense. I don't have a problem with adding a += operator, but there are... interactions. Nothing too complex but nothing that we have designed for. In general our operator overloading support is minimal and somewhat ad-hoc. We should sketch out a complete plan that accounts for these various complexities. One thing: right now, x += [5] is extra optimized in that it does not create the RHS vector. I ddn't see how any form of operator overloading will achieve *that*. We may want to create additional operators (e.g., ++) to distinguish addition of elements / vectors. I know Marijn is in favor of this (or at least he was at some point). What are the shortcomings of overloaded operators? Here are some things I can think of. - No way to do x += 5 - x[5] = 3 only works for built-in types - x[5] += 3 only works for built-in types - &x[5] only works for built-in types The questions then are: - Which of these patterns should we support at all? - Which can be implemented directly and which are desugared? - For desugaring, what fallbacks are in place? - Finally, how can we possibly implement this in our compiler in a nice way? I think the current implementation of overloading is fragile, in that it affects every downstream client which must consider "two ways" of interpreting a random set of expressions (expr_unary, expr_binary, expr_index, maybe others). This accounts for several bugs (eholk just found one the other day). I was thinking of refactoring things so that all operators ALWAYS have an entry in the "overload" table, and one of those entries is the "intrinsic" definition. So then we can treat things are overloaded operators all the time in the later analysis passes and only trans has to special case things (and maybe not even that, if we use actual rusti intrinsics?) This will get even more complex when x[5] += 5 might be a call to "[]+=" or it might desugar to "x[5] = x[5] + 5". (This all points to the ever-present desire for a rewriting IR, but I don't have any brilliant suggestions on that front) Niko From niko at alum.mit.edu Thu Jun 14 10:59:13 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 14 Jun 2012 10:59:13 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA1E1D.3000807@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> Message-ID: <4FDA2671.6060701@alum.mit.edu> On 6/14/12 10:23 AM, Graydon Hoare wrote: > What disappoints me about all this is that the language is now > dependent on unsafe library code in order to do asymptotically fast > aggregate types at all...That's a bitter pill, but I guess it was true > before too, it was just unsafe code with an interface curated by the > compiler and runtime, not core library :( This is true... but for what it's worth, I think a library class like dvec or stack is easier to audit than trans. Niko From pwalton at mozilla.com Thu Jun 14 11:03:05 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 14 Jun 2012 11:03:05 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA1E1D.3000807@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> Message-ID: <4FDA2759.9020101@mozilla.com> On 6/14/12 10:23 AM, Graydon Hoare wrote: > What disappoints me about all this is that the language is now dependent > on unsafe library code in order to do asymptotically fast aggregate > types at all. The += optimization and vec doubling-allocation was the > "one primitive" related to aggregate types that the compiler was filling > in for us safely, before, for the sake of building more-efficient > containers on top. Now pretty much every primitive container that has a > doubling-store growth pattern is going to involve unsafe code. That's a > bitter pill, but I guess it was true before too, it was just unsafe code > with an interface curated by the compiler and runtime, not core library :( Actually, I think it'd be great if we moved that stuff out of the language itself. I think that, ceteris paribus, code in core is easier to debug and get right than code in trans. I think of it just like ports and channels; the implementation improved quite rapidly once we moved it to the library. > But this general move feels like obscuring a pretty important bug, that > I'm inclined to point out: we need to expand operator overloading to > have op= forms, in general, such that a user could _define_ a version of > += that does what the compiler currently does, when that's reasonable > (overload arg-type symmetry aside). Operator overloading is simply > incomplete here; likewise, fn [](...) needs to have a 3-arg lval form, > not try to "return a mutable ref" or something. Yes, I've thought this for a while. D is good precedent here, with its opIndexAssign. Note that D got in trouble here, though; in a custom user-defined dictionary type, this can be made to work: foo["bar"] = 3; But this doesn't: foo["bar"]++; However, we nicely dodged that bullet by not supporting ++ and -- at all. Very prescient :) Patrick From graydon at mozilla.com Thu Jun 14 13:41:41 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 14 Jun 2012 13:41:41 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA2759.9020101@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2759.9020101@mozilla.com> Message-ID: <4FDA4C85.3050401@mozilla.com> On 12-06-14 11:03 AM, Patrick Walton wrote: > I think of it just like ports and channels; the implementation improved > quite rapidly once we moved it to the library. Fair enough. > However, we nicely dodged that bullet by not supporting ++ and -- at > all. Very prescient :) Not really. Reoccurs with foo["bar"] += 1; -Graydon From pwalton at mozilla.com Thu Jun 14 13:45:35 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 14 Jun 2012 13:45:35 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA4C85.3050401@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2759.9020101@mozilla.com> <4FDA4C85.3050401@mozilla.com> Message-ID: <4FDA4D6F.7040904@mozilla.com> On 6/14/12 1:41 PM, Graydon Hoare wrote: >> However, we nicely dodged that bullet by not supporting ++ and -- at >> all. Very prescient :) > > Not really. Reoccurs with foo["bar"] += 1; Well, there's a fairly straightforward desugaring: foo["bar"] = foo["bar"] + 1; For ++ it's less certain (you have to dummy up a 1 constant of... some type?) Patrick From graydon at mozilla.com Thu Jun 14 13:54:59 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 14 Jun 2012 13:54:59 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA2624.9070308@alum.mit.edu> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2624.9070308@alum.mit.edu> Message-ID: <4FDA4FA3.1090503@mozilla.com> On 12-06-14 10:57 AM, Niko Matsakis wrote: > One thing: right now, x += [5] is extra optimized in that it does not > create the RHS vector. I know, I mentioned that in the last email. It's gruesome and has to go. > What are the shortcomings of overloaded operators? Here are some things > I can think of. > > - No way to do x += 5 > - x[5] = 3 only works for built-in types > - x[5] += 3 only works for built-in types > - &x[5] only works for built-in types Yeah. This gets gnarly fast. I would prefer our solution not wind up looking like blitz++ though. Maybe I was wrong to dismiss the decomposed-to-calls version, but it requires that we support a move-based version and a copy-based version? Or reify the region used for expression temporaries or something? > The questions then are: > - Which of these patterns should we support at all? > - Which can be implemented directly and which are desugared? > - For desugaring, what fallbacks are in place? > - Finally, how can we possibly implement this in our compiler in a nice > way? Fair. > I think the current implementation of overloading is fragile, in that it > affects every downstream client which must consider "two ways" of > interpreting a random set of expressions (expr_unary, expr_binary, > expr_index, maybe others). This accounts for several bugs (eholk just > found one the other day). I was thinking of refactoring things so that > all operators ALWAYS have an entry in the "overload" table, and one of > those entries is the "intrinsic" definition. Maybe. Not sure how this will play out. > are overloaded operators all the time in the later analysis passes and > only trans has to special case things (and maybe not even that, if we > use actual rusti intrinsics?) No, we need to be able to constant-fold manually in the front- or middle- passes, not just punt the whole task to LLVM. Sad but true. -Graydon From eric.holk at gmail.com Thu Jun 14 15:39:21 2012 From: eric.holk at gmail.com (Eric Holk) Date: Thu, 14 Jun 2012 15:39:21 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA4C85.3050401@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2759.9020101@mozilla.com> <4FDA4C85.3050401@mozilla.com> Message-ID: On Jun 14, 2012, at 1:41 PM, Graydon Hoare wrote: > On 12-06-14 11:03 AM, Patrick Walton wrote: > >> I think of it just like ports and channels; the implementation improved >> quite rapidly once we moved it to the library. > > Fair enough. For what it's worth, I've been working on moving vector append into libcore for about the last week, and after a lot of help optimizing from Niko, the library version now slightly beats the hard-coded compiler version for the core-vec-append.rs benchmark. From graydon at mozilla.com Thu Jun 14 15:50:11 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 14 Jun 2012 15:50:11 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA4D6F.7040904@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2759.9020101@mozilla.com> <4FDA4C85.3050401@mozilla.com> <4FDA4D6F.7040904@mozilla.com> Message-ID: <4FDA6AA3.2010507@mozilla.com> On 12-06-14 1:45 PM, Patrick Walton wrote: > On 6/14/12 1:41 PM, Graydon Hoare wrote: >>> However, we nicely dodged that bullet by not supporting ++ and -- at >>> all. Very prescient :) >> >> Not really. Reoccurs with foo["bar"] += 1; > > Well, there's a fairly straightforward desugaring: foo["bar"] = > foo["bar"] + 1; For ++ it's less certain (you have to dummy up a 1 > constant of... some type?) No, this just kicks the can one step further down the road; it's back to losing the whole point of the += in-place optimization. Which is what the user wrote and the library-author wants to provide. I think .. actually I think we want it to turn into: foo.lval_index("bar", |x| x += 1); But as Niko suggests, this really requires a day at a whiteboard to go through the variations and make sure it all hangs together. -Graydon From graydon at mozilla.com Thu Jun 14 16:01:25 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Thu, 14 Jun 2012 16:01:25 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FD941C2.1050709@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> <4FD7C28A.7030206@alum.mit.edu> <4FD7C3BF.3010408@mozilla.com> <4FD94052.90409@alum.mit.edu> <4FD941C2.1050709@mozilla.com> Message-ID: <4FDA6D45.6000301@mozilla.com> On 12-06-13 6:43 PM, Patrick Walton wrote: > +1 for ^T. There's also precedent in Managed C++ (although ^ is a > managed pointer there, while we'd be using it for the opposite). > > ^ is somewhat ugly, but unsafe pointers are by their very nature ugly > and it's at least a lightweight-looking sigil. Compare (adopting the proposed revision back to ., for module-separator): fn trans_binary(bcx: ^block, op: ast.binop, lhs: ^ast.expr, rhs: ^ast.expr, dest: ^dest, ex: ^ast.expr) -> block; vs. fn trans_binary(bcx: *block, op: ast.binop, lhs: *ast.expr, rhs: *ast.expr, dest: *dest, ex: *ast.expr) -> block; I actually think if you're going to go down that road you want * to be unsafe as it is now, and ^ to be your region pointer. That has both more precedent in other languages and, looking at the above examples, is a bit less visually noisy. Bonus intuitions: * evokes C, which is what it's used for, and region pointers always point "up" the stack to a root pinned in an earlier frame :) -Graydon From pwalton at mozilla.com Thu Jun 14 16:06:55 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Thu, 14 Jun 2012 16:06:55 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FDA6D45.6000301@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> <4FD7C28A.7030206@alum.mit.edu> <4FD7C3BF.3010408@mozilla.com> <4FD94052.90409@alum.mit.edu> <4FD941C2.1050709@mozilla.com> <4FDA6D45.6000301@mozilla.com> Message-ID: <4FDA6E8F.3000609@mozilla.com> On 6/14/12 4:01 PM, Graydon Hoare wrote: > I actually think if you're going to go down that road you want * to be > unsafe as it is now, and ^ to be your region pointer. That has both more > precedent in other languages and, looking at the above examples, is a > bit less visually noisy. > > Bonus intuitions: * evokes C, which is what it's used for, and region > pointers always point "up" the stack to a root pinned in an earlier > frame :) Well, I'm concerned that Rust code will be littered with ^ everywhere, which doesn't look like a pointer to most programmers. It'd be nice if, when a programmer looks at a glance at typical Rust code, the meaning of the pointer sigil were obvious. ^ will be significantly less common. Patrick From marsh at extendedsubset.com Thu Jun 14 16:32:17 2012 From: marsh at extendedsubset.com (Marsh Ray) Date: Thu, 14 Jun 2012 18:32:17 -0500 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FDA6E8F.3000609@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> <4FD7C28A.7030206@alum.mit.edu> <4FD7C3BF.3010408@mozilla.com> <4FD94052.90409@alum.mit.edu> <4FD941C2.1050709@mozilla.com> <4FDA6D45.6000301@mozilla.com> <4FDA6E8F.3000609@mozilla.com> Message-ID: <4FDA7481.7020206@extendedsubset.com> On 06/14/2012 06:06 PM, Patrick Walton wrote: > > Well, I'm concerned that Rust code will be littered with ^ > everywhere, which doesn't look like a pointer to most programmers. > It'd be nice if, when a programmer looks at a glance at typical Rust > code, the meaning of the pointer sigil were obvious. ^ will be > significantly less common. A data point from a C++ programmer just learning about Rust. A few years ago I had no choice but to write some dotnet managed C++. I didn't mind the ^s and they didn't take any time to get used to. It was actually a lot nicer than if they had just slapped another __qualifier on the common syntax. It's not any weirder than any of the other decorations we put on pointers if you think about it. -> is the only one that really makes any sense. - Marsh From niko at alum.mit.edu Thu Jun 14 16:44:21 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 14 Jun 2012 16:44:21 -0700 Subject: [rust-dev] RFC: unifying patterns in alt/destructuring assignment In-Reply-To: <4FDA6D45.6000301@mozilla.com> References: <4FD4B852.7020903@alum.mit.edu> <4FD4E7B7.4020904@mozilla.com> <4FD66AE9.7040609@alum.mit.edu> <4FD7A993.4080005@mozilla.com> <4FD7BA74.1040901@alum.mit.edu> <4FD7BD42.9020004@mozilla.com> <4FD7C28A.7030206@alum.mit.edu> <4FD7C3BF.3010408@mozilla.com> <4FD94052.90409@alum.mit.edu> <4FD941C2.1050709@mozilla.com> <4FDA6D45.6000301@mozilla.com> Message-ID: <4FDA7755.5040903@alum.mit.edu> On 6/14/12 4:01 PM, Graydon Hoare wrote: > I actually think if you're going to go down that road you want * to be > unsafe as it is now, and ^ to be your region pointer. That has both > more precedent in other languages and, looking at the above examples, > is a bit less visually noisy. Personally speaking I prefer `*` to `^` as the "normal pointer". But I won't pretend it's anything other than an aesthetic preference and a general, deep reverence for C. I also must admit that `^` as "points up the stack" is cute. Niko From niko at alum.mit.edu Fri Jun 15 05:51:14 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 15 Jun 2012 05:51:14 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA4FA3.1090503@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2624.9070308@alum.mit.edu> <4FDA4FA3.1090503@mozilla.com> Message-ID: <4FDB2FC2.7030200@alum.mit.edu> On 6/14/12 1:54 PM, Graydon Hoare wrote: > No, we need to be able to constant-fold manually in the front- or > middle- passes, not just punt the whole task to LLVM. Sad but true. I did not mean to imply that we would actually use impl machinery for everything. I meant that, internally, we would always use a method_map table (or something like it) to decide what an overloadable-operator meant. Some of the entries would be "an intrinsically defined operation". The idea is just to help centralize the code paths so that we don't have "if it's in the table do one thing, otherwise fall back to the default" but always "check the table and interpret it based on the contents". As a bonus, things that don't care whether this is an intrinsic operation or a method can probably treat them all as methods. Anyway this is still just an idea rattling around in my brain. If I have some spare time (not likely) I may try it and see if it makes the code feel nicer. Niko From graydon at mozilla.com Fri Jun 15 17:12:43 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Fri, 15 Jun 2012 17:12:43 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDB2FC2.7030200@alum.mit.edu> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2624.9070308@alum.mit.edu> <4FDA4FA3.1090503@mozilla.com> <4FDB2FC2.7030200@alum.mit.edu> Message-ID: <4FDBCF7B.7020400@mozilla.com> On 15/06/2012 5:51 AM, Niko Matsakis wrote: > On 6/14/12 1:54 PM, Graydon Hoare wrote: >> No, we need to be able to constant-fold manually in the front- or >> middle- passes, not just punt the whole task to LLVM. Sad but true. > > I did not mean to imply that we would actually use impl machinery for > everything. I meant that, internally, we would always use a method_map > table (or something like it) to decide what an overloadable-operator > meant. Yeah, I'm fine with that, it's just a different factoring; I was only responding to this parenthetical: "(and maybe not even that, if we use actual rusti intrinsics?)" We can't get by with _just_ rusti intrinsics for things we need insight into for const-folding into read-only memory during compilation. Sadly. I'd like to! Always more fun to punt stuff to LLVM :) -Graydon From niko at alum.mit.edu Fri Jun 15 18:23:36 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 15 Jun 2012 18:23:36 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDBCF7B.7020400@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2624.9070308@alum.mit.edu> <4FDA4FA3.1090503@mozilla.com> <4FDB2FC2.7030200@alum.mit.edu> <4FDBCF7B.7020400@mozilla.com> Message-ID: <4FDBE018.20104@alum.mit.edu> On 6/15/12 5:12 PM, Graydon Hoare wrote: > Yeah, I'm fine with that, it's just a different factoring; I was only > responding to this parenthetical: > > "(and maybe not even that, if we use actual rusti intrinsics?)" > > We can't get by with _just_ rusti intrinsics for things we need > insight into for const-folding into read-only memory during compilation. Yeah, there will have to be some constant-folding code that knows what the intrinsics mean. But it's *possible* (albeit rather unlikely?) that we could make it so that the *trans* code itself doesn't have to know. That is, it just "calls a fn" which happens to be an intrinsic. But the constant folding code might say "ah, it's the plus intrinsic, I know how to run *that* at compile time". Anyway, as I said, all hypothetical and not terribly relevant to the bigger question of the proper design for overloaded operator APIs. Niko From niko at alum.mit.edu Fri Jun 15 18:23:56 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Fri, 15 Jun 2012 18:23:56 -0700 Subject: [rust-dev] a vision for vectors In-Reply-To: <4FDA6AA3.2010507@mozilla.com> References: <4FD91F15.9010108@alum.mit.edu> <4FDA1E1D.3000807@mozilla.com> <4FDA2759.9020101@mozilla.com> <4FDA4C85.3050401@mozilla.com> <4FDA4D6F.7040904@mozilla.com> <4FDA6AA3.2010507@mozilla.com> Message-ID: <4FDBE02C.20907@alum.mit.edu> On 6/14/12 3:50 PM, Graydon Hoare wrote: > foo.lval_index("bar", |x| x += 1); That's clever. I hadn't thought about that. From niko at alum.mit.edu Sat Jun 16 07:30:12 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 16 Jun 2012 07:30:12 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FD3D19B.8020101@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD3BF1C.6020702@gmail.com> <4FD3D19B.8020101@mozilla.com> Message-ID: <4FDC9874.5090100@alum.mit.edu> Jumping back to an old thread: > Yes, except that continue/break/ret would be valid in the latter but > not the former. It seems like we should allow continue or break but not both. And it seems mildly inconsistent to allow breaks in a `do` but not other blocks. Perhaps we should just allow `break` in any block? After all, we want to allow labeled break and continue?this extends naturally to blocks. In Java, for example, the following is permitted: outer: { if (cond) { ... break outer; } ... } ... This is kind of a structured goto, in that it cannot create irreducible graphs. Truth be told though I always found it a bit hard to read. I think this is because the `break outer` references a label defined on top, but in fact jumps to the bottom of the block. Niko From pwalton at mozilla.com Sat Jun 16 08:15:56 2012 From: pwalton at mozilla.com (Patrick Walton) Date: Sat, 16 Jun 2012 08:15:56 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FDC9874.5090100@alum.mit.edu> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD3BF1C.6020702@gmail.com> <4FD3D19B.8020101@mozilla.com> <4FDC9874.5090100@alum.mit.edu> Message-ID: <4FDCA32C.80005@mozilla.com> On 06/16/2012 07:30 AM, Niko Matsakis wrote: > Jumping back to an old thread: > >> Yes, except that continue/break/ret would be valid in the latter but >> not the former. > > It seems like we should allow continue or break but not both. And it > seems mildly inconsistent to allow breaks in a `do` but not other > blocks. Perhaps we should just allow `break` in any block? I assume you mean labeled break, right? Otherwise this won't do what you expect: for array.each |x| { if (x == 1) { break; } } Patrick From niko at alum.mit.edu Sat Jun 16 09:50:01 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 16 Jun 2012 09:50:01 -0700 Subject: [rust-dev] RFC: Block lambda syntax tweak In-Reply-To: <4FDCA32C.80005@mozilla.com> References: <4FCEB044.1010204@mozilla.com> <4FD11B31.8060109@gmail.com> <4FD11CD7.80104@mozilla.com> <4FD3BF1C.6020702@gmail.com> <4FD3D19B.8020101@mozilla.com> <4FDC9874.5090100@alum.mit.edu> <4FDCA32C.80005@mozilla.com> Message-ID: <4FDCB939.9000403@alum.mit.edu> On 6/16/12 8:15 AM, Patrick Walton wrote: > I assume you mean labeled break, right? Otherwise this won't do what > you expect: > > for array.each |x| { > if (x == 1) { > break; > } > } Yes, of course. Thinking about it a bit more: I guess `break` breaks out of the nearest `while`, `do` or `for` statement. That's perfectly consistent without needing to dive into labeled break from blocks. I'm not sure why I thought otherwise. Niko From niko at alum.mit.edu Sat Jun 16 17:12:16 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sat, 16 Jun 2012 17:12:16 -0700 Subject: [rust-dev] incoming and reverting commits Message-ID: <4FDD20E0.5090101@alum.mit.edu> When reverting a commit on the incoming branch, I think it would be helpful if people included a short note explaining why the commit was being reverted (e.g., test xyz fails on windows, performance degradation, etc) Niko From pc at wada314.jp Sat Jun 16 23:28:00 2012 From: pc at wada314.jp (Shohei Wada) Date: Sun, 17 Jun 2012 15:28:00 +0900 Subject: [rust-dev] str::as_c_str() : How long the raw pointer available? Message-ID: Hi, list, I've read the tutorial and had a glance at the reference and other documents. I'm now trying to implement the GLUT library wrapper for rust, but I got a problem. Essentially, what I want to do is to convert main()'s args: [str] to [*c_char]. I've read the document, and I found str::as_c_str() function, and the signature is: fn as_c_str(s: str, f: fn(*libc::c_char) -> T) -> T. I'm wondering if it is ok to use this function as: let my_cstr = as_c_str(my_str) {|x| x}; If it is OK, then it's easy to convert [str] to [*c_char]. But I'm afraid that the *c_char may not available at the outside of the closure. Or, it may be possible that suddenly the *c_char became unavailable at outside, like C++'s vector::iterator become unavailable when the original vector has edited. Currently, I assume it is NG, and I'm writing the convert function using recursion like this: fn rec(strs: [str], i: uint, cstrs: [mut *c_char]) unsafe { if strs.len() == i { // converted, do something with cstrs. } else { str::as_c_str(strs[i]) {|x| rec(strs, i+1u, cstrs + [x]) } } } rec(strs, 0u, [mut]); Of course, this code will cause stack overflow when the list is very big. Anyone, do you know it is OK to use *c_char at outside of as_c_str()? Thanks, From banderson at mozilla.com Mon Jun 18 11:12:22 2012 From: banderson at mozilla.com (Brian Anderson) Date: Mon, 18 Jun 2012 11:12:22 -0700 Subject: [rust-dev] str::as_c_str() : How long the raw pointer available? In-Reply-To: References: Message-ID: <4FDF6F86.5050409@mozilla.com> On 06/16/2012 11:28 PM, Shohei Wada wrote: > Hi, list, I've read the tutorial and had a glance at the reference and > other documents. > I'm now trying to implement the GLUT library wrapper for rust, but I > got a problem. You may be interested in collaborating with pcwalton, who also has some GLUT bindings: https://github.com/pcwalton/rust-glut > > Essentially, what I want to do is to convert main()'s args: [str] to [*c_char]. > I've read the document, and I found str::as_c_str() function, and the > signature is: > > fn as_c_str(s: str, f: fn(*libc::c_char) -> T) -> T. > > I'm wondering if it is ok to use this function as: > > let my_cstr = as_c_str(my_str) {|x| x}; It is ok, as long as you make sure that you hold the reference to my_str for at least as long as my_cstr (as_c_str is simply passing a pointer into the Rust string). > > If it is OK, then it's easy to convert [str] to [*c_char]. > But I'm afraid that the *c_char may not available at the outside of the closure. > Or, it may be possible that suddenly the *c_char became unavailable at outside, > like C++'s vector::iterator become unavailable when the original > vector has edited. It should work the way you expect. Just don't modify the original string vector while using the unsafe pointers. > > Currently, I assume it is NG, and I'm writing the convert function > using recursion like this: > fn rec(strs: [str], i: uint, cstrs: [mut *c_char]) unsafe { > if strs.len() == i { > // converted, do something with cstrs. > } else { > str::as_c_str(strs[i]) {|x| rec(strs, i+1u, cstrs + [x]) } > } > } > rec(strs, 0u, [mut]); > > Of course, this code will cause stack overflow when the list is very big. This is overkill. Your other approach should work. This has come up before so it seems like a standard library function would help here. Something vaguely like this: let strs = .... /* Keep a reference to the string vector */ let cstrs = strs.map({ |s| as_c_str({ |buf| buf })); And this would give you a pointer to a C array of *c_char: vec::as_buf(strs.map({ |s| as_c_str({ |buf| buf })) { |vec_buf| /* vec_buf is a **c_char */ } > > Anyone, do you know it is OK to use *c_char at outside of as_c_str()? > Thanks, > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > From graydon at mozilla.com Mon Jun 18 11:31:05 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Mon, 18 Jun 2012 11:31:05 -0700 Subject: [rust-dev] str::as_c_str() : How long the raw pointer available? In-Reply-To: <4FDF6F86.5050409@mozilla.com> References: <4FDF6F86.5050409@mozilla.com> Message-ID: <4FDF73E9.2010403@mozilla.com> On 12-06-18 11:12 AM, Brian Anderson wrote: > It is ok, as long as you make sure that you hold the reference to my_str > for at least as long as my_cstr (as_c_str is simply passing a pointer > into the Rust string). This is only true by accident now and is going to stop being true when we move to slices. In particular, a slice that points into a non-terminal substring will be copied into a temp buffer and null terminated before passing back to such a closure for use in C. So then it's _really_ garbage memory after the closure returns. Generally: copy the string out if you want it to survive after the closure. -Graydon From niko at alum.mit.edu Mon Jun 18 21:13:29 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Mon, 18 Jun 2012 21:13:29 -0700 Subject: [rust-dev] agenda Message-ID: <4FDFFC69.1080808@alum.mit.edu> https://etherpad.mozilla.org/Meeting-weekly-2012-06-19 From pc at wada314.jp Tue Jun 19 04:12:41 2012 From: pc at wada314.jp (Shohei Wada) Date: Tue, 19 Jun 2012 20:12:41 +0900 Subject: [rust-dev] str::as_c_str() : How long the raw pointer available? In-Reply-To: <4FDF73E9.2010403@mozilla.com> References: <4FDF6F86.5050409@mozilla.com> <4FDF73E9.2010403@mozilla.com> Message-ID: >You may be interested in collaborating with pcwalton, who also has some GLUT bindings: https://github.com/pcwalton/rust-glut Thanks! I'll take a look at it. 2012/6/19 Graydon Hoare : > On 12-06-18 11:12 AM, Brian Anderson wrote: > >> It is ok, as long as you make sure that you hold the reference to my_str >> for at least as long as my_cstr (as_c_str is simply passing a pointer >> into the Rust string). > > > This is only true by accident now and is going to stop being true when we > move to slices. In particular, a slice that points into a non-terminal > substring will be copied into a temp buffer and null terminated before > passing back to such a closure for use in C. So then it's _really_ garbage > memory after the closure returns. > > Generally: copy the string out if you want it to survive after the closure. Is there any good datatype to copy out and keep the c-string? Of course str is useless in this case, and it seems [c_char] has same problem. (vec::as_buf's signature is as_buf(v: [const E], f: fn(*E) -> T) -> T, I may not allowed to return *E from the closure) So I think I should use libc::malloc/memcpy/free and std::c_vec to make sure the c-string survive. Is this right? From niko at alum.mit.edu Tue Jun 19 20:56:00 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Tue, 19 Jun 2012 20:56:00 -0700 Subject: [rust-dev] autoderef on method calls Message-ID: <4FE149D0.8060400@alum.mit.edu> I just pushed a change to incoming that supports autoderef on method calls. The ultimate system I ended up with is a bit different from what was initially discussed on the mailing list, so I wanted to specify how it works and why. The basic rule is that we will try to find an impl for the type of the receiver using the existing rules. If no impl is found, then we will attempt to autoderef the receiver and search again. This repeats until a match is found or it is not possible to autoderef. In particular, this means that if there is an impl for @T and an impl for T, and the receiver has type @T, then we will use the @T impl. I had originally planned to report an ambiguity but I changed my mind after seeing the following impl in the to_str module: impl of to_str for @A { fn to_str() -> str { (*self).to_str() } } This implements a pattern like Haskell's deriving. It is inherently ambiguous when combined with autoderef on method receivers. And yet it serves a purpose that autoderef on method receivers does not. For example, using that impl, I can write a routine like: fn connect(v: [A], sep: str) -> str { let mut base = ""; for v.each { |e| base += e.to_str() + sep } ret base; } and I can apply `connect()` to types like `[@uint]`, where `to_str` is defined to `uint`. Niko From graydon at mozilla.com Wed Jun 20 10:05:18 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 20 Jun 2012 10:05:18 -0700 Subject: [rust-dev] str::as_c_str() : How long the raw pointer available? In-Reply-To: References: <4FDF6F86.5050409@mozilla.com> <4FDF73E9.2010403@mozilla.com> Message-ID: <4FE202CE.5090408@mozilla.com> On 19/06/2012 4:12 AM, Shohei Wada wrote: > Is there any good datatype to copy out and keep the c-string? > Of course str is useless in this case, and it seems [c_char] has same problem. > (vec::as_buf's signature is as_buf(v: [const E], f: fn(*E) -> T) -> T, > I may not allowed to return *E from the closure) > So I think I should use libc::malloc/memcpy/free and std::c_vec to > make sure the c-string survive. Is this right? _Currently_ you can do what Brian suggested and just make sure the underlying strings live long enough. When we finish moving to slices, we'll provide an interface wherein the user passes an arena into the as_c_str function, which any temporary is allocated inside. In that case you will be safe keeping both the underlying strings (for terminal slices) and the arena (for non-terminal slices) alive and non-reset as long as you keep the pointers alive. I.e. if you write your code so it keeps the strings alive for the duration of your needs, presently, you will only have a slight additional bit of code to write, to keep an arena alive as well, when we finish the upgrade to slices. (For users who don't wish to keep an arena around, we'll have a variant of the API that uses a general stack-parallel task-local arena automatically, which it resets at the end of the call. This is generally how we're planning on handling alloca()-like problems, via APIs that take user-provided arenas, but default to use the stack-parallel task-local one, when none is provided.) -Graydon From graydon at mozilla.com Wed Jun 20 10:07:30 2012 From: graydon at mozilla.com (Graydon Hoare) Date: Wed, 20 Jun 2012 10:07:30 -0700 Subject: [rust-dev] str::as_c_str() : How long the raw pointer available? In-Reply-To: <4FE202CE.5090408@mozilla.com> References: <4FDF6F86.5050409@mozilla.com> <4FDF73E9.2010403@mozilla.com> <4FE202CE.5090408@mozilla.com> Message-ID: <4FE20352.2040703@mozilla.com> On 20/06/2012 10:05 AM, Graydon Hoare wrote: > On 19/06/2012 4:12 AM, Shohei Wada wrote: > >> Is there any good datatype to copy out and keep the c-string? >> Of course str is useless in this case, and it seems [c_char] has same >> problem. >> (vec::as_buf's signature is as_buf(v: [const E], f: fn(*E) -> T) >> -> T, >> I may not allowed to return *E from the closure) >> So I think I should use libc::malloc/memcpy/free and std::c_vec to >> make sure the c-string survive. Is this right? ... > I.e. if you write your code so it keeps the strings alive for the > duration of your needs, presently, you will only have a slight > additional bit of code to write, to keep an arena alive as well, when we > finish the upgrade to slices. Er, of course, you can also insulate yourself against this change entirely if you want to use c_vec, malloc/memcpy/free, as you note. I'm just pointing out where we're going, longer-term. That longer-term interface should be slightly less error-prone (we'll do all the null sniffing and termination automatically, for example). -Graydon From pc at wada314.jp Thu Jun 21 04:50:22 2012 From: pc at wada314.jp (Shohei Wada) Date: Thu, 21 Jun 2012 20:50:22 +0900 Subject: [rust-dev] str::as_c_str() : How long the raw pointer available? In-Reply-To: <4FE20352.2040703@mozilla.com> References: <4FDF6F86.5050409@mozilla.com> <4FDF73E9.2010403@mozilla.com> <4FE202CE.5090408@mozilla.com> <4FE20352.2040703@mozilla.com> Message-ID: Thank you for your detailed explanation! :D I'm so excited to see new string slices! 2012/6/21 Graydon Hoare : > On 20/06/2012 10:05 AM, Graydon Hoare wrote: >> >> On 19/06/2012 4:12 AM, Shohei Wada wrote: >> >>> Is there any good datatype to copy out and keep the c-string? >>> Of course str is useless in this case, and it seems [c_char] has same >>> problem. >>> (vec::as_buf's signature is as_buf(v: [const E], f: fn(*E) -> T) >>> -> T, >>> I may not allowed to return *E from the closure) >>> So I think I should use libc::malloc/memcpy/free and std::c_vec to >>> make sure the c-string survive. Is this right? > > ... > >> I.e. if you write your code so it keeps the strings alive for the >> duration of your needs, presently, you will only have a slight >> additional bit of code to write, to keep an arena alive as well, when we >> finish the upgrade to slices. > > > Er, of course, you can also insulate yourself against this change entirely > if you want to use c_vec, malloc/memcpy/free, as you note. I'm just pointing > out where we're going, longer-term. That longer-term interface should be > slightly less error-prone (we'll do all the null sniffing and termination > automatically, for example). > > > -Graydon > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev -- #################################### ?? ?? Shohei Wada Mail(PC): pc at wada314.jp From niko at alum.mit.edu Thu Jun 21 08:27:58 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Jun 2012 08:27:58 -0700 Subject: [rust-dev] regions not quite ready Message-ID: <4FE33D7E.9080001@alum.mit.edu> Hello, So, as most of you know, I'll be on vacation until July 5th. I've been thinking that unfortunately I think a few of the regions bugs that remain are serious enough that we ought not to try putting them into widespread use until those bugs are fixed. I am thinking of a few things in particular (in order of importance): #2657 (handling bindings only semi-correct) #2203 (prevent regions from being captured in fn@ closures) #2282 (check for regions in invariant/contravariant locations) I may be able to fix #2657 before I go, but I won't get to the other ones. None of them are terribly complex to solve (though #2203 entails a new kind) but I am a bit nervous about using regions widely before they are fixed. Niko From niko at alum.mit.edu Thu Jun 21 15:23:23 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Thu, 21 Jun 2012 15:23:23 -0700 Subject: [rust-dev] syntax of vectors and slices Message-ID: <4FE39EDB.3050802@alum.mit.edu> So I was thinking about what was said about the syntax of vectors and slices in the previous Tuesday meeting. I thought I'd throw some random ideas out. Here are some possibilities (I'm sure there are more). In each case, I give fixed-length, dynamic, and then slice notation. For better or worse I omitted the @ and ~ sigils on the vector form. The "M" indicates where the mut/const would go should they be relevant. Obviously use fixed-width to view. Graydon suggested perhaps using the idea of "number vs _" to distinguish static-fixed-length from dynamic-length vectors, so I pursued that for a while. I always tried to preserve the rule that the parser knows whether what it is looking at is an expression (possibly involving constants) or a type name, without requiring arbitrary lookahead. One Dimensional Two Dimensional Fixed Vector Slice Fixed Vector Slice [5]MT [_]MT [:]MT [5]M[5]MT [_]M[_]MT [:]M[:]MT [5]MT []MT [:]MT [5]M[5]MT []M[]MT [:]M[:]MT [5]MT [_]MT []MT [5]M[5]MT [_]M[_]MT []M[]MT [5 M]T [_ M]T [:M]T [5 M][5 M]T [_ M][_ M]T [:M][:M]T [5 M]T [M]T [:M]T [5 M][5 M]T [M][M]T [:M][:M]T [5 M]T [_ M]T [M]T [5 M][5 M]T [_ M][_ M]T [M][M]T [MT*5] [MT*_] [MT] [M[MT*5]*5] [M[MT*_]*_] [M[MT]] [MT,5] [MT,_] [MT] [M[MT,5],5] [M[MT,_],_] [M[MT]] [MT;5] [MT;_] [MT] [M[MT;5];5] [M[MT;_];_] [M[MT]] [MT:5] [MT:_] [MT] [M[MT:5]:5] [M[MT;_];_] [M[MT]] (MT*5) vec [MT] ((MT*5)*5) vec> [M[MT]] [5]MT []MT slice [5]M[5]MT []M[]MT slice> [MT,5] [MT] slice [[MT,5],5] [M[MT] slice> Niko From garethdanielsmith at gmail.com Sat Jun 23 13:40:42 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Sat, 23 Jun 2012 21:40:42 +0100 Subject: [rust-dev] Dealing with ` illegal borrow unless pure` errors Message-ID: <4FE629CA.9030807@gmail.com> Hi rust-dev, How should these errors be dealt with? For example, given the following code: fn takes_an_option(_x: option) {} fn takes_a_rec(x: @{mut a: option}) { takes_an_option(x.a); } fn main() { let x = @{mut a: some(4)}; takes_a_rec(x); } rustc produces: test.rs:6:20: 6:23 error: illegal borrow unless pure: creating immutable alias to aliasable, mutable memory test.rs:6 takes_an_option(x.a); ^~~ test.rs:6:4: 6:19 note: impure due to access to impure function test.rs:6 takes_an_option(x.a); ^~~~~~~~~~~~~~~ error: aborting due to previous error I can think of 3 ways of fixing the issue: 1. Declaring takes_an_option as pure. This can't be done in a library controlled by someone else, though, and it also can't be done if the function isn't actually pure. 2. Declaring the argument mode for takes_an_option to be ++ (pass by copy). Again this can only be done if the library isn't someone else's, but I can't see any other downsides apart from more sigil-filled source code. 3. Copying the argument explicitly when invoking the function: takes_an_option(copy a.x); This doesn't require owning the library. Are there other ways of fixing the issue? I also have read that argument modes are being removed. How will that affect this situation? If the single remaining argument mode is by-copy, does that mean this issue will go away? Thanks Gareth From niko at alum.mit.edu Sun Jun 24 11:51:37 2012 From: niko at alum.mit.edu (Niko Matsakis) Date: Sun, 24 Jun 2012 11:51:37 -0700 Subject: [rust-dev] Dealing with ` illegal borrow unless pure` errors In-Reply-To: <4FE629CA.9030807@gmail.com> References: <4FE629CA.9030807@gmail.com> Message-ID: Are there other ways of fixing the issue? > There is one other way. You can restructure the caller. The most ambitious would be to change the field from mutable to immutable, but often that does not work. In that case, you can also update the type of the record from @{mut f: option} to @{mut f: @option}. You would then call the function with `*r.f` (where `r` is the record). This is permitted because, while the `f` field is mutable, the field does not store the option but rather a pointer to the option. The *option itself* is stored in immutable memory (that is, the @ box). > I also have read that argument modes are being removed. How will that > affect this situation? > Probably not at all. What will happen is that the argument will change from being mode && and type option to type *option (or ^option, whichever syntax we choose). > If the single remaining argument mode is by-copy, does that mean this > issue will go away? > The problem goes away if the parameter type is `option`---but I would guess that in practice the type will be `*option` to avoid the copy. Niko -------------- next part -------------- An HTML attachment was scrubbed... URL: From catamorphism at gmail.com Sun Jun 24 14:30:46 2012 From: catamorphism at gmail.com (Tim Chevalier) Date: Sun, 24 Jun 2012 14:30:46 -0700 Subject: [rust-dev] Removing resources Message-ID: Hello, As per https://github.com/mozilla/rust/issues/2485 and https://mail.mozilla.org/pipermail/rust-dev/2011-November/000929.html , I have a patch ready to remove resources from Rust (the straightforward replacement is classes with destructors), pending a snapshot that I'm waiting for. I think this is not a change requiring an RFC, as it's part of the long-standing class proposal, but I wanted to check to see if anyone would object to me removing resources now. If so, let me know. Cheers, Tim -- Tim Chevalier * http://catamorphism.org/ * Often in error, never in doubt "Debate is useless when one participant denies the full dignity of the other." -- Eric Berndt From banderson at mozilla.com Sun Jun 24 14:36:22 2012 From: banderson at mozilla.com (Brian Anderson) Date: Sun, 24 Jun 2012 14:36:22 -0700 Subject: [rust-dev] Removing resources In-Reply-To: References: Message-ID: <4FE78856.6020005@mozilla.com> On 06/24/2012 02:30 PM, Tim Chevalier wrote: > Hello, > > As per https://github.com/mozilla/rust/issues/2485 and > https://mail.mozilla.org/pipermail/rust-dev/2011-November/000929.html > , I have a patch ready to remove resources from Rust (the > straightforward replacement is classes with destructors), pending a > snapshot that I'm waiting for. I think this is not a change requiring > an RFC, as it's part of the long-standing class proposal, but I wanted > to check to see if anyone would object to me removing resources now. > If so, let me know. We discussed this on IRC, but servo is currently using a resource to work around #2708. We need to either fix it or find another workaround. From mictadlo at gmail.com Sun Jun 24 18:47:18 2012 From: mictadlo at gmail.com (Mic) Date: Mon, 25 Jun 2012 11:47:18 +1000 Subject: [rust-dev] other platforms support Message-ID: Hello, Also maybe some ideas could be taken from: * http://haxe.org/doc/features * http://en.wikipedia.org/wiki/Opa_%28programming_language%29 Cheers, Mic -------------- next part -------------- An HTML attachment was scrubbed... URL: From dteller at mozilla.com Mon Jun 25 01:11:11 2012 From: dteller at mozilla.com (David Rajchenbach-Teller) Date: Mon, 25 Jun 2012 10:11:11 +0200 Subject: [rust-dev] other platforms support In-Reply-To: References: Message-ID: <4FE81D1F.1050409@mozilla.com> Not sure we have much to gain from imitating Opa, but if you have any question about the language, it just happens so that I used to lead the project, so don't hesitate to ask me :) Cheers, David On 6/25/12 3:47 AM, Mic wrote: > Hello, > Also maybe some ideas could be taken from: > > * http://haxe.org/doc/features > > * http://en.wikipedia.org/wiki/Opa_%28programming_language%29 > > Cheers, > > Mic > > > _______________________________________________ > Rust-dev mailing list > Rust-dev at mozilla.org > https://mail.mozilla.org/listinfo/rust-dev > -- David Rajchenbach-Teller, PhD Performance Team, Mozilla -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 487 bytes Desc: OpenPGP digital signature URL: From garethdanielsmith at gmail.com Tue Jun 26 14:17:45 2012 From: garethdanielsmith at gmail.com (Gareth Smith) Date: Tue, 26 Jun 2012 22:17:45 +0100 Subject: [rust-dev] Dealing with ` illegal borrow unless pure` errors In-Reply-To: References: <4FE629CA.9030807@gmail.com> Message-ID: <4FEA26F9.4090806@gmail.com> Thanks for the response Niko, > > There is one other way. You can restructure the caller. The most > ambitious would be to change the field from mutable to immutable, but > often that does not work. In that case, you can also update the type > of the record from @{mut f: option} to @{mut f: @option}. You > would then call the function with `*r.f` (where `r` is the record). > This is permitted because, while the `f` field is mutable, the field > does not store the option but rather a pointer to the option. The > *option itself* is stored in immutable memory (that is, the @ box). This makes sense. However I feel it encourages me to wrap all mutable record/class fields in @ boxes, which to me seems awkward to read/write and probably inefficient too. > > I also have read that argument modes are being removed. How will > that affect this situation? > > > Probably not at all. What will happen is that the argument will > change from being mode && and type option to type *option (or > ^option, whichever syntax we choose). > > If the single remaining argument mode is by-copy, does that mean > this issue will go away? > > > The problem goes away if the parameter type is `option`---but I > would guess that in practice the type will be `*option` to avoid > the copy. Is there potential for the copy to be cheap enough to use `option` (without the pointer)? I feel that by-copy is simpler to reason about and also easier to read/write. Thank You Gareth -------------- next part -------------- An HTML attachment was scrubbed... URL: From lindsey at rockstargirl.org Fri Jun 29 12:54:46 2012 From: lindsey at rockstargirl.org (Lindsey Kuper) Date: Fri, 29 Jun 2012 12:54:46 -0700 Subject: [rust-dev] Addressing "the hashtable problem" with type classes In-Reply-To: <4ED85346.4000409@alum.mit.edu> References: <4ED85346.4000409@alum.mit.edu> Message-ID: On Thu, Dec 1, 2011 at 8:25 PM, Niko Matsakis wrote: > There is a danger with typeclasses only on functions because they > permit a lack of coherence. ?This danger is particularly acute with > collections, where the definition of a particular interface---such as > hashable or ord---may be used in structuring the data structure. This > renders the data structure corrupt when used with a different > implementation. > > To see the problem, consider a hashtable defined something like this: > > ? ?mod ht { > ? ? ? ?iface hash { > ? ? ? ? ? ?fn hash() -> uint; > ? ? ? ? ? ?fn eq(other: self) -> bool; > ? ? ? ?} > > ? ? ? ?type t = { buckets: [bucket] } > > ? ? ? ?fn create() -> @t { > ? ? ? ? ? ?... > ? ? ? ?} > > ? ? ? ?fn put(ht: @t, k: K, v: V) { > ? ? ? ? ? ?... > ? ? ? ?} > > ? ? ? ?fn get(ht: @t, k: K) -> V { > ? ? ? ? ? ?... // fails if not present > ? ? ? ?} > ? ?} > > This looks reasonable. ?Now we create two modules, `Module1` and > `Module2`, which both share a reference to the same hashtable, but > which have different implementations of the `hash` interface in scope: > > ? ?mod Module1 { > ? ? ? ?impl hash for uint { > ? ? ? ? ? ?fn hash() -> uint { ret self; } > ? ? ? ? ? ?fn eq(other: int) -> bool { ret self == other; } > ? ? ? ?} > ? ? ? ?... > ? ? ? ?fn foo() -> str { > ? ? ? ? ? ?let h = ht::create(); > ? ? ? ? ? ?ht::put(ht, 3u, "hi"); // 3u.hash() == 3u here > ? ? ? ? ? ?ret Module2::bar(h); > ? ? ? ?} > ? ?} > > ? ?mod Module2 { > ? ? ? ?impl hash for uint { > ? ? ? ? ? ?fn hash() -> uint { ret self / 2; } > ? ? ? ? ? ?fn eq(other: int) -> bool { ret self == other; } > ? ? ? ?} > ? ? ? ?... > ? ? ? ?fn bar(h: @ht::t) -> str { > ? ? ? ? ? ?ret ht_get(ht, 3u); // fails because 3u.hash() == 1u here > ? ? ? ?} > ? ?} So, I want to get an actual-running-code example of the instance coherence problem as it stands in Rust, and Niko's example here seems like a good place to start. Is "impl hash for uint" a typo for "impl of hash for uint"? (If not, then I'm confused, because "impl hash for uint" just sounds like an interface-less implementation of some methods for uint, incidentally named "hash". That missing "of" changes the semantics of the example.) Lindsey