Actions
Feature #14973
closedProposal of percent literal to expand Hash
Status:
Closed
Assignee:
-
Target version:
-
Description
概要¶
変数名から { 変数名: 変数の値 }
という Hash を定義するための %記法の提案です。
以前からちょくちょく提案されていた
x = 1
y = 2
h = {x:, y:}
p h #=> {:x=>1, :y=>2}
のような ES6 ライクな構文を {}
構文ではなくて %記法で定義するものになります。
仕様¶
hoge = 1
foo = 2
bar = 3
# スペース区切りの変数名をキー、変数の値を Hash の値として展開する
%h(hoge foo bar) # => { hoge: 1, foo: 2, bar: 3 }
これは以下と同等の処理になります。
hoge = 1
foo = 2
bar = 3
{ hoge: eval("hoge"), foo: eval("foo"), bar: eval("bar") } # => { hoge: 1, foo: 2, bar: 3 }
ローカル変数以外¶
内部で eval
を使用しているので、そのコンテキストで評価できればローカル変数以外も使用することが出来ます。
def meth
"meth"
end
@hoge = 42
Foo = "str"
p %h(meth @hoge Foo $stdout)
# => {:meth=>"meth", :@hoge=>42, :Foo=>"str", :$stdout=>#<IO:<STDOUT>>}
キーは変数名そのままです($
や @
がついたまま。
重複したキーがある場合¶
キーが重複している場合、{}
と同様に2回目以降は無視されます。
hoge = 42
foo = "str"
%h(hoge foo hoge)
# => {:hoge=>42, :foo=>"str"}
キーの変数が存在しない場合¶
hoge = 42
foo = "str"
%h(hoge foo bar)
# Error: undefined local variable or method `bar' for main:Object (NameError)
Hash 内で展開¶
Hash なので **
で展開できます。
hoge = 42
foo = "str"
{ bar: "bar", **%h(hoge foo) }
# => {:bar=>"bar", :hoge=>42, :foo=>"str"}
式展開¶
%I
などと同様に式展開を行います。
hoge = 42
foo = "hoge"
%h(#{foo})
# => {:hoge=>42}
ユースケース¶
キーワード引数に渡す¶
Model = Struct.new(:tag, :name, :age, keyword_init: true)
def create_human(name:, age:)
# ** で Hash を展開して渡す
Model.new(tag: :human, **%h(name age))
# Model.new(tag: :human, name: name, age: age)
end
name = "mami"
age = 15
# 変数をまとめて渡す
create_human(%h(name age)) # => #<struct Model tag=:human, name="mami", age=15>
# create_human(name: name, age: age)
デバッグ出力として利用する¶
class Hash
# 適当なデバッグ出力用メソッド
def debug_output
each { |key, value|
puts "#{key}: #{value}"
}
end
end
def create(name, age)
# 引数を確認するためのデバッグ出力
%h(name age).debug_output
end
name = "homu"
age = 14
create(name, age)
# output:
# name: homu
# age: 14
その他¶
- キーは Symbol で定義 → String 版もあったほうがよいだろうか
- 式展開のみ実装 →
%i
みたいな式展開を行わないでほしいユースケースが思いつかなかった - なぜ
%h
という名前? →Hash
だから…
以上、任意の変数名から Hash を展開する %h
記法の提案でした。
ご意見等あればコメント頂けると助かります。
関連するチケット¶
https://bugs.ruby-lang.org/issues/11105
https://bugs.ruby-lang.org/issues/14579
https://bugs.ruby-lang.org/issues/13137
Files
Actions
Like0
Like0Like0Like0Like0Like0