わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

アスタリスク2つで,ハッシュをキーワード引数に

 今年に入ってから,あるRubyスクリプトでエラーが発生していました.
 先日久しぶりに動かしてみましたが,やはり途中でエラー終了となりました.
 FileUtils.mkdir_pメソッドを呼び出した際に,「ArgumentError (wrong number of arguments (given 2, expected 1))」と出ます.後ろから前に訳していくと,このメソッドは本来(expected = 期待されるのは)引数が1個なんだけど,コードでは(given = 与えているのは)2個で,引数の数がおかしいよ,ということでArgumentErrorです.
 実際のところ,mkdir_pには,ディレクトリ名を指定すればいいのだから,引数は1個でいいはずです.と思いながらhttps://docs.ruby-lang.org/ja/latest/class/FileUtils.html#M_MAKEDIRSを見ると,mkdir_pの引数は,作成するディレクトリ(文字列または配列)のlistと,「options = {}」というオプションです.オプションの説明は,https://docs.ruby-lang.org/ja/latest/class/FileUtils.htmlのはじめのほうに書かれています.
 Emacsで,Rubyスクリプトを開いて見ました.エラーの行,第2引数はインスタンス変数@optでした.この変数は「@opt = {:verbose => true}」で代入していました.
 irbコマンドを使って,動作確認してみますか….

$ irb
irb(main):001:0> require "fileutils"
=> false
irb(main):002:0> FileUtils.mkdir_p("a", {:verbose => true})
Traceback (most recent call last):
5: from /(略)/.rbenv/versions/3.0.0-dev/bin/irb:23:in `

'
4: from /(略)/.rbenv/versions/3.0.0-dev/bin/irb:23:in `load'
3: from /(略)/.rbenv/versions/3.0.0-dev/lib/ruby/gems/3.0.0/gem
s/irb-1.2.7/exe/irb:11:in `'
2: from (irb):1
1: from /(略)/.rbenv/versions/3.0.0-dev/lib/ruby/3.0.0/fileutil
s.rb:206:in `mkdir_p'
ArgumentError (wrong number of arguments (given 2, expected 1))

 やはり,エラーです.
 ハッシュを使わない,キーワード引数だと…うまくいきました.

irb(main):003:0> FileUtils.mkdir_p("a", verbose: true})
mkdir -p a
=> ["a"]
irb(main):004:0> FileUtils.rmdir("a", verbose: true)
rmdir a
=> ["a"]

 ブラウザで検索してみると,ハッシュオブジェクトからキーワード引数への自動変換が,Ruby 2.7で非推奨,そしてRuby 3ではできなくなるのを知りました.

 「今年に入ってから,エラー」の理由が,わかりました.rbenvを使って2.8.0-devをインストールし,このバージョンを使い始めたからです(ちなみに今は3.0.0-devです).
 対応策は,double splat演算子(**)とのこと.irbに戻って,試してみると…うまくいきました.

irb(main):005:0> FileUtils.mkdir_p("a", **{:verbose => true})
mkdir -p a
=> ["a"]
irb(main):006:0> FileUtils.rmdir("a", verbose: true)
rmdir a
=> ["a"]
irb(main):007:0> exit

 Emacsで編集です.FileUtilsのメソッドの最後の引数が,@optになっている箇所を,すべて「**@opt」に書き換えました.
 それから実行すると,エラーが出なくなり,期待どおりの処理をしてくれました.