Re: [rust-dev] RFC about std::option and std::result API

2013-11-02 Thread Steve Klabnik
Would a ruby-style ok?/ok work to replace is_ok/ok?
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] RFC about std::option and std::result API

2013-11-02 Thread Oren Ben-Kiki
I would love it if '?' was allowed at the end of any identifier, to make it
natural to name boolean variables, methods, constants, etc. Having to say
is_xxx is ugly IMO. A lint option ensuring this is only applied to boolean
typed constructs could help reduce abuse, if this is seen as an issue.
On Nov 2, 2013 8:02 AM, Steve Klabnik st...@steveklabnik.com wrote:

 Would a ruby-style ok?/ok work to replace is_ok/ok?
 ___
 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] RFC about std::option and std::result API

2013-11-02 Thread Andres Osinski
A '?' suffix for boolean methods would be fantastic.

On Sat, Nov 2, 2013 at 4:40 AM, Oren Ben-Kiki o...@ben-kiki.org wrote:
 I would love it if '?' was allowed at the end of any identifier, to make it
 natural to name boolean variables, methods, constants, etc. Having to say
 is_xxx is ugly IMO. A lint option ensuring this is only applied to boolean
 typed constructs could help reduce abuse, if this is seen as an issue.

 On Nov 2, 2013 8:02 AM, Steve Klabnik st...@steveklabnik.com wrote:

 Would a ruby-style ok?/ok work to replace is_ok/ok?
 ___
 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




-- 
Andrés Osinski
http://www.andresosinski.com.ar/
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] RFC about std::option and std::result API

2013-11-02 Thread Niko Matsakis
I am generally in favor of this proposal. It seems to be a reasonable
way forward. It is unclear to me how many types would benefit from
this approach of having methods for each variant, but `Result`
certainly does.

With respect to possible confusion between `is_ok()` and `ok()` -- I
think that the presence of a boolean return type should help with
that. (That is, if you write `if foo.ok() { ... }` the compiler will
catch it readily enough)

Some of the methods on `Result`, however, can't be implemented in
terms of this approach. For example, `chain` and `chain_err` really
need to keep the `Result` return type. But I guess that's clear
enough.

One specific comment on your message:

 - There was talk about making `Result` use an `~Error` trait object
 instead of a generic type `E`, which could invalidate most of this
 email.  However, this could also just mean that you usually will see
 `ResultT, ~Error` in the wild, for which this proposal still
 applies.  Additionally, even if the Pattern becomes useless for
 Result, the problem still exists for any other newtype variant
 enums, so I'd like to see it get used anyway.

It is not clear to me why moving to a `~Error` object would have
any effect on this proposal. `err()` would just return `Option~Error`
in that case, right?


Niko
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] RFC about std::option and std::result API

2013-11-02 Thread Marvin Löbel

On 11/02/2013 04:34 PM, Niko Matsakis wrote:

I am generally in favor of this proposal. It seems to be a reasonable
way forward. It is unclear to me how many types would benefit from
this approach of having methods for each variant, but `Result`
certainly does.

With respect to possible confusion between `is_ok()` and `ok()` -- I
think that the presence of a boolean return type should help with
that. (That is, if you write `if foo.ok() { ... }` the compiler will
catch it readily enough)
That's my thinking too, we're not using a statically typed language for 
nothing after all.

Some of the methods on `Result`, however, can't be implemented in
terms of this approach. For example, `chain` and `chain_err` really
need to keep the `Result` return type. But I guess that's clear
enough.
Right, `and` and `or` (which is what we call `chain` and `chain_err` 
these days) will still need to be implemented on `Result` directly, just 
like `map` and `map_err`.


In fact, the only methods that would actually fall away on todays 
`Result` would be `expect`, `expect_err`, a lone `get_ref` and the 
iterator constructors.


I'll send an mail containing a working patch in a follow up to this thread.

One specific comment on your message:


- There was talk about making `Result` use an `~Error` trait object
instead of a generic type `E`, which could invalidate most of this
email.  However, this could also just mean that you usually will see
`ResultT, ~Error` in the wild, for which this proposal still
applies.  Additionally, even if the Pattern becomes useless for
Result, the problem still exists for any other newtype variant
enums, so I'd like to see it get used anyway.

It is not clear to me why moving to a `~Error` object would have
any effect on this proposal. `err()` would just return `Option~Error`
in that case, right?
Well, that would still work, that much is true. However the `as_ref` and 
`as_mut_ref` adapters might pose some problems.


Worst case we'll need to have `ok_ref`, `ok_mut`, `err_ref` and 
`err_mut` adapters instead, which would be unfortunate, but still better 
than duplicating all of `Option`s composable API across `Result`.


Kimundi
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] RFC about std::option and std::result API

2013-11-02 Thread Marvin Löbel
I prepared a patch that renames everything as proposed with the 
exception of Option's unwrap - get change here: 
https://github.com/Kimundi/rust/commit/752912f75f6334da87a476fffc2475a3dfa5639d


I touches ~ 300 lines, most of them being the unwrap - get and 
unwrap_err - err_get fallout.


In fact, only a few singular places actually needed to call a `ok()`, 
`err()` or `as_ref` adapter at all, most just unwrapped or mapped.


I discovered another issue though: Right now we require a ToStr bound on 
Results error type E. Ignoring for a moment that ToStr is on the way 
out, the idea behind that bound is that the unwrapping functions could 
provide a useful error message in the common unwrap an Err value case.


Changing Result to use composition through as_ref() and ok() complicates 
that goal:


- The first problem is that ok(self) - OptionT throws away the Error 
type, which means you'd be only ever be able to see the informative 
error message if you use the shorthand get() and err_get() methods, 
which leads to inconsistency.


- The second, more interesting problem arises with as_ref. By turning 
ResultT, E into ResultT, E, we changed the self type so that now 
an ToStr bound on E is necessary. This could be solved by a generic 
ToStr impl of T for all T: ToStr, however that could decrease usability 
of ToStr, as users might now get seemingly random  prefixes all over 
the place in their to_str() outputs.


The good news is that those two issues might cancel each other out: If 
it gets decided that a composable, Option-API-leveraging interface is 
more important for Result than potentially more usable error messages in 
case of unwrapping an Err value, then we can just remove the ToStr bound 
and provide consistent, if generic, error messages. The patch above 
takes that approach for simplicity.


Kimundi
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] RFC about std::option and std::result API

2013-11-01 Thread Marvin Löbel

Hello everyone!

In the last week I've been trying to update both std::Result and 
std::Option's API
to match each other more, and I'd like to see the opinion of the 
community and the

Devs on a few areas it touches.

# Option today

The baseline here is Options current API, which roughly looks like this:

1. Methods for querying the variant
  - fn is_some(self) - bool
  - fn is_none(self) - bool

2. Adapter for working with references
  - fn as_ref'r('r self) - Option'r T
  - fn as_mut'r('r mut self) - Option'r mut T

3. Methods for getting to the contained value
  - fn expect(self, msg: str) - T
  - fn unwrap(self) - T
  - fn unwrap_or(self, def: T) - T
  - fn unwrap_or_else(self, f: fn() - T) - T

4. Methods for transforming the contained value
  - fn mapU(self, f: fn(T) - U) - OptionU
  - fn map_defaultU(self, def: U, f: fn(T) - U) - U
  - fn mutate(mut self, f: fn(T) - T) - bool
  - fn mutate_default(mut self, def: T, f: fn(T) - T) - bool

5. Iterator constructors
  - fn iter'r('r self) - OptionIterator'r T
  - fn mut_iter'r('r mut self) - OptionIterator'r mut T
  - fn move_iter(self) - OptionIteratorT

6. Boolean-like operations on the values, eager and lazy
  - fn andU(self, optb: OptionU) - OptionU
  - fn and_thenU(self, f: fn(T) - OptionU) - OptionU
  - fn or(self, optb: OptionT) - OptionT
  - fn or_else(self, f: fn() - OptionT) - OptionT

7. Other useful methods
  - fn take(mut self) - OptionT
  - fn filtered(self, f: fn(t: T) - bool) - OptionT
  - fn while_some(self, blk: fn(v: T) - OptionT)

8. Common special cases that are shorthand for chaining two other 
methods together.

  - fn take_unwrap(mut self) - T
  - fn get_ref'a('a self) - 'a T
  - fn get_mut_ref'a('a mut self) - 'a mut T

Based on this, I have a few areas of the API of both modules to discuss:

# Renaming `unwrap` to `get`

This is a known issue (https://github.com/mozilla/rust/issues/9784), and I
think we should just go through with it.
There are a few things that speak in favor for this:
- The name `unwrap` implies destruction of the original `Option`, which is
  not the case for implicitly copyable types, so it's a bad name.
- Ever since we got the reference adapters, Options primary
  usage is to take self by value, with `unwrap` being the main method for
  getting the value out of an Option.
  `get` is a shorter name than `unwrap`, so it would make using Option 
less painful.
- `Option` already has two shorthands for `.as_ref().unwrap()` and 
`as_mut().unwrap()`:
  `.get_ref()` and `.get_mut_ref`, so the name `get` has precedence in 
the current API.


# Renaming `map_default` and `mutate_default` to `map_or` and 
`mutate_or_set`


I can't find an issue for this, but I remember there being an informal 
agreement to

not use the `_default` prefix in methods unless they are related to the
`std::default::Default` trait, a confirmation of this would be nice.

The names `map_or` and `mutate_or_set` would fit in the current naming 
scheme.


# The problem with Result

Now, the big issue. Up until now, work on the result module tried to 
converge on

option's API, except adapted to work with Result.

For example, option has `fn or_else(self, f: fn() - OptionT) - 
OptionT`

to evaluate a function in case of a `None` value, while result has
`pub fn or_elseF(self, op: fn(E) - ResultT, F) - ResultT, F`
to evaluate a function in case of an `Err` value.

However, while some of the operations are directly compatible with this 
approach,
most others require two methods each, one for the `Ok` and one for the 
`Err` variant:


- `fn unwrap(self) - T` vs
  `fn unwrap_err(self) - E`
- `fn expect(self, str) - T` vs
  `fn expect_err(self, str) - E`
- `fn map_defaultU(self, def: U, op: fn(T) - U) - U` vs
  `fn map_err_defaultF(self, def: F, op: fn(E) - F) - F`
- ... and many other methods in blocks 3, 4 and 5.

As you can see, this leads to API duplication twofold: All those methods
already exist on Option, and all those methods exist both for the `Ok` 
and the `Err`

variant.

This is not an Result-only issue: Every enum that is laid out like 
Result either

suffers the same kind of method duplication, or simply does not provide any,
instead requiring the user to match and manipulate them manually.

Examples would be `std::either::Either`, or 
`std::unstable::sync::UnsafeArcUnwrap`


To solve this problem, I'm proposing a convention for all enums that 
consist of

only newtype-like variants:

# Variant adapters for newtype variant enums

Basically, we should start the convention that every enum of the form

enum FooA, B, C, ... {
VariantA(A),
VariantB(B),
VariantC(C),
...
}

should implement two sets of methods:

1. Reference adapters for the type itself:
  - fn as_ref'r('r self) - Foo'r A, 'r B, 'r C, ...
  - fn as_mut'r('r mut self) - Foo'r mut A, 'r mut B, 'r mut C, 
...

2. Option adapters for each variant:
  - fn variant_a(self) - OptionA
  - fn variant_b(self) - OptionB
  - fn variant_c(self) - OptionC
  - ...

This would 

Re: [rust-dev] RFC about std::option and std::result API

2013-11-01 Thread Alex Crichton
 # Renaming `unwrap` to `get`

I would personally find this change a little odd because we still have
a large number of `unwrap` methods thorughout the codebase. Most of
these do indeed imply destruction of the enclosing type. A change like
this would mean that when you decide to write your unwrapping method
you must internally think about whether this always implies that the
outer type would be destroyed or not. In my opinion, unwrap() on
Optionint does exactly what it should and it's just a bug vs state
of mind kind of thing. I would rather strive for consistency across
all APIs than have a special case based on whether the type just
happens to not be destroyed because the whole thing is implicitly
copyable.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] RFC about std::option and std::result API

2013-11-01 Thread Marvin Löbel

On 11/01/2013 08:22 PM, Brian Anderson wrote:
My first reaction is that it's not obvious the difference between 
`is_ok` and `ok`. Also, it would seem that `ok()` is required to 
return a different type to make this work, which seems fairly 
burdensome. If it *is* required to return a different type, then the 
obvious thing to do is just transform it into `OptionT` which is 
fairly nice since it just defers the problem to `Option` completely. 
The idea is that for example for `res: ResultT, E`, `res.ok()` returns 
`OptionT` and `res.err()` returns `OptionE`. So yes, it would just 
defer to Option.


About the difference between `is_ok` and `ok` - fair enough. However I 
think the only way to make this more clear is to rename `ok()` and 
`err()` to something longer, which would make the chaining more verbose 
and has the problem that all short words that would fit are already 
heavily overloaded in rust terminology:

- `as_ok()` and `as_err()`
- `to_ok()` and `to_err()`
- `get_ok()` and `get_err()`
- `ok_get()` and `err_get()`

Maybe a abbreviation of variant would work:

- `ok_var()` and `err_var()`

Seems to read nice at least:

~~~
res.ok_var().get();
res.err_var().get();
res.err_var().expect(...);
~~~

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] RFC about std::option and std::result API

2013-11-01 Thread Marvin Löbel

On 11/01/2013 08:30 PM, Alex Crichton wrote:

# Renaming `unwrap` to `get`

I would personally find this change a little odd because we still have
a large number of `unwrap` methods thorughout the codebase. Most of
these do indeed imply destruction of the enclosing type. A change like
this would mean that when you decide to write your unwrapping method
you must internally think about whether this always implies that the
outer type would be destroyed or not. In my opinion, unwrap() on
Optionint does exactly what it should and it's just a bug vs state
of mind kind of thing. I would rather strive for consistency across
all APIs than have a special case based on whether the type just
happens to not be destroyed because the whole thing is implicitly
copyable.
Imo we still keep consistency even with this rename. `get` is simply the 
more general term which we'd use for generic situations where we don't 
know anything about the type, while specific implementations can choose 
either name depending on situation.


I think it's more useful to say use the name unwrap if the function 
does something non-trivial. For example, `ARC::unwrap()` should 
probably not be renamed to `get` because it can block the task.

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] RFC about std::option and std::result API

2013-11-01 Thread Kevin Ballard

On Nov 1, 2013, at 12:59 PM, Marvin Löbel loebel.mar...@gmail.com wrote:

 Maybe a abbreviation of variant would work:
 
 - `ok_var()` and `err_var()`
 
 Seems to read nice at least:
 
 ~~~
 res.ok_var().get();
 res.err_var().get();
 res.err_var().expect(...);
 ~~~

var here makes me think variable.

My two cents says go with `res.ok().get()` and `res.err().get()`. It's 
unfortunate that `ok()` can be read as if it were `is_ok()`, but I think people 
will get used to it pretty fast.

-Kevin___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] RFC about std::option and std::result API

2013-11-01 Thread Kevin Cantu
Yeah, many of the overlaps between these APIs should or could be expressed
as additional traits...

-- Kevin
On Nov 1, 2013 12:49 PM, Brendan Zabarauskas bjz...@yahoo.com.au wrote:

  My first thought is unrelated: it would be awesome if we had a lint mode
 that detected methods like `get`, `get_ref`, etc. - all these common
 patterns - and confirmed that their result type looked like what we expect.
 We could apply this to all the official libraries to try to stay consistent.

 This could help to ensure that our APIs could remain reasonably intact
 through a transition to higher kinded types.

 ~Brendan
 ___
 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