やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rustのシャドーイングについて

 今まで書いてきたプログラミング言語にはない概念だったので。

シャドーイング

let x = 0;
let x = "a";

 同名の変数が再宣言されたとき、前者を隠す(再宣言以降は前者は参照不可となり後者が参照される)。

let x = 0;
println("{}", x); // 0
let x = "a";
println("{}", x); // a

 ところでこのコード、せっかくミュータブルで不変にしているのに、シャドーイングのせいで再代入されたように見える。ミュータブルにする意義が薄れるように思うのだが……。

シャドーイングがない言語

 C/C++, C#, Javaなどはコンパイルエラーになる。

 他は以下。

  • Shellは再代入される。(問題があっても元から文字列型のみなのでエラーにならず誤動作する)
  • JavaScript, Pythonは再代入される。(型は実行時に決まる。問題があれば実行時エラーになる)

 「コンパイルする言語において、静的型付けで同一スコープ内に同名変数を宣言したら、コンパイルエラーになる」ものだと思っていた。

シャドーイングの価値

 同じものを意味するが型の違う変数がある。これに同じ名前をつけることができる。たとえば型名をプレフィックスとして「intVar」「strVar」などという冗長な名前にしなくてもよい。どちらも「Var」でいい。

シャドーイングの悪影響

 あるとしたら何か。

意図せず上書き

 まちがって別の変数であるべきものを同名の変数で再宣言してしまうことがあるかもしれない。バグの元。

 シャドーイングがない言語ならコンパイルエラーになってくれる。だが、シャドーイングがあるRust言語では上書きされてしまう。これに気づくにはユニットテストが必要だろう。(おそらくデバッグで変数の確認などしないだろうから)。後戻り作業が生じてしまう。

コードリーディング

 シャドーイングがあると、コードリーディングの手間が増える可能性がある。

 ある特定の変数名でコードをテキスト検索すると、再代入、再宣言(シャドーイング)の2種類があり、探しているコード箇所を見つけるのに少しだけ時間がかかるかもしれない。

 「変数名を流用できる」ことは名付けの手間が省ける反面、名前の一意性が下がってコードリーディングに手間取るかもしれない。トレードオフ。メンテより開発を優先か。もっとも、深刻ではないだろうが。

対象環境

$ uname -a
Linux raspberrypi 4.14.98-v7+ #1200 SMP Tue Feb 12 20:27:48 GMT 2019 armv7l GNU/Linux

前回まで