Ruby’s magic underscore
po-ru.com
po-ru.com
Is there any reason while the Ruby 1.8 behaviour that duplicate variable names are allowed was changed? This seems a much cleaner way of allowing this construct.
Because in general allowing duplicate argument names is a terrible idea and a rich source of bugs?
> This seems a much cleaner way of allowing this construct.
I feel the exact opposite. A privileged 'disregard' symbol gives you the power of signalling that you don't care about certain arguments, without the 'shoot-yourself-in-the-foot' side effect of easily accidentally shadowing what you intended to be distinct entities.
Ever since I first saw it in Prolog, I've loved the idea of having a special symbol for "don't care", and I find the examples using it in this article to be much more immediately clear than the ones with unused variables (once you know about the _, at least). While it doesn't provide the same level of functionality here as in Prolog, being just a nice little indicator of unuse here, using duplicate names for unused variables, feels much more sketchy to me -- a non-underscore variable name just doesn't stand out as immediately noticeable in the same way.
And allowing duplicate names as a general rule, not just for one special case, seems a much more likely thing to trip up inexperienced programmers in the future. Say someone was lazy and used "x" as their unused variable, and someone newer to the language came along and didn't notice the duplication and actually used the x variable for something?
"Ignored" perhaps?
Digital electronics has 0, 1 and x.
Java/C# have Boolean/bool?, with values true, false, and null.
English has apathetic, neutral, unbiased, nonpartisan.
e.g.
>>> p = { "Alice": ["g", 1, "a@a"], "Bob": ["b", 2, "b@b"]}
>>> [(name, email) for name, (unused, unused, email) in p.iteritems()]
[('Bob', 'b@b'), ('Alice', 'a@a')]It looks like this used to work in 1.8, but a "duplicate checker" was added in 1.9?
>>> p = { "Alice": ["g", 1, "a@a"], "Bob": ["b", 2, "b@b"]}
>>> [(name, email) for name, (_, _, email) in p.iteritems()]
[('Bob', 'b@b'), ('Alice', 'a@a')]The equivalent code in Python would be this:
def each_fn(unused, unused, email):
pass
map(iter_fn, list)
And this does in fact give a syntax error: SyntaxError: duplicate argument 'unused' in function definitionTo, in general, make giving multiple arguments for a function or block/lambda the same name a syntax error.
Python special-cases generators, but having multiple identical argument names for a function in Python is a syntax error.
Ruby is a bit more 'regular' in that in both blocks/lambdas and functions, reusing an argument name is always an error. '_' then functions not as a name but a special 'disregard' symbol.
Though I do feel obligated to point out that, being lazy-evaluated, even if you do give a parameter a name it still won't be evaluated until you actually use it.
Not really, it's older than both Ruby and Python. Compared to Prolog and C, yes I suppose so.
If you only need the second item in the range (the value), use the blank identifier, an underscore, to discard the first:
sum := 0 for _, value := range array { sum += value }
do |variable, (array, elements)|
is valid syntax. That's so neat :)