Closed brson closed 10 years ago
DropOff/PickUp?
On Fri, Jan 24, 2014 at 6:18 PM, Brian Anderson notifications@github.comwrote:
@bjz https://github.com/bjz also suggested Address/Mailbox
— Reply to this email directly or view it on GitHubhttps://github.com/mozilla/rust/issues/11765#issuecomment-33278634 .
Users should operate on interfaces, not implementations. They are not required to known what it really is in the black-box. So, channel() should returns trait Sender and trait Receiver to users. While in the black-box, from rust-developers' view, it maybe XPort and YPort, or any other names which are private, and so users don't care.
trait Sender;
trait Receiver;
channel() -> (Sender,Receiver) { (PrivXPort as Sender, PrivYPort as Receiver) }
let (s,r) = channel();
Because users may always omit variable's type here, how to correctly spell Receiver
is not a matter. Using a noun word to name function channel() isn't a matter too, because other languages such as python often do this on constructor functions also. @brson
Compulsory virtual dispatch is a negative, as is the requirement for them to be allocations (~Sender
and ~Receiver
) to be able to return trait objects.
Either way, why have traits called Sender
and Receiver
when we can just have public wrapper types call that (with private fields)? Also, why would there be less debate about the names of the public traits vs. names of public types? Both are defining the public interface.
(I don't think the internal private names were ever being discussed here.)
@jfager it's not that Open
implies that something has to already exist; it's more that the common case is that it does, or at the very least can. With channel()
(or whatever it will be called), it will always return a new channel, never one that already exists. That seems to me to be quite a different contract than you would expect from something called "open."
accepted for 1.0, P-backcompat-libs
After reading all of the comments carefully, I think the winner API is:
pub fn channel() -> (ChanSender, ChanReceiver)
that is most meaningful, most straightforward and most people support it (or not hate it). How to easily spell a useful word (receive) correctly is not a big question. Benefit from the type inference, users don't need to use it explicitly:
let (s,r) = channel();
I like this too:
Chan::open() -> (Sender, Receiver)
@liigo I feel good about that design.
@brson that naming distinctly feels like the result of design-by-committee. I'd prefer for someone to make an executive decision rather than have it turn out so "meh."
ChanSender seems worse than Sender. The types are already scoped by module :smile:
I think Sender and Receiver are fine names, since they're in std::comm
.
I agree with @cmr and @wycats. Sender
and Receiver
are my recommendation.
+1 on Sender
and Receiver
-1 on Sender
and Receiver
. I'm sure there are pairs of words equally explicit about the intended use that don't come off so dry. I can't think of any right now, but there's no real rush on getting this figured out, is there?
Do we need clever names? What's wrong with straightforward, simple names?
On Thu, Feb 13, 2014 at 8:45 PM, Tim notifications@github.com wrote:
-1 on Sender and Receiver. I'm sure there are pairs of words equally explicit about the intended use that don't come off so dry. I can't think of any right now, but there's no real rush on getting this figured out, is there?
— Reply to this email directly or view it on GitHubhttps://github.com/mozilla/rust/issues/11765#issuecomment-35048005 .
There's nothing wrong with straightforward and simple names. I want these names to be both straightforward and simple. But I also want them to be elegantly named and lacking redundancy. It's not about cleverness. Sender
and Receiver
sound straight out of java or something; does anyone really want to see sender.send()
and receiver.recv()
everywhere? To make somewhat of a straw man argument, we might as well rename channel()
to createSenderAndReceiver()
, since channel isn't really explicit about what it's doing. i.e. it could be a single struct that both sends and receives, it could disallow having multiple senders, etc.
It might seem like I'm unnecessarily bikeshedding this, but let me remind everyone that bikeshedding is what got us to Sender
and Receiver
in the first place. Channels are high profile; it wouldn't be the end of the world to go with Sender
and Receiver
, but it seems to me Rust deserves better.
We should keep in mind the design space for a second flavor of channels when considering new names for the current channels. We're thinking of adding a synchronous-send channel which can either have a buffer or not (it always blocks waiting for a slot in the buffer if it's empty).
With these new channels, we should consider what we're going to name the in tandem with the current channels. Right now we have Chan
and Port
and in theory this would add a SyncChan
. Would we have a channel()
and sync_channel()
function returning a Sender
and a SyncSynder
? Just something to keep in mind I think.
I like straightforward and simple names. Sender
and Receiver
is good.
If we will have another channel type, as @alexcrichton said, maybe we should design Sender
and Receiver
as Trait? sync_channel()
is a good name too.
Receiver
will most likely be the receiving type for both channel types, so it's only the ctor and the sender types that need to be distinct.
fn channel() -> (Sender, Receiver);
fn sync_channel() -> (SyncSender, Receiver);
Another idea:
fn channel() -> (SendPort, RecvPort)
Sadly SyncSendPort
is awful. I do like the idea that each half is a "port" to the whole concept of a channel.
@alexcrichton I like that. We could also plausibly have SyncPort
instead of SyncSendPort
, if we're comfortable with the idea that RecvPort
is the only receiver and therefore SyncPort
must be a sender.
2014年2月23日 下午3:35于 "Alex Crichton" notifications@github.com写道:
Another idea:
fn channel() -> (SendPort, RecvPort)
Sadly SyncSendPort is awful. I do like the idea that each half is a "port" to the whole concept of a channel.
+1, and +1 for syncport.
— Reply to this email directly or view it on GitHub.
I do like the idea that each half is a "port" to the whole concept of a channel.
While I agree that "port" is a nice way to describe an end of a channel, I do not think that having it in the name we provide to the user is useful; as you noticed, we'd still have to attach another word (like "Send" or "Recv") to make it meaningful. And "Recv" being shortened kinda gives it away that "Port" is useless in the name and doesn't pull its own weight but merely adds to the letters the user has to type out.
"Source" and "Sink" are short and unambiguous. Conceptually, they're ports but making them "SourcePort" and "SinkPort" is just adding letters for no benefit.
"Sender" and "Receiver" are also fine (though longer than "Source" and "Sink" for IMO no increase in readability); I'd strongly encourage avoiding adding more butchered shorthands like "Recv" to the standard library. Frankly, Rust already suffers for it.
"Sink" is only unambiguous once you explain what the heck it actually means.
Given the traditional role of "port" in Berkeley sockets, I'd consider naming the endpoints of a channel "ports" is confusing.
"Sink" is only unambiguous once you explain what the heck it actually means.
On it's own, it's hard to understand what it is. But the name is not presented to the user in a vacuum. The name is presented in the context of "A Channel has a Source and a Sink endpoint." In that one sentence, it's immediately obvious to the user (now and forever) what end does what.
"A Channel has a Source and a Sink endpoint." In that one sentence, it's immediately obvious to the user (now and forever) what end does what.
Remember the POV issue. Does a Source call send or recv? It is not very clear.
Remember the POV issue. Does a Source call send or recv? It is not very clear.
How is it an issue? The user has a Source and a Sink in their code. Per English, stuff comes out of a Source and goes into a Sink. Thus, you can get data out of the Channel from the Source and put it into the Channel through the Sink.
Is Sink
a handle to something you send to, or is it the end point that receive from?
+1 for source/sink (or upstream/downstream) being confusing
I originally liked "Source" and "Sink/Drain", but I have come around to agreeing with @anasazi that, as @brson summarized, they could each be either end depending whether one takes the POV of the channel itself or not. So I've been now wondering which terms use the flow analogy but do not fail in this manner
— @pnkfelix https://github.com/mozilla/rust/issues/11765#issuecomment-33217604
The advantage of Sender
and Receiver
is that the method names are actually in the type names. That makes it easy to remember.
I disagree about the POV issue, but since I think Sender
and Receiver
are fine names I don't think this is worth discussing further.
I'm not super thrilled about Sender/Receiver, but I think that clarity is more important than conciceness. To reiterate @brson's comment (https://github.com/mozilla/rust/issues/11765#issuecomment-35050596), this ticket needs these changes:
Chan<T>
to Sender<T>
Port<T>
to Receiver<T>
Chan::new
to channel
(and put channel
in the prelude)Chan
type to a derivative tx
Port
type to a derivative rx
The only outstanding decision I can think of are what PortReader
and ChanWriter
should become, and I'd recommend ChanWriter
and ChanReader
now that we have the design space open up (these types are readers/writers of channels).
One concern that occurred to me tonight is that Sender
and Receiver
are -er words, which tend to imply traits (e.g. Writer
, Reader
), but in this case are concrete types. I know we aren't terribly consistent about this, but the -er concrete types that I can think of off the top of my head are named after the traits they implement, e.g. MemWriter
.
The current
Chan::new() -> (Port, Chan)
is confusing becausenew
returns a tuple instead of a new object, 'port' and 'chan' are not intuitive, and the name 'chan' is reused for two purposes (the sender and the total channel).Some proposed alternatives:
Chan::open() -> (Source, Sink)
Chan::new() -> (Source, Sink)
Chan::new() -> (Sender, Receiver)
Chan::new() -> (Source, Drain)
pipe() -> (Port, Chan)
Also need to consider whether sender or receiver comes first in the tuple.
Nominating.
Discussion: https://mail.mozilla.org/pipermail/rust-dev/2014-January/007928.html