ITメンティーの補助輪

駆け出しメンティーの自分と、日本のどこかにいる誰かのための補助輪

【追記あり】Rubyの「ローカル変数のスコープにおける仕様変遷」の補助輪

2003年のスラッシュドットの記事(Matzさんのインタビュー記事)を拝読していたところ、「その後の動向」が気になる内容を見つけました。

まつもとゆきひろさん 答える

🔗 まつもとゆきひろ 答える | スラド

(一部抜粋)

【質問者さん】
Ruby の仕様で、これはやめておけばよかったというものはありますか?

【Matzさん】
あんまりないです。今のRubyとまったく異なってRubyと同じくらい良い言語は存在できるだろうとは思いますが、Rubyをそのように変えようとは思いません。
変えるとしたら、Larryも指摘したローカル変数のスコープくらいでしょうか。 これは2.0(Rite)で変更しようと考えています。

この記事を拝読し、「ローカル変数のスコープの仕様」がその後どのように変更されていったのか(または変更されなかったのか)が気になり調べたのですが自力で見つけることができず…。

キニナル病を治すべく、Quoraで質問させていただきました😅

ささださん 答える

すると、すぐに笹田さんからご回答いただきキニナル病はあっという間に完治…!

「ローカル変数の仕様変更」として「ブロックパラメータのシャドウィング」を教えていただきました。

ありがとうございます!!

🔗 2003年頃のインタビュー記事でMatzさんが「Rubyのローカル変数のスコープを直したい」とおっしゃっていたのですが、実際に仕様変更は行われたのでしょうか?(旧仕様が気になりまして…) - Quora


【仕様変更】ブロックパラメータのシャドウィング(Ruby 1.9 〜)

( 以下は自分なりの解釈を加えたまとめにつき、いただいたご回答の原文はぜひ上記Quoraのリンクよりご覧くださいませ🙇🏻‍♂️ )

# コード例
i = 10
1.times { |i| }
p i

Ruby 1.8 まで

  • ブロックパラメータは「外側のi」だった
  • そのため、1.times { |i| の部分で、ブロックの外側の変数iに「i = 0」と代入され、ブロックを抜けた後のp iは「0」を出力していた
# Ruby 1.8 まで
i = 10
1.times { |i| }
p i #=> 0

Ruby 1.9 から

  • 1.times { |i|iが「ブロックの中のローカル変数」に変わった
    • (shadowing / シャドウィング)
  • そのため、外側の変数とは別の変数ii = 0 が代入され、ブロックから抜けても外側の変数iはそのままなので p i は「10」を出力する
# Ruby 1.9 から
i = 10
1.times { |i| }
p i #=> 10
  • ただし「外側と同じ名前を新たに使うよ」ということを明示するため、ruby -wで起動すると warning: shadowing outer local variable -i という警告を出すようにしていた
    • ruby -w … 冗長モードでRubyプログラムを実行する
      • (普段出力されないwarningを出力してくれる)
  • Ruby 2.6 からこの警告は消えた

Ruby 1.9 で一緒に加わった仕様

ブロックパラメータではないが、ブロック内で同名の新しい変数を明示的に宣言するための記法(例 |; i|)がRuby 1.9 からサポートされた。

# コード例
i = 10
1.times { |; i| i = 0 }
p i #=> 10

※ 余談: この記法をどこかで見た気がして手元の書籍・自分の書きなぐりメモを探したところ、書籍「 プロを目指す人のためのRuby入門 」のP.129で紹介されていた😆
伊藤さん、さすがっス…!

(まとめ ここまで)


【2020/11/19追記】Matzさんからもご回答いただいた!

Rubyのブロックローカル変数のスコープ、実は「外側での事前の宣言(代入)を避けるアイデア」が玉造温泉で生まれていたことを教えていただきました(残念ながらその後、不採用となったようです…)。

ご興味のある方はぜひ上記QuoraのリンクよりMatzさんのご回答をご覧くださいませ🙇🏻‍♂️
…いや、結構上にあるのでもう一度貼っておきます!

🔗 2003年頃のインタビュー記事でMatzさんが「Rubyのローカル変数のスコープを直したい」とおっしゃっていたのですが、実際に仕様変更は行われたのでしょうか?(旧仕様が気になりまして…) - Quora

笹田さんに続き、Matzさんからもご回答いただいてしまった…。これから自分はQuoraを「Quoraさん」と呼ぶことにします。

謝辞

笹田さん、ご回答いただきありがとうございました!

(2020/11/19追記)
Matzさん、ご回答いただきありがとうございました!