Rubyのイテレータ変数itを喜ぶ記事
プログラミング::lang
序
Ruby
3.4がリリースされ、新しい機能としてイテレータ変数it
が追加された。
これが意味するところは、これを使う人ならだいたい分かるし、解説しても「そんなん知ってるし、分かるし」になるだろう。
だが、これはかなり嬉しいので謎の解説をする記事を勢いで書いた。
it
について
Rubyの場合標準的なブロックの構造はこんな感じ。
[1, 2, 3].each do |i|
puts i
end
i
は一般的なイテレータ変数である。
イテレータ変数のような一時変数を使うメリットは、それがイテレータ内に閉じた使い捨ての変数であることが明瞭という、リーディングコストの低さだ。
for (const i of [1,2,3]) {
console.log(i)
}
イテレータ変数は基本的に自分が所属する直近のブロックで定義されているものという前提で探すことができる。 2ブロックのネストループなどでは2レベル探すこともあるが、基本的には1つの文脈に閉じて定義すべきものだ。
そして、複数イテレータ変数を用意する場合はちょっと困る。i
,
j
あたりがせいぜいで、数が多いときはイテレータ変数を使うべきでないように見える。
つまり、だいたいはイテレータ変数を使うときはi
なのだ。
だったら、暗黙にi
を使わせてくれても良いのではないかと思うことがある。
[1, 2, 3].each do
puts i
end
そういう使い方ができるように追加されたのが、今回のit
だ。
[1, 2, 3].each do
puts it
end
従来も同じ用途で_1
という変数を使うことができたが、「_1
を使うと_2
があるのではないかと思ってしまってreading
costが高い」という理由でit
が導入されたらしい。
私は_1
にPerl的な汚さを感じるので使わない。別にブロック変数書けばええやん。
itの使いどころ
it
は有効なケースというのが割と明確にある。
it
というキーワードを使うものとして私が思い浮かべるのはPandocのテンプレート。
アップデートで追加された機能だけれど、これにより連想配列の配列が使えるようになった。
$for(links)$
<li><a href="${it.url}">${it.title}
$endfor$
みたいなことができる。
とりあえず簡潔なイテレータでは結構効果が大きい。
.map { it[:score] } ary
連想配列の配列でもやはり便利。
.each do
ary+= it[:score]
sum end
ネストされたブロックからアクセスすると混乱を招くから、使えるケースはかなり短いブロックに限られてくる。 とはいえ、イテレータではないブロックでも便利なケースはあるだろう。
File.open path do
= it.read
data end
もっとも、この場合は英語的には目的語に来るべきitが主語に来ているように見えるのが気になるから嫌だという人はいそう。
it
は直近のブロックのみを対象にするため、ネストしたブロックの内側でit
を使うことはできないし、そもそもブロックをネストさせるとit
が意味するものが場所によって変わるため、そのようなブロックでは向いていない。
.each do
ary# itは配列の要素 (連想配列)
.each do |k,v|
it[k] #直近ブロックではk,vが定義されているのでエラーになる
it# `it` is not allowed when an ordinary parameter is defined
end
end
だいぶ嬉しい機能
実際の使いどころはとても限られるけど、あればつい使っちゃうような機能が久しぶりに追加されてかなり嬉しい。
ただ、気軽に使いたくなるからこそ、気軽に使うと最低バージョンが3.4.0になるということに注意が必要だろう。