This is a good example of the little inconsequential details that I love about Ruby. As much as I sometimes dislike the way things are done in the community, I always respect this attention to detail. It contrasts with the PHP approach of "what symbol is available to shoehorn in this new functionality", not to pick on PHP but that's where I spent half my professional life.
I'm sorry, but special casing a variable name like this seems to be something that, in the long term, leads to a messy, overly complex, language and lots of traps for newcomers.
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.
> Is there any reason while the Ruby 1.8 behaviour that duplicate variable names are allowed was changed?
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.
I can see the argument for having a special symbol for this - but that is not what's happening here. The underscore is still a perfectly valid variable name and is used as such, only it behaves different from every other variable name. If it's supposed to be a special symbol don't make it a valid variable name.
Ruby also lets you do this in function definitions. Python doesn't special-case the underscore like Ruby does -- while I have occasionally wished otherwise, it is at least consistent with Python's language design principles that the special case doesn't exist.
I don't have a source for this, but it is my understanding that, even though the python interpreter doesn't special-case the "_" variable name, it is a convention to use the underscore in the same situations in python as are described in ruby in the article.
Apart from the special meaning of the underscore in interactive mode, and the function _() in Django, I don't think it's common to use _ as a placeholder in Python. I sometimes do it regardless, hoping its meaning should be clear enough, but it's less suitable than in Ruby because you can't use it to ignore multiple arguments.
Great post! I had no idea that Ruby supported _ for "don't care" in block declarations like that.
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?
slightly off topic, but it's always seemed weird to me that there is no english word for "don't care", it's a really awkward phrasing. - In boolean logic, we have true, false, and then no word for when it can be either.
Ruby defines 'map', 'each', and other iteration utilities as higher order functions. This means that, while it works for tuples, this does not for looping.
> Why does _ need to be special cased like this? In Python this works with any variable name.
To, 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.
Python also supports the '_' character in that same manner. It's just a legal variable name that is given special meaning when in the interactive interpreter.
>>> 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')]
Yes, _ indicating that a parameter is not relevant is how it's used in Haskell.
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.
Haskell is a relatively recent language; I know that Prolog (a completely different paradigm) did the same for underscores back in 1972, and I wouldn't be surprised if there is an even earlier example.
The ruby prompt Irb has _ as the value for the result of last expression as in Perl, it's pretty handy. Didn't know this that it could be used in destructuring like in Erlang.