I was hoping for a way to somehow "skip" the nil values during array creation. But after thinking about this for a while, I realized that this can't be achieved because of Ruby's way to handle multiple values. There's no concept of a "list" of values, multiple values are always represented as an array.
If you assign multiple values, Ruby creates an array:
ary = 1, nil, 3
#=> [1, nil, 3]
Same for a method taking a variable number of arguments:
def foo(*args)
args
end
foo(1, nil, 3)
#=> [1, nil, 3]
So even if I would patch Array with a class method new_without_nil, I would end up with:
def Array.new_without_nil(*values)
values.compact!
values
end
This just moves the code elsewhere.
Everything is an object
From an OO point of view, there's nothing special about nil - it's an object like any other. Therefore, removing nil's is not different from removing 1's.
Using a bunch of if statements on the other hand is something I'm trying to avoid when writing object oriented code. I prefer sending messages to objects.
Regarding "advantages or drawbacks":
[...] with compact / compact!
- creates full array and shrinks it as needed
- short code, often fits in one line
- is easily recognized
- evaluates each item once
- faster (compiled C code)
[...] with << and if statements
- creates empty array and grows it as needed
- long code, one line per item
- purpose might not be as obvious
- items can easily be commented / uncommented
- evaluates each item twice
- slower (interpreted Ruby code)
Verdict:
I'll use compact, might have been obvious.
compactif I already had an array. But since I'm creating a new array, I think it would be cleaner not to add thenilvalues in the first place. But that is just my opinion :-)non_nil_valuesinstead?#compact!is IMO the best way, everybody understands it does just that at a glance, and there is good chance that beeing part of standard library it has minimal overhead. I won't bet on it, but it might be even faster than a stream of#<<s andifs.ifinto a method.