Is there a reason for not support multi-assignment on select statement?

Following is a reduced example:

chan = Channel(Tuple(String, String)).new

a = spawn(name: "spawn1") do
  sleep rand(10)
  chan.send({"spawn1", "a"})
end

b = spawn(name: "spawn1") do
  sleep rand(10)
  chan.send({"spawn2", "b"})
end

2.times do
  select
  when a, b = chan.receive
    pp! a, b
  end
end

Get following error:

In 1.cr:15:8

 15 | when a, b = chan.receive
           ^
Error: invalid select when expression: must be an assignment or call

Thanks.

Any idea? Is this question described not clearly enough?

What happens when you wrap the a, b = chan.receive in parentheses?


 15 | when (a, b = chan.receive)
           ^
Error: unterminated parenthesized expression

I think it was never implemented. But I don’t there is a blocker to do it. It’s syntax sugar mostly.

Will create a PR for that.

Multiple conditions separated by commas can share a when clause in a case expression. I think it would be quite confusing if the same when could turn the conditions into one multiple assignment when the parser encounters = ... at the end

2 Likes

But it’s a when clause with a select. Unless we foresee some use for comas the parse can be adapted to parse a multi assignment in select-when.

It’s true that having a single parser logic for when is nicer.

I don’t use multi-assign a lot so I won’t miss them if we prefer not to add it.

I see your point. On the other hand I think select behaves differently to case already, suppose

chan = Channel(Nil).new

[..]

select
when a = chan.receive
  pp a
end

Can the print statement be reached? This is already very different from how a case statement behaves.

That said I think select is an abstraction that don’t match the underlying capabilities the OSes provides very well, and it is not very efficient.

That’s a semantical question, not a syntactic one ;)

I think it looks a bit weird to have a multi assign in a condition of a control structure. if a, b = c doesn’t work either.
Arguably, select is a bit special and conditions actually work quite differently from those of if and case. So maybe it’s okay.

I wouldn’t object to adding it, but I’m not quite convinced about it.

3 Likes

It works in Ruby, and it would be nice if it worked in Crystal too.

In fact, it neither work on ruby too.

if a, b = [100, 200]
  p a, b
end

Get

syntax error, unexpected ',', expecting `then' or ';' or '\n'
> 1  if a, b = [100, 200]
> 3  end
1.rb:1: syntax error, unexpected ',', expecting `then' or ';' or '\n' (SyntaxError)
if a, b = [100, 200]

I consider this not so useful, because don’t know use which one (a or b?) to as if condition.

Try putting parentheses:

if (a, b = [100, 200])
  p a, b
end

Yes, this time the syntax is clearly enough to use expression in parentheses as if condition.

Maybe we should support this, create a new issue there.