SlideShare a Scribd company logo
1 of 20
Download to read offline
Ruby 3のキーワード引数
について考える
The Ruby Team
2018/09/15 (Sat.) 大江戸Ruby会議7
1
今日の議題
• Ruby 2のキーワード引数の問題
• Ruby 3に向けた改善の提案
2
『キーワード拡張』
• メソッドに新たにキーワード引数を持たせること
• 『キーワード拡張』は常に安全か?
– もともとあった呼び出しは元の通りに動いてほしい
def foo(...)
end
foo(...)
def foo(..., extension: false)
end
foo(...)
foo(..., extension: true)
3
キーワード拡張は安全でない
def foo(*args)
p args
end
foo(1, 2, 3) #=> [1, 2, 3]
foo(k: 42) #=> [{:k=>42}]
4
キーワード拡張は安全でない
def foo(*args, extension: false)
p args
end
foo(1, 2, 3) #=> [1, 2, 3]
foo(k: 42) #=> unknown key: k
5
問題:キーワード拡張が安全でない
• rest引数をとるメソッドのキーワード拡張は危険
– 既存コードが動かなくなるリスクがある
– optional引数も同様にダメ
• バグ報告が多数来ている
– #8316,#11967,#12104,#12717,#12821,#13336,#13647,#14130
• 実際にAPI拡張で困っている
– Thread.new(stack_size: 100000)とか
– Struct.new(keyword_init: true)とか
6
問題の原因
• キーワードとハッシュを自動変換していること
def foo(h)
p h #=>{:k=>42}
end
foo(k: 42)
def foo(k: 1)
p k #=> 42
end
foo({ k: 42 })
キーワード➔ハッシュ ハッシュ➔キーワード
7
Ruby 3での解決提案
• キーワードハッシュの変換をやめる #14183
– キーワードかハッシュか、明示してください
注意:Ruby 3の決定事項ではない
def foo(h)
p h #=>{:k=>42}
end
foo(k: 42)
def foo(k: 1)
p k #=> 42
end
foo({ k: 42 })
def foo(h)
p h[:k] #=> 42
end
foo({ k: 42 })
def foo(h)
p h #=>{:k=>42}
end
foo({ k: 42 })
def foo(**h)
p h #=>{:k=>42}
end
foo(k: 42)
def foo(k: 1)
p k #=> 42
end
foo(**{ k: 42 })
8
互換性の問題
• 修正箇所は少なくないが、修正は簡単
– だいたいは、**をつけるだけ
• 一部、むずかしいケースがある
9
互換性問題1:既存API
• キーワードとハッシュのどちらも許すAPI
• こういうAPIをRuby 3で定義するには?
– 修正方法:両方受け取ってマージしてください
erb.result_with_hash(k: 1)
erb.result_with_hash(hash)
def result_with_hash(h1={}, *h2)
h = h1.merge(h2)
...
end
10
互換性問題2:委譲
• 引数を丸投げするコード
• こういうコードをRuby 3で書くには?
– 修正方法:**kw も委譲してください
def forward(*args, &blk)
target(*args, &blk)
end
def forward(*args, **kw, &blk)
target(*args, **kw, &blk)
end
11
議題
• 議題0:問題と提案に対するお気持ちは?
• 議題1:foo(:key=>1)はキーワード?
• 議題1':foo("str"=>1, key:2)は?
• 議題2:既存APIのための記法?
• 議題3:委譲のための記法?
12
議題1
• Ruby 3で、以下はキーワード?ハッシュ?
– 案1:キーワードにする?(Ruby 2と互換)
– 案2:=>だったら常にハッシュにする?(非互換)
– 案3:文法エラー?(=>は{}を書かないとダメ)
foo(:key=>1)
13
議題1'
• Ruby 3で、以下はキーワード?ハッシュ?
– 案1:キーの種類で自動分割する?
• foo({"str"=>1}, key:2)
– 案2:非Symbolがあったら全部ハッシュ?
• foo({"str"=>1, key:2})
– 案3:文法エラーにする?(混ぜるな危険)
• 参考:こういうAPIは実在する(Kernel#spawn)
foo("str"=>1, key:2)
14
議題1''
• Ruby 3で、以下はキーワード?ハッシュ?
– 案1:キーの種類で自動分割する?
• foo({"s"=>2,"ss"=>4}, k:1, kk:3)
– 案2:非Symbolがあったら全部ハッシュ?
• foo({k:1, "s"=>2, kk:3, "ss"=>4})
– 案3:文法エラーにする?(混ぜるな危険)
foo(k:1, "s"=>2, kk:3, "ss"=>4)
15
議題2
• Ruby 2のように動くメソッドを簡単に定義したい
– 案1:諦めてもらう
• 手動マージしてください
– 案2:互換定義用のAPIを提供する
def result_with_hash(***h); end
ruby2 def result_with_hash(h); end
define_ruby2_method(:result_with_hash){}
16
議題3
• Ruby 2.6 と Ruby 3 の両方でうごく委譲は?
– 委譲専用の記法を導入する? #3447
def forward(...)
target(...)
end
17
議題3'
• Ruby 2.6 と Ruby 3 の両方でうごく委譲は?
– ↓は Ruby2.6で若干問題がある
– forward() が target(**{}) を呼ぶ
• target()とtarget(**{})は微妙に意味が違う
• 実用上は問題ない?
def forward(*args, **kw, &blk)
target(*args, **kw, &blk)
end
18
議題3''
• Ruby 2.5 は **{} がバグっている #15052
• 2.6で、どう直す?
def foo(opt=42)
p opt
end
foo(**{}) #=> 42
h={}
foo(**h) #=> {}
19
議題3'''
• Ruby 2.6で、以下の意味は?
foo(**{})
def foo(opt=42,**kw)
p [opt, kw]
end
foo({}, **{})
#foo({})と同じ
#=> [42, {}]
def foo(opt=42)
p opt
end
foo(**{}) #=> {}
案1:「無」とみなす? 案2:空ハッシュを渡す?
案3:いい感じに(難しい)
20

More Related Content

What's hot

たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数Shinichi Kozake
 
Redmineとgitの 連携利用事例
Redmineとgitの 連携利用事例Redmineとgitの 連携利用事例
Redmineとgitの 連携利用事例Tomohisa Kusukawa
 
GoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンGoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンAkihiko Horiuchi
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!kwatch
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐりKazuyuki TAKASE
 
Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略Takayuki Shimizukawa
 
SQLアンチパターン~スパゲッティクエリ
SQLアンチパターン~スパゲッティクエリSQLアンチパターン~スパゲッティクエリ
SQLアンチパターン~スパゲッティクエリItabashi Masayuki
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南Mikiya Okuno
 
ネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けモノビット エンジン
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
SQLアンチパターン - ナイーブツリー
SQLアンチパターン - ナイーブツリーSQLアンチパターン - ナイーブツリー
SQLアンチパターン - ナイーブツリーke-m kamekoopa
 
今日から使おうSmalltalk
今日から使おうSmalltalk今日から使おうSmalltalk
今日から使おうSmalltalkSho Yoshida
 
RLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoRLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoTakayuki Shimizukawa
 
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)mosa siru
 
メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?Takuya Ueda
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話Takuto Wada
 
PHP の GC の話
PHP の GC の話PHP の GC の話
PHP の GC の話y-uti
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門Hideyuki Tanaka
 

What's hot (20)

たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数
 
Redmineとgitの 連携利用事例
Redmineとgitの 連携利用事例Redmineとgitの 連携利用事例
Redmineとgitの 連携利用事例
 
GoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンGoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホン
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり
 
Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略Webアプリを並行開発する際のマイグレーション戦略
Webアプリを並行開発する際のマイグレーション戦略
 
show innodb status
show innodb statusshow innodb status
show innodb status
 
Oss貢献超入門
Oss貢献超入門Oss貢献超入門
Oss貢献超入門
 
SQLアンチパターン~スパゲッティクエリ
SQLアンチパターン~スパゲッティクエリSQLアンチパターン~スパゲッティクエリ
SQLアンチパターン~スパゲッティクエリ
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南
 
ネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分けネットワーク ゲームにおけるTCPとUDPの使い分け
ネットワーク ゲームにおけるTCPとUDPの使い分け
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
SQLアンチパターン - ナイーブツリー
SQLアンチパターン - ナイーブツリーSQLアンチパターン - ナイーブツリー
SQLアンチパターン - ナイーブツリー
 
今日から使おうSmalltalk
今日から使おうSmalltalk今日から使おうSmalltalk
今日から使おうSmalltalk
 
RLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoRLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for Django
 
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
 
メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?メルカリ・ソウゾウでは どうGoを活用しているのか?
メルカリ・ソウゾウでは どうGoを活用しているのか?
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話
 
PHP の GC の話
PHP の GC の話PHP の GC の話
PHP の GC の話
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 

More from mametter

error_highlight: User-friendly Error Diagnostics
error_highlight: User-friendly Error Diagnosticserror_highlight: User-friendly Error Diagnostics
error_highlight: User-friendly Error Diagnosticsmametter
 
TRICK 2022 Results
TRICK 2022 ResultsTRICK 2022 Results
TRICK 2022 Resultsmametter
 
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料mametter
 
Enjoy Ruby Programming in IDE and TypeProf
Enjoy Ruby Programming in IDE and TypeProfEnjoy Ruby Programming in IDE and TypeProf
Enjoy Ruby Programming in IDE and TypeProfmametter
 
TypeProf for IDE: Enrich Development Experience without Annotations
TypeProf for IDE: Enrich Development Experience without AnnotationsTypeProf for IDE: Enrich Development Experience without Annotations
TypeProf for IDE: Enrich Development Experience without Annotationsmametter
 
Ruby 3の型解析に向けた計画
Ruby 3の型解析に向けた計画Ruby 3の型解析に向けた計画
Ruby 3の型解析に向けた計画mametter
 
emruby: ブラウザで動くRuby
emruby: ブラウザで動くRubyemruby: ブラウザで動くRuby
emruby: ブラウザで動くRubymametter
 
Type Profiler: Ambitious Type Inference for Ruby 3
Type Profiler: Ambitious Type Inference for Ruby 3Type Profiler: Ambitious Type Inference for Ruby 3
Type Profiler: Ambitious Type Inference for Ruby 3mametter
 
型プロファイラ:抽象解釈に基づくRuby 3の静的解析
型プロファイラ:抽象解釈に基づくRuby 3の静的解析型プロファイラ:抽象解釈に基づくRuby 3の静的解析
型プロファイラ:抽象解釈に基づくRuby 3の静的解析mametter
 
Ruby 3の型推論やってます
Ruby 3の型推論やってますRuby 3の型推論やってます
Ruby 3の型推論やってますmametter
 
マニアックなRuby 2.7新機能紹介
マニアックなRuby 2.7新機能紹介マニアックなRuby 2.7新機能紹介
マニアックなRuby 2.7新機能紹介mametter
 
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3mametter
 
A Plan towards Ruby 3 Types
A Plan towards Ruby 3 TypesA Plan towards Ruby 3 Types
A Plan towards Ruby 3 Typesmametter
 
Ruby 3 の型解析に向けた計画
Ruby 3 の型解析に向けた計画Ruby 3 の型解析に向けた計画
Ruby 3 の型解析に向けた計画mametter
 
A Type-level Ruby Interpreter for Testing and Understanding
A Type-level Ruby Interpreter for Testing and UnderstandingA Type-level Ruby Interpreter for Testing and Understanding
A Type-level Ruby Interpreter for Testing and Understandingmametter
 
本番環境で使える実行コード記録機能
本番環境で使える実行コード記録機能本番環境で使える実行コード記録機能
本番環境で使える実行コード記録機能mametter
 
Transcendental Programming in Ruby
Transcendental Programming in RubyTranscendental Programming in Ruby
Transcendental Programming in Rubymametter
 
Cookpad Hackarade #04: Create Your Own Interpreter
Cookpad Hackarade #04: Create Your Own InterpreterCookpad Hackarade #04: Create Your Own Interpreter
Cookpad Hackarade #04: Create Your Own Interpretermametter
 
TRICK 2018 results
TRICK 2018 resultsTRICK 2018 results
TRICK 2018 resultsmametter
 
Type Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesType Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesmametter
 

More from mametter (20)

error_highlight: User-friendly Error Diagnostics
error_highlight: User-friendly Error Diagnosticserror_highlight: User-friendly Error Diagnostics
error_highlight: User-friendly Error Diagnostics
 
TRICK 2022 Results
TRICK 2022 ResultsTRICK 2022 Results
TRICK 2022 Results
 
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
 
Enjoy Ruby Programming in IDE and TypeProf
Enjoy Ruby Programming in IDE and TypeProfEnjoy Ruby Programming in IDE and TypeProf
Enjoy Ruby Programming in IDE and TypeProf
 
TypeProf for IDE: Enrich Development Experience without Annotations
TypeProf for IDE: Enrich Development Experience without AnnotationsTypeProf for IDE: Enrich Development Experience without Annotations
TypeProf for IDE: Enrich Development Experience without Annotations
 
Ruby 3の型解析に向けた計画
Ruby 3の型解析に向けた計画Ruby 3の型解析に向けた計画
Ruby 3の型解析に向けた計画
 
emruby: ブラウザで動くRuby
emruby: ブラウザで動くRubyemruby: ブラウザで動くRuby
emruby: ブラウザで動くRuby
 
Type Profiler: Ambitious Type Inference for Ruby 3
Type Profiler: Ambitious Type Inference for Ruby 3Type Profiler: Ambitious Type Inference for Ruby 3
Type Profiler: Ambitious Type Inference for Ruby 3
 
型プロファイラ:抽象解釈に基づくRuby 3の静的解析
型プロファイラ:抽象解釈に基づくRuby 3の静的解析型プロファイラ:抽象解釈に基づくRuby 3の静的解析
型プロファイラ:抽象解釈に基づくRuby 3の静的解析
 
Ruby 3の型推論やってます
Ruby 3の型推論やってますRuby 3の型推論やってます
Ruby 3の型推論やってます
 
マニアックなRuby 2.7新機能紹介
マニアックなRuby 2.7新機能紹介マニアックなRuby 2.7新機能紹介
マニアックなRuby 2.7新機能紹介
 
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3A Static Type Analyzer of Untyped Ruby Code for Ruby 3
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
 
A Plan towards Ruby 3 Types
A Plan towards Ruby 3 TypesA Plan towards Ruby 3 Types
A Plan towards Ruby 3 Types
 
Ruby 3 の型解析に向けた計画
Ruby 3 の型解析に向けた計画Ruby 3 の型解析に向けた計画
Ruby 3 の型解析に向けた計画
 
A Type-level Ruby Interpreter for Testing and Understanding
A Type-level Ruby Interpreter for Testing and UnderstandingA Type-level Ruby Interpreter for Testing and Understanding
A Type-level Ruby Interpreter for Testing and Understanding
 
本番環境で使える実行コード記録機能
本番環境で使える実行コード記録機能本番環境で使える実行コード記録機能
本番環境で使える実行コード記録機能
 
Transcendental Programming in Ruby
Transcendental Programming in RubyTranscendental Programming in Ruby
Transcendental Programming in Ruby
 
Cookpad Hackarade #04: Create Your Own Interpreter
Cookpad Hackarade #04: Create Your Own InterpreterCookpad Hackarade #04: Create Your Own Interpreter
Cookpad Hackarade #04: Create Your Own Interpreter
 
TRICK 2018 results
TRICK 2018 resultsTRICK 2018 results
TRICK 2018 results
 
Type Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signaturesType Profiler: An Analysis to guess type signatures
Type Profiler: An Analysis to guess type signatures
 

Ruby 3のキーワード引数について考える