変数宣言が無くても大丈夫?
2007.03.10 Saturday 23:43
プログラミング言語のPython, Rubyに共通の特徴としてC, Java等にある変数宣言が無いことを挙げられる.これまで自分にはこれがバグの温床となりそうで気持ち悪く,それ故これらには手を出さなかった,
しかし最近は動的言語が開発効率の高さにおいて注目されている.
この矛盾について一応自分なりに出した結論は
* 型付けの強さである程度保証できる
* 開発環境による保証を前提とすればよい
しかし最近は動的言語が開発効率の高さにおいて注目されている.
この矛盾について一応自分なりに出した結論は
* 型付けの強さである程度保証できる
* 開発環境による保証を前提とすればよい
参考記事
まつもとゆきひろのプログラミング言語論
境界を越える: Javaモデルを超える型定義戦略
変数宣言のある言語として,C, C++, Java, (Perl), (VisualBasic), (JavaScript), PHP等が挙げられる.()は必須ではないことを意味する.
さて,一言で変数宣言といってもC, C++, JavaのそれとVisualBasic,JavaScript, Perlのそれは性質が異なる.前者は入れ物に型が付いているので,入れ物を明示的に用意しないと使うことが出来ない.後者では宣言は本当に使うという宣言に過ぎず(VisualBasicのVariantを含む),使おうと思えば宣言しなくても使える.
無くても良い物を使う理由はスコープである.元々スコープの考え方が無く,変数が全てグローバルなところから出発した言語,あるいは利便性を重視してグローバルスコープが優先される言語ではローカル変数を明示する記号が必要だ.一般的にグローバル変数の使用は良くないと言われており,宣言の強制はグローバル変数の安易な利用を防止するものであろう.そして宣言を強制することでもう一つの効果である変数名誤りの防止効果が現れる.
バグの中でも最悪なのは期待通りに動かないけど何もエラーが出ないパターン.エラーが出ればそこを見ればよいが,誤ったまま先に進んで最後に気付くようだとどこで間違ったのか見当が付かない.そして,ありがちなミスがスペルミスと変数名誤り.変数名誤りは他のコードを流用したり,気が変わって変数名を変えたりすると発生する.こうなると入れたはずの値が取り出されず,わかりにくいバグとなる.
例えばPerlの場合,最初に参照された場合に中身が空であると勝手に解釈してくれる.そのため,例えばcccに値を入れて,取り出すときに誤ってcceとしても黙って空の値(厳密にはundefだが,文脈によって0にも""にも変わる)を渡してくれる.
Perlでuse strictを使うと,宣言されていない変数へのアクセスが全てコンパイルエラーとなる.自分はこのuse strictとperl -cwを使ってCと同じように最初にコンパイルエラーが出ないことを確認してから実行している.ちなみにuse strictを使わない場合でもperl -cwでは1回しか使われていない変数に対してミススペルの可能性が高いことを警告してくれる.
同様の機能としてVisual BasicにはOption Explicitが用意されている.
JavaScriptは慣れていないので突っ込んだことは言えないのだが,言語上は宣言無しでグローバル変数を使える機能を防ぐことはできなさそうだ.JSLintを使って変数をリストアップすれば,実行前の発見もかろうじて出来そうである.
PythonやRubyには基本的には変数宣言が存在しない.Pythonにはglobalという宣言が存在するが,宣言せずに使えばローカル変数になるので普通は宣言しない.Rubyはスコープを変数の接頭記号で区別するので宣言は全くない.では,どうやって安全性を保ってプログラムが作れるのだろうか.PythonやRubyを使った場合にどうなるかをPerlと比較してみようと思う.
結論の1つめである「型付けの強さ」について.Perlでは未定義の変数を参照した場合に良きに計らってくれることは上で述べた.それに対してRuby及びPythonは強い型付けが行われているので未定義は他の値に自動変換されない.使われていない変数をいきなり参照したらエラーとして検出されるので,値を渡したつもりで0だったという間違いはおおむね回避できる.(JavaScriptも初期値に関しては同様).しかし代入文で代入先を誤ったらその先は全滅だ.
そこでいろいろ考えた挙げ句,2つめの「開発環境による保証」に行き着いた.端的に言えばプログラムの正確性を保証するのは言語仕様ではなく開発環境の責任で行うべきという考え方である.
プログラムを書くときはどのような環境を使っているだろうか.お気に入りのエディタか.与えられた統合環境か.まさかメモ帳という人は(プログラミングを始めたばかりでなければ)いないだろう.
ここで,例えば補完機能があるエディタでは補完機能を最大限使うことでミススペル問題はある程度避けられる.あるはずの名前が候補に出てこなかったり紛らわしい物が2つ候補に出たりすればミススペルの可能性が高い.ただ,これだけでは変数名誤りは検出できない.
もっと考えを進めてみよう.例えば最初に使われた変数とそれ以外の変数を別の色で表示するエディタや,変数の一覧を常時近くに表示してくれるエディタがあれば変数名の誤りに直ちに気付くだろう.そのとき変数宣言は行数を増やすだけの冗長な代物に成り下がる.
たとえて言えば(極端な例だが),地雷を避けて進める装置があれば安全な道を遠回りするより地雷原を真っ直ぐ進んだ方が早い,といった感じだろうか.しかし裏を返せば,その装置を持たない人は真似をせずに安全な道を歩くべきとも言える.
現実問題として複数のプログラミング言語を使う身としては使い慣れたエディタをいつも使いたい.この2つの要求が矛盾しないためには,エディタには(色分けにとどまらず)言語に特化したお助け機能を豊富に用意することが必要であろう.
2009/12/29追記
python 用 lint、Pyflakes vs. pyChecker vs. pylint - 傀儡師の館.Python - 楽天ブログ(Blog)
まつもとゆきひろのプログラミング言語論
境界を越える: Javaモデルを超える型定義戦略
変数宣言のある言語として,C, C++, Java, (Perl), (VisualBasic), (JavaScript), PHP等が挙げられる.()は必須ではないことを意味する.
さて,一言で変数宣言といってもC, C++, JavaのそれとVisualBasic,JavaScript, Perlのそれは性質が異なる.前者は入れ物に型が付いているので,入れ物を明示的に用意しないと使うことが出来ない.後者では宣言は本当に使うという宣言に過ぎず(VisualBasicのVariantを含む),使おうと思えば宣言しなくても使える.
無くても良い物を使う理由はスコープである.元々スコープの考え方が無く,変数が全てグローバルなところから出発した言語,あるいは利便性を重視してグローバルスコープが優先される言語ではローカル変数を明示する記号が必要だ.一般的にグローバル変数の使用は良くないと言われており,宣言の強制はグローバル変数の安易な利用を防止するものであろう.そして宣言を強制することでもう一つの効果である変数名誤りの防止効果が現れる.
バグの中でも最悪なのは期待通りに動かないけど何もエラーが出ないパターン.エラーが出ればそこを見ればよいが,誤ったまま先に進んで最後に気付くようだとどこで間違ったのか見当が付かない.そして,ありがちなミスがスペルミスと変数名誤り.変数名誤りは他のコードを流用したり,気が変わって変数名を変えたりすると発生する.こうなると入れたはずの値が取り出されず,わかりにくいバグとなる.
例えばPerlの場合,最初に参照された場合に中身が空であると勝手に解釈してくれる.そのため,例えばcccに値を入れて,取り出すときに誤ってcceとしても黙って空の値(厳密にはundefだが,文脈によって0にも""にも変わる)を渡してくれる.
Perlでuse strictを使うと,宣言されていない変数へのアクセスが全てコンパイルエラーとなる.自分はこのuse strictとperl -cwを使ってCと同じように最初にコンパイルエラーが出ないことを確認してから実行している.ちなみにuse strictを使わない場合でもperl -cwでは1回しか使われていない変数に対してミススペルの可能性が高いことを警告してくれる.
同様の機能としてVisual BasicにはOption Explicitが用意されている.
JavaScriptは慣れていないので突っ込んだことは言えないのだが,言語上は宣言無しでグローバル変数を使える機能を防ぐことはできなさそうだ.JSLintを使って変数をリストアップすれば,実行前の発見もかろうじて出来そうである.
PythonやRubyには基本的には変数宣言が存在しない.Pythonにはglobalという宣言が存在するが,宣言せずに使えばローカル変数になるので普通は宣言しない.Rubyはスコープを変数の接頭記号で区別するので宣言は全くない.では,どうやって安全性を保ってプログラムが作れるのだろうか.PythonやRubyを使った場合にどうなるかをPerlと比較してみようと思う.
結論の1つめである「型付けの強さ」について.Perlでは未定義の変数を参照した場合に良きに計らってくれることは上で述べた.それに対してRuby及びPythonは強い型付けが行われているので未定義は他の値に自動変換されない.使われていない変数をいきなり参照したらエラーとして検出されるので,値を渡したつもりで0だったという間違いはおおむね回避できる.(JavaScriptも初期値に関しては同様).しかし代入文で代入先を誤ったらその先は全滅だ.
そこでいろいろ考えた挙げ句,2つめの「開発環境による保証」に行き着いた.端的に言えばプログラムの正確性を保証するのは言語仕様ではなく開発環境の責任で行うべきという考え方である.
プログラムを書くときはどのような環境を使っているだろうか.お気に入りのエディタか.与えられた統合環境か.まさかメモ帳という人は(プログラミングを始めたばかりでなければ)いないだろう.
ここで,例えば補完機能があるエディタでは補完機能を最大限使うことでミススペル問題はある程度避けられる.あるはずの名前が候補に出てこなかったり紛らわしい物が2つ候補に出たりすればミススペルの可能性が高い.ただ,これだけでは変数名誤りは検出できない.
もっと考えを進めてみよう.例えば最初に使われた変数とそれ以外の変数を別の色で表示するエディタや,変数の一覧を常時近くに表示してくれるエディタがあれば変数名の誤りに直ちに気付くだろう.そのとき変数宣言は行数を増やすだけの冗長な代物に成り下がる.
たとえて言えば(極端な例だが),地雷を避けて進める装置があれば安全な道を遠回りするより地雷原を真っ直ぐ進んだ方が早い,といった感じだろうか.しかし裏を返せば,その装置を持たない人は真似をせずに安全な道を歩くべきとも言える.
現実問題として複数のプログラミング言語を使う身としては使い慣れたエディタをいつも使いたい.この2つの要求が矛盾しないためには,エディタには(色分けにとどまらず)言語に特化したお助け機能を豊富に用意することが必要であろう.
2009/12/29追記
python 用 lint、Pyflakes vs. pyChecker vs. pylint - 傀儡師の館.Python - 楽天ブログ(Blog)
Comments