rubyの%記法にハマった

  • 13
    Like
  • 0
    Comment
More than 1 year has passed since last update.

前提

  • ruby 2.3.1

やったこと

sample1.rb
require 'active_support'
require 'active_support/core_ext/hash/slice'

{ 'key1' => 'hoge', 'key2' => 'fuga', 'key3' => 'piyo' }.slice(*%w( key1 key2 ))
#=> { "key1" => "hoge", "key2" => "fuga" }

のようにハッシュから指定したキーのみの部分ハッシュを取得したかった.
この際sliceに渡すキーを%w(...)で指定していたつもりが下記のように%(...)になってしまっていた

sample2.rb
require 'active_support'
require 'active_support/core_ext/hash/slice'

{ 'key1' => 'hoge', 'key2' => 'fuga', 'key3' => 'piyo' }.slice(*%( key1 key2 ))
#=> { }

実行結果にもあるように,実はこれ文法エラーにならない.
区切り文字前が%のみの場合文字列として評価されてしまう.

sample3.rb
%w( a b c ) #=> ["a", "b", "c"]
%( a b c ) #=> " a b c "

なので,sample3.rbは実は下記と等価になり想定外の結果となっていたのでした.

require 'active_support'
require 'active_support/core_ext/hash/slice'

# キーを2つ指定したつもりが単なる文字列になってしまっていた...
{ 'key1' => 'hoge', 'key2' => 'fuga', 'key3' => 'piyo' }.slice(*" key1 key2 ")
#=> { }

文法上のエラーではないのでLintで気づかなくてハマった...

おまけ

日本語ドキュメントに%記法の区切り文字は%w、%W、%i、%I以外なら改行もいけると書いていたので試してみた

sample4.rb
x = %
This is a pen!

puts x 
This is a pen!

これはキモい

参考

http://ruby-doc.org/core-2.3.1/doc/syntax/literals_rdoc.html#label-Percent+Strings
http://docs.ruby-lang.org/ja/2.3.0/doc/spec=2fliteral.html#percent