Multiple assignment

I’m a bit miffed that x, y = str.split(";") throws an error on not enough elements rather than giving me a nil y. Or rather, the fact that I’ve been in incapable of coming up with a palatable alternative.

Isn’t there an elegant solution to the problem that doesn’t involve using a intermediate array variable?

FWIW, multi-assignment like this doesn’t avoid an intermediary array. It just is syntactic sugar for it.

I recall there being an issue or thread or something about supporting optional values during a multi-assignment, but can’t seem to find it.

EDIT: It’s Allow array destructuring to produce nil values · Issue #8436 · crystal-lang/crystal · GitHub

First thought on this would be, if you’re expecting it to have two elements separated by a ;, but also possibly a single element without a ; at all, you could do like:

x, y = val.includes?(';') ? val.split(';') : {val, nil}

Could also do like x, _, y = "foo".partition ';', but it would produce y # => "" in this context. But would have the benefit of using no intermediary array since it uses a Tuple.

Since split could produce a number of outputs, you can splat the “rest”:

x, *y = str.split(";")

str = ""
# x => "", y => []
str = "foo"
# x => "foo", y => []
str = "foo;bar"
# x => "foo", y => ["bar"]
str = "foo;bar;baz"
# x => "foo", y => ["bar", "baz"]

That being said, I could see how it would be nice if "foo".split(";", 2) actually produced an Array of 2 items with nil on the rhs, especially since I asked for 2 items. This doesn’t match what Ruby does, but it would lend itself to destructuring.

"foo".split(";", 2) also returns a 1-element array in Ruby, the difference is that Ruby behaves as if #[]? is used for multiple assignment (it is more complex than that since nil alone can also be used on the RHS there).

We can’t fill the array with nils as that would make #split nilable, but we can introduce a new #split? doing exactly that. It would be to #split as Enumerable#in_groups_of is to #in_slices_of.

3 Likes

I like that idea, the question mark goes well with “I’m not sure how many there are”.