Add Channel#<< as an alias to Channel#send

The suggestion here is to have something like Go channel <- value.

Usually I’m against aliases, but << is already quite widespread an used in the stdlib to append/push a value (Array#<<, IO#<<). Furthermore, by returning self, we can even have the possibility to send several values in one line, like with IO#<<.

class Channel
  def <<(value : T) : Channel
    send value
    self
  end
end

channel = Channel(Int32).new
spawn do
  channel << 0
  # Same as
  channel.send 0

  # Multiple sends
  channel << 0 << 0
end
4.times do
  puts channel.receive # => 0
end
1 Like

The problem with operator overloading from where I stand is that whenever the new semantics are substantially different from the original the result is non-intuitive.

Consider this:

class Channel
  def <<(value : T) : Channel
    send value
    self
  end
end

x = 1
p x << 4                 # => 16
p x << 2 << 4            # => 64
x = Channel::Buffered(Int32).new(10)
p x << 1 << 2 << 4       # => #<Channel::Buffered(Int32):0xcb6ea0>

Having said that I don’t think this particular operator will be a notable issue exactly because as you’ve pointed out it’s already widely understood to do a “push” operation as well as the bit shift.

But just for being a contrarian my counter suggestion would be to remove the << overloads from Array, IO, Set, Deque and other non-numbers. :stuck_out_tongue:

In C++, the << operator is used for streams.

std::cout << "hello" << std::endl;

I think it’s natural when you knew it, but hard to understand when not.

Do you know any practical example where chaining channel sends would be useful?

I really like this. It seems idiomatic and doesn’t impose a large learning curve or understanding overhead. I actually think Go’s version is a little less obvious when skimming as they have very similar syntax to send and recieve.

I didn’t know about the << syntax when I started (Not a Rubyist) but it’s pretty self explanatory and obvious.