I just introduced myself to the Ruby splat oprator. And I played with it lot's of way. but the below experiment somehow made me think about it twice :)
langs = ["java", "csharp", "ruby", "haskell" ]
# => ["java", "csharp", "ruby", "haskell"]
l1,*,l2 = *langs
# => ["java", "csharp", "ruby", "haskell"]
l1
# => "java"
l2
# => "haskell"
l1,*,*,l2 = *langs
SyntaxError: (irb):27: syntax error, unexpected tSTAR
l1,*,*,l2 = *langs
^
from /usr/bin/irb:12:in `<main>'
Yes, the error is obvious, as I used more then 1 *(splat)
operators in the same argument list.
Now I tried to play with it.
l1,(*),(*),l2 = *langs
# => ["java", "csharp", "ruby", "haskell"]
Ahh! here it works. But couldn't understand why so?
l1
# => "java"
l2
# => "haskell"
l1,(*),l2 = *langs
# => ["java", "csharp", "ruby", "haskell"]
l1
# => "java"
l2
# => "ruby"
From the above example it seems that it is doing skipping of array elements.
Questions are :
(a) what the operator (*) is called?
(b) when I used in splat(*) in the line l1,*,l2 = *langs
it consumes all the elements - "csharp", "ruby"
. Is there any way to see what *
consumes there technically? Obviously I am teling with the use if l1,*,l2 = *langs
not by l1,l*,l2 = *langs
.
& is the set-intersection operator, which means the result is a collection of the common elements in both arrays.
In ruby 'a ||= b' is called "or - equal" operator. It is a short way of saying if a has a boolean value of true(if it is neither false or nil) it has the value of a. If not it has the value of b.
+= is not a real Ruby operator, and the expression above is simply an abbreviation for: x = x + 1. Abbreviated assignment cannot be combined with parallel assignment: it only works when there is a single lvalue on the left and a single value on the right.
||= is called a conditional assignment operator. It basically works as = but with the exception that if a variable has already been assigned it will do nothing. In the first example x is now equal to 10.
This is due to how parentheses work with parallel assignment as explained by Matz.
For example:
a, b, c = *[1, 2, 3]
a => 1
b => 2
c => 3
Is different than:
a, (b, c) = *[1, 2, 3]
a => 1
b => 2
c => nil
Basically, the parenthesis say: assign the right hand element at this index to the variables in the parens. So 2 is assigned to b
, with nothing left at index 1
to assign to c
. Similarly, (*) will take only the element at the given index and distribute it.
# the * is interpreted to mean 'take all remaining elements'
a, * = 1, 2, 3, 4
# the * is interpreted to mean 'take all remaining elements except
# the last element'
a, *, c = 1, 2, 3, 4
# incorrect syntax, can't splat more than once on all remaining
# elements
a, *, *, c = 1, 2, 3, 4
# the * is interpreted to mean 'take all elements at index 1'
a, (*), c = 1, 2, 3, 4
# the *'s are interpreted to mean 'take all elements at index 1,
# then again at index 2'
a, (*), (*), c = 1, 2, 3, 4
Typically, the *
operator is used in conjuction with a variable as *foo
- but if not it will hold its place and take element assignments as if it were a variable (essentially discarding them)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With