Ruby でふつーの引数でもキーワード引数でも渡せるようにしたい

Swift の named parameters みたいな使い方のやつですかね。

こんなんでどうでしょうか、というのを tw では雑に書いたもののちゃんと清書していなかったので置いときます。

class Foo
  FOO__ARG1 = Object.new
  private_constant :FOO__ARG1
  FOO__NAME = Object.new
  private_constant :FOO__NAME


  def foo(_arg1 = FOO__ARG1, name: FOO__NAME)
    unless FOO__ARG1.equal?(_arg1)
      name = _arg1
    end
    if FOO__NAME.equal?(name)
      raise ArgumentError
    end

    puts "name: #{name}"
  end
end

Foo.new.foo(name: 'taro')
Foo.new.foo('hanako')
Foo.new.foo
$ ruby foo.rb
name: taro
name: hanako
Traceback (most recent call last):
        1: from foo.rb:24:in `<main>'
foo.rb:15:in `foo': ArgumentError (ArgumentError)

nil を使うと nil を渡せないということがあるので適当に Object.new して object_id 比較をしています。
引数が足りない場合は自前で raise してます。

これ書くのめんどいなーと思って、self.class.instance_method(__method__).params あたりでなんとかできないかなーとは思いつつ、実のところ自分ではそんなに使いそうにないからここでやめときます、


class Foo
  FOO__ARG1 = Object.new
  private_constant :FOO__ARG1

  def foo(_arg1 = FOO__ARG1, name: _arg1)
    if FOO__ARG1.equal?(name)
      raise ArgumentError
    end

    puts "name: #{name}"
  end
end

仮引数使うというアイデアのおかげでちょっと短くなりました。