Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std: Make std::comm return types consistent #13448

Merged
merged 1 commit into from
Apr 12, 2014

Conversation

alexcrichton
Copy link
Member

There are currently a number of return values from the std::comm methods, not
all of which are necessarily completely expressive:

  • Sender::try_send(t: T) -> bool
    This method currently doesn't transmit back the data t if the send fails
    due to the other end having disconnected. Additionally, this shares the name
    of the synchronous try_send method, but it differs in semantics in that it
    only has one failure case, not two (the buffer can never be full).
  • SyncSender::try_send(t: T) -> TrySendResult<T>
    This method accurately conveys all possible information, but it uses a
    custom type to the std::comm module with no convenience methods on it.
    Additionally, if you want to inspect the result you're forced to import
    something from std::comm.
  • SyncSender::send_opt(t: T) -> Option<T>
    This method uses Some(T) as an "error value" and None as a "success value",
    but almost all other uses of Option have Some/None the other way
  • Receiver::try_recv(t: T) -> TryRecvResult<T>
    Similarly to the synchronous try_send, this custom return type is lacking in
    terms of usability (no convenience methods).

With this number of drawbacks in mind, I believed it was time to re-work the
return types of these methods. The new API for the comm module is:

Sender::send(t: T) -> ()
Sender::send_opt(t: T) -> Result<(), T>
SyncSender::send(t: T) -> ()
SyncSender::send_opt(t: T) -> Result<(), T>
SyncSender::try_send(t: T) -> Result<(), TrySendError<T>>
Receiver::recv() -> T
Receiver::recv_opt() -> Result<T, ()>
Receiver::try_recv() -> Result<T, TryRecvError>

The notable changes made are:

  • Sender::try_send => Sender::send_opt. This renaming brings the semantics in
    line with the SyncSender::send_opt method. An asychronous send only has one
    failure case, unlike the synchronous try_send method which has two failure
    cases (full/disconnected).
  • Sender::send_opt returns the data back to the caller if the send is guaranteed
    to fail. This method previously returned bool, but then it was unable to
    retrieve the data if the data was guaranteed to fail to send. There is still a
    race such that when Ok(()) is returned the data could still fail to be
    received, but that's inherent to an asynchronous channel.
  • Result is now the basis of all return values. This not only adds lots of
    convenience methods to all return values for free, but it also means that you
    can inspect the return values with no extra imports (Ok/Err are in the
    prelude). Additionally, it's now self documenting when something failed or not
    because the return value has "Err" in the name.

Things I'm a little uneasy about:

  • The methods send_opt and recv_opt are not returning options, but rather
    results. I felt more strongly that Option was the wrong return type than the
    _opt prefix was wrong, and I coudn't think of a much better name for these
    methods. One possible way to think about them is to read the _opt suffix as
    "optionally".
  • Result<T, ()> is often better expressed as Option. This is only applicable
    to the recv_opt() method, but I thought it would be more consistent for
    everything to return Result rather than one method returning an Option.

Despite my two reasons to feel uneasy, I feel much better about the consistency
in return values at this point, and I think the only real open question is if
there's a better suffix for {send,recv}_opt.

Closes #11527

@liigo
Copy link
Contributor

liigo commented Apr 10, 2014

I'd suggest:

  1. Remove send and rename send_opt to send.
  2. Just rename send_opt to send_r, r means result/return.
    The same to recv.
    2014年4月11日 上午6:16于 "Alex Crichton" notifications@github.com写道:

There are currently a number of return values from the std::comm methods,
not
all of which are necessarily completely expressive:

Sender::try_send(t: T) -> bool
This method currently doesn't transmit back the data t if the send
fails
due to the other end having disconnected. Additionally, this shares
the name
of the synchronous try_send method, but it differs in semantics in
that it
only has one failure case, not two (the buffer can never be full).

SyncSender::try_send(t: T) -> TrySendResult
This method accurately conveys all possible information, but it uses a
custom type to the std::comm module with no convenience methods on it.
Additionally, if you want to inspect the result you're forced to import
something from std::comm.

SyncSender::send_opt(t: T) -> Option
This method uses Some(T) as an "error value" and None as a "success
value",
but almost all other uses of Option have Some/None the other way

Receiver::try_recv(t: T) -> TryRecvResult
Similarly to the synchronous try_send, this custom return type is
lacking in
terms of usability (no convenience methods).

With this number of drawbacks in mind, I believed it was time to re-work
the
return types of these methods. The new API for the comm module is:

Sender::send(t: T) -> ()
Sender::send_opt(t: T) -> Result<(), T>
SyncSender::send(t: T) -> ()
SyncSender::send_opt(t: T) -> Result<(), T>
SyncSender::try_send(t: T) -> Result<(), TrySendError>
Receiver::recv() -> T
Receiver::recv_opt() -> Result<T, ()>
Receiver::try_recv() -> Result<T, TryRecvError>

The notable changes made are:

Sender::try_send => Sender::send_opt. This renaming brings the
semantics in
line with the SyncSender::send_opt method. An asychronous send only
has one
failure case, unlike the synchronous try_send method which has two
failure
cases (full/disconnected).

Sender::send_opt returns the data back to the caller if the send is
guaranteed
to fail. This method previously returned bool, but then it was unable
to
retrieve the data if the data was guaranteed to fail to send. There is
still a
race such that when Ok(()) is returned the data could still fail to be
received, but that's inherent to an asynchronous channel.

Result is now the basis of all return values. This not only adds lots
of
convenience methods to all return values for free, but it also means
that you
can inspect the return values with no extra imports (Ok/Err are in the
prelude). Additionally, it's now self documenting when something
failed or not
because the return value has "Err" in the name.

Things I'm a little uneasy about:

The methods send_opt and recv_opt are not returning options, but rather
results. I felt more strongly that Option was the wrong return type
than the
_opt prefix was wrong, and I coudn't think of a much better name for
these
methods. One possible way to think about them is to read the _opt
suffix as
"optionally".

Result is often better expressed as Option. This is only applicable
to the recv_opt() method, but I thought it would be more consistent for
everything to return Result rather than one method returning an Option.

Despite my two reasons to feel uneasy, I feel much better about the
consistency
in return values at this point, and I think the only real open question is
if
there's a better suffix for {send,recv}_opt.

Closes #11527 #11527

You can merge this Pull Request by running

git pull https://github.com/alexcrichton/rust rework-chan-return-values

Or view, comment on, or merge it at:

#13448
Commit Summary

  • std: Make std::comm return types consistent

File Changes

Patch Links:


Reply to this email directly or view it on GitHubhttps://github.com//pull/13448
.

@brson
Copy link
Contributor

brson commented Apr 10, 2014

I'm pretty happy with this rationalization.

If we made send_opt the default send method then that forces every caller to check the result, which I've previously thought was too burdensome. For most protocols it's simply wrong for the receiver to just disappear so failing is a reasonable result.

There are currently a number of return values from the std::comm methods, not
all of which are necessarily completely expressive:

  Sender::try_send(t: T) -> bool
    This method currently doesn't transmit back the data `t` if the send fails
    due to the other end having disconnected. Additionally, this shares the name
    of the synchronous try_send method, but it differs in semantics in that it
    only has one failure case, not two (the buffer can never be full).

  SyncSender::try_send(t: T) -> TrySendResult<T>
    This method accurately conveys all possible information, but it uses a
    custom type to the std::comm module with no convenience methods on it.
    Additionally, if you want to inspect the result you're forced to import
    something from `std::comm`.

  SyncSender::send_opt(t: T) -> Option<T>
    This method uses Some(T) as an "error value" and None as a "success value",
    but almost all other uses of Option<T> have Some/None the other way

  Receiver::try_recv(t: T) -> TryRecvResult<T>
    Similarly to the synchronous try_send, this custom return type is lacking in
    terms of usability (no convenience methods).

With this number of drawbacks in mind, I believed it was time to re-work the
return types of these methods. The new API for the comm module is:

  Sender::send(t: T) -> ()
  Sender::send_opt(t: T) -> Result<(), T>
  SyncSender::send(t: T) -> ()
  SyncSender::send_opt(t: T) -> Result<(), T>
  SyncSender::try_send(t: T) -> Result<(), TrySendError<T>>
  Receiver::recv() -> T
  Receiver::recv_opt() -> Result<T, ()>
  Receiver::try_recv() -> Result<T, TryRecvError>

The notable changes made are:

* Sender::try_send => Sender::send_opt. This renaming brings the semantics in
  line with the SyncSender::send_opt method. An asychronous send only has one
  failure case, unlike the synchronous try_send method which has two failure
  cases (full/disconnected).

* Sender::send_opt returns the data back to the caller if the send is guaranteed
  to fail. This method previously returned `bool`, but then it was unable to
  retrieve the data if the data was guaranteed to fail to send. There is still a
  race such that when `Ok(())` is returned the data could still fail to be
  received, but that's inherent to an asynchronous channel.

* Result is now the basis of all return values. This not only adds lots of
  convenience methods to all return values for free, but it also means that you
  can inspect the return values with no extra imports (Ok/Err are in the
  prelude). Additionally, it's now self documenting when something failed or not
  because the return value has "Err" in the name.

Things I'm a little uneasy about:

* The methods send_opt and recv_opt are not returning options, but rather
  results. I felt more strongly that Option was the wrong return type than the
  _opt prefix was wrong, and I coudn't think of a much better name for these
  methods. One possible way to think about them is to read the _opt suffix as
  "optionally".

* Result<T, ()> is often better expressed as Option<T>. This is only applicable
  to the recv_opt() method, but I thought it would be more consistent for
  everything to return Result rather than one method returning an Option.

Despite my two reasons to feel uneasy, I feel much better about the consistency
in return values at this point, and I think the only real open question is if
there's a better suffix for {send,recv}_opt.

Closes rust-lang#11527
@brson
Copy link
Contributor

brson commented Apr 12, 2014

I r+ed this despite @liigo's comments since I think this is a good improvement. The suggested improvements look contentious enough to me that we can follow up on those topics later.

@brson
Copy link
Contributor

brson commented Apr 12, 2014

@liigo Although the _r isn't currently a convention it's an interesting idea that I may be slowly warming to. I wonder why this case hasn't come up before though, and I wonder how many _opt variants we have these days - it may not be many.

@huonw
Copy link
Member

huonw commented Apr 12, 2014

One (weak) argument against _r is the meaning differs to the one in C, where it means "reentrant".

bors added a commit that referenced this pull request Apr 12, 2014

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
…=brson

There are currently a number of return values from the std::comm methods, not
all of which are necessarily completely expressive:

 * `Sender::try_send(t: T) -> bool`
    This method currently doesn't transmit back the data `t` if the send fails
    due to the other end having disconnected. Additionally, this shares the name
    of the synchronous try_send method, but it differs in semantics in that it
    only has one failure case, not two (the buffer can never be full).

 * `SyncSender::try_send(t: T) -> TrySendResult<T>`
    This method accurately conveys all possible information, but it uses a
    custom type to the std::comm module with no convenience methods on it.
    Additionally, if you want to inspect the result you're forced to import
    something from `std::comm`.

 * `SyncSender::send_opt(t: T) -> Option<T>`
    This method uses Some(T) as an "error value" and None as a "success value",
    but almost all other uses of Option<T> have Some/None the other way

 * `Receiver::try_recv(t: T) -> TryRecvResult<T>`
    Similarly to the synchronous try_send, this custom return type is lacking in
    terms of usability (no convenience methods).

With this number of drawbacks in mind, I believed it was time to re-work the
return types of these methods. The new API for the comm module is:

    Sender::send(t: T) -> ()
    Sender::send_opt(t: T) -> Result<(), T>
    SyncSender::send(t: T) -> ()
    SyncSender::send_opt(t: T) -> Result<(), T>
    SyncSender::try_send(t: T) -> Result<(), TrySendError<T>>
    Receiver::recv() -> T
    Receiver::recv_opt() -> Result<T, ()>
    Receiver::try_recv() -> Result<T, TryRecvError>

The notable changes made are:

* Sender::try_send => Sender::send_opt. This renaming brings the semantics in
  line with the SyncSender::send_opt method. An asychronous send only has one
  failure case, unlike the synchronous try_send method which has two failure
  cases (full/disconnected).

* Sender::send_opt returns the data back to the caller if the send is guaranteed
  to fail. This method previously returned `bool`, but then it was unable to
  retrieve the data if the data was guaranteed to fail to send. There is still a
  race such that when `Ok(())` is returned the data could still fail to be
  received, but that's inherent to an asynchronous channel.

* Result is now the basis of all return values. This not only adds lots of
  convenience methods to all return values for free, but it also means that you
  can inspect the return values with no extra imports (Ok/Err are in the
  prelude). Additionally, it's now self documenting when something failed or not
  because the return value has "Err" in the name.

Things I'm a little uneasy about:

* The methods send_opt and recv_opt are not returning options, but rather
  results. I felt more strongly that Option was the wrong return type than the
  _opt prefix was wrong, and I coudn't think of a much better name for these
  methods. One possible way to think about them is to read the _opt suffix as
  "optionally".

* Result<T, ()> is often better expressed as Option<T>. This is only applicable
  to the recv_opt() method, but I thought it would be more consistent for
  everything to return Result rather than one method returning an Option.

Despite my two reasons to feel uneasy, I feel much better about the consistency
in return values at this point, and I think the only real open question is if
there's a better suffix for {send,recv}_opt.

Closes #11527
@bors bors closed this Apr 12, 2014
@bors bors merged commit 545d471 into rust-lang:master Apr 12, 2014
@alexcrichton alexcrichton deleted the rework-chan-return-values branch April 12, 2014 20:43
@liigo
Copy link
Contributor

liigo commented Apr 13, 2014

I like @alexcrichton's this improvement too. But for _opt names, ...
We already have Option, getopts::optopt, TaskOpts, a little mix up.

bors added a commit that referenced this pull request Apr 19, 2014
…hton

I was getting a bit confused by these and (I think) managed to track it down to fallout from #13448 and #13465.
compiler-errors pushed a commit to compiler-errors/rust that referenced this pull request Oct 26, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
…und, r=Veykril

Workaround the python vscode extension's polyfill

Fixes rust-lang#13442

`String.replaceAll` and `String.replace` behave the same when given a (/g-flagged) Regex, so fix is very simple.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Should Sender::try_send return the message on failure?
5 participants