rubynamed-parameterspositional-parameterruby-3

Why is it not possible to combine `...` and named arguments in Ruby 3?


In Ruby 3, the new ... syntax was introduced, allowing constructs like these:

def locked_run(...)
  lock
  run(...)
  unlock
end

This is documented here: https://rubyreferences.github.io/rubychanges/3.0.html

After this discussion (https://bugs.ruby-lang.org/issues/16378), it was decided to let positional arguments in as well:

  def block_section(name, ...)
    section(name, true, ...)
  end

However, the following still leads to a syntax error:

  def block_section(...)
    section(block_section: true, ...)
  end

Why are positional arguments allowed with ... but named arguments are not?


Solution

  • section(block_section: true, ...)
    

    This wouldn't be the correct syntax anyway. Looking at how Ruby does things, it expects named arguments (i.e., hash) to be the last arguments after the normal ones.

    def section(a,b,c,d: false)
      puts "#{a} #{b} #{c} #{d}"
    end
    
    def old_style_block_section(*args)
      section(*args,d: true)
      
      #=> syntax error, unexpected *, expecting ')'
      section(d: true,*args)
    end
    
    section(1,2,3,d: true)
    old_style_block_section(1,2,3)
    
    #=> syntax error, unexpected ',', expecting =>
    section(d: true,1,2,3)
    

    So what you would need is this:

    section(..., block_section: true)
    

    However, this still doesn't work, as it hasn't been implemented as part of the Ruby language grammar for the new ... currently.

    If you want this, I'd suggest creating an issue (or emailing or something else) to request it.