rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.64k stars 12.63k forks source link

Rename channel types and constructor #11765

Closed brson closed 10 years ago

brson commented 10 years ago

The current Chan::new() -> (Port, Chan) is confusing because new 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:

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

anasazi commented 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 .

liigo commented 10 years ago

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

huonw commented 10 years ago

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.)

tikue commented 10 years ago

@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."

pnkfelix commented 10 years ago

accepted for 1.0, P-backcompat-libs

liigo commented 10 years ago

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)
brson commented 10 years ago

@liigo I feel good about that design.

tikue commented 10 years ago

@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."

wycats commented 10 years ago

ChanSender seems worse than Sender. The types are already scoped by module :smile:

emberian commented 10 years ago

I think Sender and Receiver are fine names, since they're in std::comm.

lilyball commented 10 years ago

I agree with @cmr and @wycats. Sender and Receiver are my recommendation.

tarcieri commented 10 years ago

+1 on Sender and Receiver

tikue commented 10 years ago

-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?

emberian commented 10 years ago

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 .

tikue commented 10 years ago

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.

alexcrichton commented 10 years ago

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.

liigo commented 10 years ago

I like straightforward and simple names. Sender and Receiver is good.

liigo commented 10 years ago

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.

brson commented 10 years ago

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);
alexcrichton commented 10 years ago

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.

lilyball commented 10 years ago

@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.

liigo commented 10 years ago

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.

Valloric commented 10 years ago

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.

lilyball commented 10 years ago

"Sink" is only unambiguous once you explain what the heck it actually means.

tarcieri commented 10 years ago

Given the traditional role of "port" in Berkeley sockets, I'd consider naming the endpoints of a channel "ports" is confusing.

Valloric commented 10 years ago

"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.

brendanzab commented 10 years ago

"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.

Valloric commented 10 years ago

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.

brendanzab commented 10 years ago

Is Sink a handle to something you send to, or is it the end point that receive from?

tarcieri commented 10 years ago

+1 for source/sink (or upstream/downstream) being confusing

brendanzab commented 10 years ago

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.

Valloric commented 10 years ago

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.

alexcrichton commented 10 years ago

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:

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).

lilyball commented 10 years ago

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.