Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
Hi, Am 23.12.2013 um 10:11 schrieb Masklinn maskl...@masklinn.net: On 2013-12-23, at 05:12 , Corey Richardson co...@octayn.net wrote: I find the ability to have refutable let I may have missed it, but is there a reason not to have just that? Make let similar to Erlang’s `=` and fail on refutation? I didn’t understand this to be about wether let should accept refutable patterns in general. Rather this is about wether there should be additional syntax for refutable patterns. The decision to make irrefutable let the default seems reasonable as it avoids silent breakage when new variants are introduced for an enum type. You said you find the basic let’s irrefutability to be a useful property but have not explained why, and why it makes sense to introduce a separate-but-similar construct with subtly different semantics (I also see this as a possible failure, would users of the language really expect `let` to be irrefutable and `let [else]` to be refutable, or would they expect `let [else]` to allow returning a value and `let` to just fail on mismatch? If such different semantics are desired, I’d suggest using a different keyword entirely) more compelling than the ability to work around it with functions wrapping `match` That assertion seems ill supported so far: just about every example is in terms of `Option`, and `Option` is the one type which does not need a refutable let, owing to its truckload of convenience methods covering just about every basic use cases the only reasons to use a `match` with Option are personal preferences and insufficient knowledge of the type. Sure, this discussion has used Option as a running example. I guess the more interesting use case is a library defined type without an unwrap() or similar method. A client of the library could of course implement his own helper method to solve that issue - or just use a variant of let with refutable patterns. The benefit of the refutable patterns would be less boilerplate for helper methods like unwrap(), the ability to „unwrap“ any type, and a nice syntax for trying multiple values in succession ( let Some(x) =? try_1(), try_2(), fail() ). Cheers, Stefan.___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
On Mon, Dec 23, 2013 at 10:11 AM, Masklinn maskl...@masklinn.net wrote: On 2013-12-23, at 05:12 , Corey Richardson co...@octayn.net wrote: I find the ability to have refutable let I may have missed it, but is there a reason not to have just that? Make let similar to Erlang’s `=` and fail on refutation? I don't like either that (a) the possible failure is silent, and refutable lets look the same as irrefutable ones, nor (b) baking fail!() into the semantics. Haskell has these also and I think it's a wart. The proposed syntax solves both issues. Rust doesn't allow partial matches in `match`es either, for reasons, so I think it would be pretty strange to turn around and silently allow them in `let`s. The strongest arguments against IMHO are YAGNI (which is why I prefaced the whole thing with *if* there's demand for a refutable let), and the ambiguity with `if` (which is a technical issue that may or may not have a satisfactory solution). A meta-level process question: now that we have the `feature` attribute, wouldn't that be a great way to empirically decide questions like these? Implement the feature, put it behind a feature gate, and see how much use it gets, and/or if there are any problems with it? This isn't the first case where it seems like that might be more productive than trying to anticipate all of the answers from theory alone. And it seems to work pretty well for GHC. Just perhaps we could be more aggressive about removing features which weren't successful. You said you find the basic let’s irrefutability to be a useful property but have not explained why, and why it makes sense to introduce a separate-but-similar construct with subtly different semantics (I also see this as a possible failure, would users of the language really expect `let` to be irrefutable and `let [else]` to be refutable, or would they expect `let [else]` to allow returning a value and `let` to just fail on mismatch? If such different semantics are desired, I’d suggest using a different keyword entirely) If I'm understanding you correctly, this is a problem that would solve itself: if someone thinks a plain `let` is refutable and will just fail on mismatch, the compiler will quickly tell her otherwise. more compelling than the ability to work around it with functions wrapping `match` That assertion seems ill supported so far: just about every example is in terms of `Option`, and `Option` is the one type which does not need a refutable let, owing to its truckload of convenience methods covering just about every basic use cases the only reasons to use a `match` with Option are personal preferences and insufficient knowledge of the type. On Sun, Dec 22, 2013 at 11:00 PM, Carter Schonwald carter.schonw...@gmail.com wrote: Agreed! On Sunday, December 22, 2013, Ziad Hatahet wrote: But we already have Option::unwrap_or() and Option::unwrap_or_else() that behave similar to the 'else' syntax suggested above. -- Ziad On Sun, Dec 22, 2013 at 10:37 AM, Léo Testard leo.test...@gmail.com wrote: Hello, Le 22 déc. 2013 à 18:59, Stefan Plantikow stefan.planti...@gmail.com a écrit : Hi, Am 22.12.2013 um 16:47 schrieb Gábor Lehel glaebho...@gmail.com: This is a nice idea. At first I thought it wouldn’t work with `if` but in expressions `if` requires `else` so the grammar wouldn’t be ambiguous: No, it doesn't. As long as the if's true block returns unit. let foo = if ... { }; is perfectly legal, even it doesn't make much sense in practice. Leo ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
On Sun, Dec 22, 2013 at 7:37 PM, Léo Testard leo.test...@gmail.com wrote: Hello, Le 22 déc. 2013 à 18:59, Stefan Plantikow stefan.planti...@gmail.com a écrit : Hi, Am 22.12.2013 um 16:47 schrieb Gábor Lehel glaebho...@gmail.com: This is a nice idea. At first I thought it wouldn’t work with `if` but in expressions `if` requires `else` so the grammar wouldn’t be ambiguous: No, it doesn't. As long as the if's true block returns unit. let foo = if ... { }; is perfectly legal, even it doesn't make much sense in practice. Leo Thinking about this, if we say that `else` following a `let` is allowed if *and only if* the pattern is refutable, then this wouldn't actually be ambiguous, because something of type `()` can never be refutable. Therefore `let ... = if { ... } else { ... };` can only be legal if the `else` belongs to the `if`. I'm not completely clear on the relationship between grammatic and semantic ambiguity. Would the grammar still be ambiguous in this case? I would naively think that you're not allowed to take types and such into account at the grammar level, but Rust seemingly already does so w.r.t. whether or not things (such as `if`) return `()`, so I'm a little bit confused. Can someone explain? ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
I may have missed it, but is there a reason not to have just that? Make let similar to Erlang’s `=` and fail on refutation? Erlang is designed around handling failure. It has links, monitors, supervisors, and so forth. Rust has only some very basic tools for catching the failure of a task. I'll also note, that because Erlang has pattern matching in the clauses themselves, many failures occur even before the function bodies. Some of those features incur non-trivial runtime costs which is why Rust doesn't have them. jack. ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
On 12/23/13 4:12 AM, Gábor Lehel wrote: I don't like either that (a) the possible failure is silent, and refutable lets look the same as irrefutable ones, nor (b) baking fail!() into the semantics. Haskell has these also and I think it's a wart. The proposed syntax solves both issues. For what it's worth, Rust's pattern matching is pretty heavily based on OCaml's and the OCaml compiler complains with a warning if you use a refutable pattern in `let`. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
that seems like a reasonable balance On Mon, Dec 23, 2013 at 12:23 PM, Patrick Walton pcwal...@mozilla.comwrote: On 12/23/13 4:12 AM, Gábor Lehel wrote: I don't like either that (a) the possible failure is silent, and refutable lets look the same as irrefutable ones, nor (b) baking fail!() into the semantics. Haskell has these also and I think it's a wart. The proposed syntax solves both issues. For what it's worth, Rust's pattern matching is pretty heavily based on OCaml's and the OCaml compiler complains with a warning if you use a refutable pattern in `let`. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
the OCaml compiler complains with a warning if you use a refutable pattern in `let`. And what does OCaml do at runtime if the pattern is refuted? On Mon, Dec 23, 2013 at 12:23 PM, Patrick Walton pcwal...@mozilla.comwrote: On 12/23/13 4:12 AM, Gábor Lehel wrote: I don't like either that (a) the possible failure is silent, and refutable lets look the same as irrefutable ones, nor (b) baking fail!() into the semantics. Haskell has these also and I think it's a wart. The proposed syntax solves both issues. For what it's worth, Rust's pattern matching is pretty heavily based on OCaml's and the OCaml compiler complains with a warning if you use a refutable pattern in `let`. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
On 12/23/13 10:48 AM, Benjamin Striegel wrote: the OCaml compiler complains with a warning if you use a refutable pattern in `let`. And what does OCaml do at runtime if the pattern is refuted? Throws. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
That seems like a nice compromise, but I don't think it's a good one. Either you intended the pattern to be refutable or you didn't. If you didn't and it is, you should get an error, not a warning. If you did, you shouldn't get a warning at all. Are you going to put a compiler pragma to disable the warning at every use site where you intentionally want a let to be refutable? At that point, you might as well have separate syntax for refutable and irrefutable lets. Or are you just going to live with having false positive warnings in your code? (FWIW, I'm basically fine with having only irrefutable lets, and using `match` for the other cases, or in other words the status quo. But if we *do* add refutable lets, I strongly think they should be explicit.) On Mon, Dec 23, 2013 at 7:03 PM, Carter Schonwald carter.schonw...@gmail.com wrote: that seems like a reasonable balance On Mon, Dec 23, 2013 at 12:23 PM, Patrick Walton pcwal...@mozilla.comwrote: On 12/23/13 4:12 AM, Gábor Lehel wrote: I don't like either that (a) the possible failure is silent, and refutable lets look the same as irrefutable ones, nor (b) baking fail!() into the semantics. Haskell has these also and I think it's a wart. The proposed syntax solves both issues. For what it's worth, Rust's pattern matching is pretty heavily based on OCaml's and the OCaml compiler complains with a warning if you use a refutable pattern in `let`. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
I too think it would be a big mistake to allow let patterns to be refutable, when we've already tried and rejected allowing the same in match statements (ancient Rust history quiz: who else remembers `match check`?). On Mon, Dec 23, 2013 at 2:44 PM, Gábor Lehel glaebho...@gmail.com wrote: That seems like a nice compromise, but I don't think it's a good one. Either you intended the pattern to be refutable or you didn't. If you didn't and it is, you should get an error, not a warning. If you did, you shouldn't get a warning at all. Are you going to put a compiler pragma to disable the warning at every use site where you intentionally want a let to be refutable? At that point, you might as well have separate syntax for refutable and irrefutable lets. Or are you just going to live with having false positive warnings in your code? (FWIW, I'm basically fine with having only irrefutable lets, and using `match` for the other cases, or in other words the status quo. But if we *do* add refutable lets, I strongly think they should be explicit.) On Mon, Dec 23, 2013 at 7:03 PM, Carter Schonwald carter.schonw...@gmail.com wrote: that seems like a reasonable balance On Mon, Dec 23, 2013 at 12:23 PM, Patrick Walton pcwal...@mozilla.comwrote: On 12/23/13 4:12 AM, Gábor Lehel wrote: I don't like either that (a) the possible failure is silent, and refutable lets look the same as irrefutable ones, nor (b) baking fail!() into the semantics. Haskell has these also and I think it's a wart. The proposed syntax solves both issues. For what it's worth, Rust's pattern matching is pretty heavily based on OCaml's and the OCaml compiler complains with a warning if you use a refutable pattern in `let`. Patrick ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
On 23/12/2013 20:55, Benjamin Striegel wrote: I too think it would be a big mistake to allow let patterns to be refutable, when we've already tried and rejected allowing the same in match statements (ancient Rust history quiz: who else remembers `match check`?). For those of us that were not around or do not remember, can you explain what was tried and rejected? I sometimes find myself writing a `_ = ()` arm for match and wish it could be implied… and sometimes `_ = fail!()`. That the two are sometimes used is probably a sign that the status quo (require it to be explicit) is better. -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
[rust-dev] See pull request #11129 (was: Re: Let’s avoid having both foo() and foo_opt())
FYI, made a pull request according to this proposal: https://github.com/mozilla/rust/pull/11129 -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] See pull request #11129 (was: Re: Let’s avoid having both foo() and foo_opt())
Code full of .unwrap() is not good smell I think. 在 2013年12月24日 上午4:42,Simon Sapin simon.sa...@exyr.org写道: FYI, made a pull request according to this proposal: https://github.com/mozilla/rust/pull/11129 -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] See pull request #11129
On 23/12/2013 22:19, Liigo Zhuang wrote: Code full of .unwrap() is not good smell I think. I agree, and I wrote in the first email that it is one of the downsides. But doubling the API (from_utf8 and from_utf8_opt) is also not a good smell, so it’s a compromise to find. -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] Let’s avoid having both foo() and foo_opt()
For those of us that were not around or do not remember, can you explain what was tried and rejected? Heh, it was so long ago that I forgot that the `match` keyword used to be `alt`. Here's the relevant section from the 0.1 manual (Jan 2012): https://github.com/mozilla/rust/blob/16e4369fe3b5f00aa3cdc584a4e41c51c0d3ca8a/doc/tutorial.md#pattern-matching If the arm with the wildcard pattern was left off in the above example, running it on a number greater than ten (or negative) would cause a run-time failure. When no arm matches, alt constructs do not silently fall through—they blow up instead. Back then, we had no facility to statically force exhaustiveness. This changed in 0.2, when exhaustive matches became the default, though you could still opt-in to non-exhaustive matches by using `alt check` rather than `alt`. https://github.com/mozilla/rust/blob/619c4fce891f31ec234a3ac162d40d3def95956e/RELEASES.txt#L581 Indeed, as you mention, at the time people were worried that this would lead to widespread proliferation of `_ = fail`, especially for uses such as matching on integers, which we lack the facilities to exhaustively check. However, in the years since, I can remember only a single person noticing this and lamenting it, and the peace of mind provided by statically-checked exhaustiveness is certainly pleasant. Furthermore, so few people opted-in to dynamic checking via `alt check` that we had dropped the functionality entirely by 0.4. On Mon, Dec 23, 2013 at 3:40 PM, Simon Sapin simon.sa...@exyr.org wrote: On 23/12/2013 20:55, Benjamin Striegel wrote: I too think it would be a big mistake to allow let patterns to be refutable, when we've already tried and rejected allowing the same in match statements (ancient Rust history quiz: who else remembers `match check`?). For those of us that were not around or do not remember, can you explain what was tried and rejected? I sometimes find myself writing a `_ = ()` arm for match and wish it could be implied… and sometimes `_ = fail!()`. That the two are sometimes used is probably a sign that the status quo (require it to be explicit) is better. -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] See pull request #11129
Even with refutable `let`s, I think there's still a good case for having `.unwrap()`-style APIs on enums, which is that often you need to unwrap an enum inside a larger expression. A refutable `let` only works if you're actually using a `let`-binding to begin with. -Kevin On Dec 23, 2013, at 1:24 PM, Simon Sapin simon.sa...@exyr.org wrote: On 23/12/2013 22:19, Liigo Zhuang wrote: Code full of .unwrap() is not good smell I think. I agree, and I wrote in the first email that it is one of the downsides. But doubling the API (from_utf8 and from_utf8_opt) is also not a good smell, so it’s a compromise to find. -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev
Re: [rust-dev] See pull request #11129
On 23/12/2013 22:26, Kevin Ballard wrote: Even with refutable `let`s, I think there's still a good case for having `.unwrap()`-style APIs on enums, which is that often you need to unwrap an enum inside a larger expression. A refutable `let` only works if you're actually using a `let`-binding to begin with. Please don’t change the subject of (at least this part of) this thread. This is about having both variations of an API (using task failure or returning Option) vs. only the latter (and using unwrap() when task failure is desired.) It is not about refutable let vs. unwrap-style methods. -- Simon Sapin ___ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev