evalの罠

どうも私はevalに属する機能があまり好きでない。

evalってのは、たいてい「何らかの文字列をコードとして実行する」ものなので、便利で強力なカスタマイズ機能を手軽に付加してくれるのだけど、それが故に好きでない。

一番嫌なのは、この「何らかの文字列」をユーザに公開した時に、その機能を持ったプログラムが、

何の言語で書かれているか

をユーザに意識させてしまうという点だ。Rubyのevalなら、当然文字列が意味するところはRubyになる。LispのevalならLispになる。

これ自体は別に「そんなもの」なのだけど、この「文字列」をユーザに見せると事情が一変する。どんな言語でそのアプリケーションが書かれているなんて、本来ユーザは意識するもんじゃない。何であっても使えればそれでいい。ところが、evalを使う時点で「何で書かれているか」をユーザに意識させてしまう。と同時に、それを理解していることをユーザに要求してしまう。これがどうにも気に入らない。

100歩譲って、それが「しょうがないこと」だとしても、次に嫌になるのは、

evalされる環境が不明

という点だ。「環境に依存しないプログラムを書け」とか言われても、100%環境に依存しなかったら、そもそもそこでeval必要もない。もちろん「evalを使う」ということに十分配慮された環境が作られているのなら、そんな余計なことを心配しなくて済むものも少なくないのだけど、100%それは不可能だ。

ということで、evalを便利に使える局面というのは、かなり限定される。プログラマ向けツールやフレームワークの一部であれば、「そういったもの」であるからいいんだけど、定義体の中にちょろっとマクロ的に… というのは、どうも好きになれない。また、うっかり「汚染された文字列」をevalってしまう危険とかも皆無じゃない。それに頑張って対応させると、結局evalを自分で書くのと大差ない手間になってしまうわけで、それじゃあせっかくシンプルにやった意味がない。

確かに便利で強力な機能なんだけど、ちょっとした麻薬性があるし、それこそ麻薬のようにアプリケーションの寿命を縮めかねないし。

なので私はあまりevalは好きでない。普段使っている言語がCであるとか、parserやevalを書くことがそれ程苦じゃない(むしろ好き)だということもあって、evalが欲しくなる局面では、自前でevalみたいなものを作ってしまう方が好きだ。その方がいろいろ安全だし。

まぁ「evalを使うな」と声高に言う程のことではないけれど、evalを使いたいなーと思う前にevalの危険性がすぐ5個くらいは思い浮かばないと、スキル的には使っちゃいけないと思う。そうして挙げた危険性をクリアしている確信がある時にだけ、ちょこっと使う。それくらいストイックにしておいてもバチは当たらない機能だと思う。

PS.

同じような理由で、今時流行りの「evalするだけの定義体」も好きでない。確かに手軽に無限のカスタマイズが可能にするいい方法なんだろうけど、どうもアプリケーションの寿命を縮める元のような気がしてならない。