Feature #6869
openDo not treat `_` parameter exceptionally
Description
I started by commenting on #6693, but i have realized that this is a slightly different request.
I propose to not treat the variable name "_" exceptionally. Current behavior:
 {0=>1}.each_with_index { |_,_| p _ } # [0, 1]
prints "[0, 1]", but
 {1=>2}.each_with_index { |x,x| p x } # SyntaxError: (eval):2: duplicated argument name
raises "SyntaxError: (eval):2: duplicated argument name".
Similarly for methods:
 def f(_, _)
   _
 end
 f(0, 1) # => 0
 def f(x, x)
   x
 end # => SyntaxError: (eval):2: duplicated argument name
Observe also that the use of repeated _ parameter is not consistent between methods and blocks: for methods the value is the first assigned value, and for blocks it is the array of all the assigned values.
- I propose to use the same rule for all variables, without distinguishing _specially.
In particular i propose to allow to repeat any variable, not only _, in block or method arguments without raising an error.
There may be several solutions what the repeated argument will hold: it may hold the array of all assigned values, the first assigned value, the last assigned value, the first non-nil assigned value, or the last non-nil assigned value.
- 
I propose to treat repeated arguments in methods and in blocks the same way (do not know which one). 
- 
For unused variables i propose to introduce a special placeholder, for example " -" not followed by anything other than a delimiter (comma or bracket):
 each_with_index { |-, value| puts value }
 -, -, suffix = parse(name)
        
           Updated by drbrain (Eric Hodel) about 13 years ago
          Updated by drbrain (Eric Hodel) about 13 years ago
          
          
        
        
      
      - Category set to core
- Assignee set to matz (Yukihiro Matsumoto)
Seems to be part of variable shadowing checks. The check was added before r8857 (which was a refactor of the feature) and checking for '_' was removed in r14186.
Since it was committed by matz I think your chances at acceptance are low.
        
           Updated by marcandre (Marc-Andre Lafortune) about 13 years ago
          Updated by marcandre (Marc-Andre Lafortune) about 13 years ago
          
          
        
        
      
      Hi,
alexeymuranov (Alexey Muranov) wrote:
I propose to not treat the variable name "
_" exceptionally.
Sorry for the naive question, but why? What are you trying to achieve? What real world problem do you want to fix?
- For unused variables i propose to introduce a special placeholder
I feel that unused variables do not warrant a change to the already complex Ruby syntax.
        
           Updated by alexeymuranov (Alexey Muranov) about 13 years ago
          Updated by alexeymuranov (Alexey Muranov) about 13 years ago
          
          
        
        
      
      marcandre (Marc-Andre Lafortune) wrote:
Hi,
alexeymuranov (Alexey Muranov) wrote:
I propose to not treat the variable name "
_" exceptionally.Sorry for the naive question, but why? What are you trying to achieve? What real world problem do you want to fix?
I do not like exceptions. When i was first learning Ruby, i thought that the underscore is a letter like any other, but sometimes it behaves like any other, and sometimes not.
It also seems to me more natural to use a placeholder for a discarded value than to assign it to a variable first and then discard.
- For unused variables i propose to introduce a special placeholder
I feel that unused variables do not warrant a change to the already complex Ruby syntax.
In my opinion, treating variables differently based on their names is also a part of syntax, and in my opinion such rules are harder to follow than a rule for a single placeholder. As there is no dedicated placeholder in Ruby now, this one may be adapted later to other situations as well, i think.
Update: The most important real world problem this addresses is reading the code! With a placeholder, it is immediately clear that the value is discarded, but with a special variable one needs to look through the code to be sure it is not used somewhere.
Plus one needs to remember currently what a repeated variable is holding in different situations.
        
           Updated by alexeymuranov (Alexey Muranov) over 11 years ago
          Updated by alexeymuranov (Alexey Muranov) over 11 years ago
          
          
        
        
      
      It looks like the use of the underscore _ as a "placeholder" is quite common in other languages ("black hole" register in Vim, "whatever" pattern that matches everything in Haskell), but there it is really a placeholder and not a variable: values "assigned" to _ cannot be retrieved.
With this in view, maybe, instead of this my proposal, the underscore can be "downgraded" to a "placeholder" (or "black hole" peudo-variable)?
        
           Updated by nobu (Nobuyoshi Nakada) over 11 years ago
          Updated by nobu (Nobuyoshi Nakada) over 11 years ago
          
          
        
        
      
      - Description updated (diff)
Alexey Muranov wrote:
Observe also that the use of repeated
_parameter is not consistent between methods and blocks: for methods the value is the first assigned value, and for blocks it is the array of all the assigned values.
It is unrelated to _, but because of Enumerable#each_with_index.
Try:
{0=>1}.each_with_index {|x,y| p x} # [0, 1]
Alexey Muranov wrote:
It looks like the use of the underscore
_as a "placeholder" is quite common in other languages ("black hole" register in Vim, "whatever" pattern that matches everything in Haskell), but there it is really a placeholder and not a variable: values "assigned" to_cannot be retrieved.
Isn't it more exceptional?
        
           Updated by alexeymuranov (Alexey Muranov) over 11 years ago
          Updated by alexeymuranov (Alexey Muranov) over 11 years ago
          
          
        
        
      
      Nobuyoshi Nakada wrote:
Alexey Muranov wrote:
Observe also that the use of repeated
_parameter is not consistent between methods and blocks: for methods the value is the first assigned value, and for blocks it is the array of all the assigned values.It is unrelated to
_, but because ofEnumerable#each_with_index.
Try:{0=>1}.each_with_index {|x,y| p x} # [0, 1]
Thanks, i do not know what i was thinking.
Alexey Muranov wrote:
It looks like the use of the underscore
_as a "placeholder" is quite common in other languages ("black hole" register in Vim, "whatever" pattern that matches everything in Haskell), but there it is really a placeholder and not a variable: values "assigned" to_cannot be retrieved.Isn't it more exceptional?
Yes, so this proposal would need to be closed, and i would need to open a new one. When i opened this one, i did not know that the underscore was a common "placeholder" in other languages and i thought that Ruby documentation presents the underscore in identifiers roughly as equivalent to a lowercase letter (doesn't it?).
Here is a sentence from the online version of Programming Ruby:
In these descriptions, lowercase letter means the characters ''a'' though ''z'', as well as ''_'', the underscore.
In any case, in Ruby the following works perfectly, and in my opinion this all is confusing:
_ = 1
p _
So, yes, my new proposal would be to downgrade the underscore to a placeholder, so that in something like this
foo do |_,x|
  # 10 lines of code
end
or
_, _, suffix = parse something
it would be immediately clear the values "assigned" to _ are discarded.
        
           Updated by docx (Lukas Dolezal) over 5 years ago
          Updated by docx (Lukas Dolezal) over 5 years ago
          
          
        
        
      
      Hi. This is interesting and I can see that the inconsistent treatment of _ can be confusing (I never noticed tho because I never tried to access _).
I wonder however, I always thought that _ is exactly explicitly part of syntax as "unused parameter". Am I wrong?
So if that is the case, what about going the other direction to remove the inconsistency of what value it takes, and just make it explicitly "unusable" - can we raise SyntaxError when any _ is being accessed inside of method/block?
        
           Updated by docx (Lukas Dolezal) over 5 years ago
          Updated by docx (Lukas Dolezal) over 5 years ago
          
          
        
        
      
      Re
In these descriptions, lowercase letter means the characters ''a'' though ''z'', as well as ''_'', the underscore.
I think what they mean here is that you can use it inside of a variable. Probably just did not realized the single underscore case :) But that is my interpretation.
        
           Updated by naruse (Yui NARUSE) almost 5 years ago
          Updated by naruse (Yui NARUSE) almost 5 years ago
          
          
        
        
      
      - Target version deleted (3.0)
        
           Updated by hsbt (Hiroshi SHIBATA) over 1 year ago
          Updated by hsbt (Hiroshi SHIBATA) over 1 year ago
          
          
        
        
      
      - Status changed from Open to Assigned