📝
[Feature #19764] パターンマッチを利用して呼び出されるメソッドをオーバーロードする提案
[Feature #19764] Introduce defp keyword for defining overloadable, pattern matched methods
- 以下のようにパターンマッチを利用して呼び出されるメソッドをオーバーロードしたいという提案
- 同名のメソッドを複数定義できる
- どのメソッドが呼び出されるのかはパターンマッチで制御する
defp call(String => s unless s in /^[a-z]/)
puts "string: #{s.inspect} (capitalized)"
end
defp call(String => s)
puts "string: #{s.inspect}"
end
defp call(Hash(foo:, bar:) => h)
puts "hash: #{h.inspect}"
end
defp call(**nil)
puts "no keyword args"
end
call("Example") # => string: "Example" (capitalized)
call("test") # => string: "test"
call(foo: 1, bar: 2)
# => hash: { :foo => 1, :bar => 2 }
- 上は以下のような疑似コードになる
-
case ...
は実際にかけないので動かない
-
def call(...)
case ...
in String => s unless s in /foo/
puts "string: #{s.inspect} (not foo)"
in String => s
puts "string: #{s.inspect}"
in Hash(foo:, bar:) => h
puts "hash: #{h.inspect}"
in **nil
puts "no keyword args"
else
raise NoMatchingMethod
end
end
- コメントでは
メソッドのオーバーロード
とメソッドシグネチャ内のパータンマッチ
を別々に考える必要があると書いてある - 後者に関しては以下のように利用したいと書いてある
def foo(nb => Integer) # class validation
def foo(minutes => 0..59) # range/structure validation
def foo(if: => condition) # alias for keyword argument (#18402)
def foo(v => @hostname) # DRY way to set instance variables (#15192 and many others)
- オーバーロードに関してはモンキーパッチを書かずにメソッドを拡張する事ができるので個人的にはあると便利
- 便利ではあるけどどこでどのメソッドが定義されているのかわからなくなる事もあるのでデメリットもある
- 引数に対してパターンマッチがかけるのも個人的にはめっちゃほしいけど、どういう感じで構文を考えるのかはむずかしそう
- 結局メソッドの中でパターンマッチかけばいいだけではあるので複雑な構文を導入してまでほしいのか?と言われるとウーン
Discussion