檜山さんが returnも嫌いな理由 という興味深いエントリを書かれている。
結論自体はまったく異論はないのだけど、どうにももやもやしたものを抱えていた。ついさっき、その正体が分かった気がしたので駄文ながらぐだぐだと書いてみる。
以下、続きを読む。からどうぞ

リターン議論! ランキング!
結論自体はまったく異論はないのだけど、どうにももやもやしたものを抱えていた。ついさっき、その正体が分かった気がしたので駄文ながらぐだぐだと書いてみる。
以下、続きを読む。からどうぞ

リターン議論! ランキング!
つまり、僕は檜山さんの意見じゃなくてメイヤーセンセのごイケンに賛成できないものを感じていたのね。
これは実は1つも賛成できない。
まず1なんだけども、変数Resultを使うってことは関数最後尾にC言語風にいうところの
return Result;
って行を挿入することに等しい。
でも、これってResultってだけじゃ何も意味をもっていなくて
return tmp;
って書いたのと情報量は変わらない。
僕は名前重要!主義者なのだからして、tmp だの val1 だのって変数は大嫌い。一例を挙げよう
かの有名なprintfの型宣言はこう
でもこの戻り値ってつかったことある人ってまずいないよね?
で、何かの拍子にこの戻り値を調べたくなったとする。で関数の実装を見るわけだ
ここで
はたして、どちらが情報量が多いだろうか?
2.についても、積極的に複数出口推進派として全否定したい。
いや、あれですよ
「必要以上に」むやみやたらに出口が多いプログラミングはあかんとは僕も思いますよ。
でもたくさんがアカンから出口は1つが一番だ!ってのは、かなり飛躍があるでしょ。
ぶっちゃけ、ただの思い込みなんじゃないの? と。
たとえば
というプログラムで、おかしな引数はわたしてないつもりなのになぜか0が帰る時があるとする
(もちろん、つもりってのが気のせいで呼び方が間違っているんだが)
そうするとこのプログラムだと return tolal; の行に total==0 の条件ブレークを貼らないといけない。
gdb とかでデバッグしてて条件ブレーク入れたら実行がやたら遅くなった。という経験を持つ人は多いと思うがインタプリタ言語はともかくとして、コンパイル型言語だと条件ブレークってのは普通に無条件ブレーク命令をプログラム中に埋め込んでおいて、ブレークして止まったときにユーザに見せる前にまず条件式を評価、式が真にならなかったら、ユーザープロンプトに戻らず自動的に実行を再開。ということをデバッガがこっそり実行しているだけなのだ。
そんなぼんぼんCPU例外起こしといて速度なんか出るわけないでしょ。
そういうわけで、運が良くて超遅くてイライラ。運が悪いと速度が遅くなった影響でどこかでtimeoutが動き出して
デバッグがそもそも不可能になってしまう。
デバッグを軽視しているコーディングスタイルってどうなのさ?
とか思いませんか。
職業プログラマーだと、自分がバグ0でもどこかのアホが1人でもちょんぼしたらデバッグは付き合わされるわけで。
(とゆーか、会社でそれなりのポジションにつけば、後輩のデバッグに付き合わされる時間がどんどん延びていくよね)
3.はホント?
C言語は、returnがなかったときの動作は未定義だけど、これが原因のバグって聞かないよ。
なぜならコンパイラが検出して warning だしてくれるから。
逆に perl のような最終評価結果をreturn値とする言語のほうがうっかり動いてしまって
デバッガ動かさないと原因がわからなくてイヤな思いすることが多いけどなぁ・・
という事で、オイラはラムダ式以外では最終評価結果を返す仕様はあんまり好きじゃないなぁ・・・
あ、ラムダはいいんですよ。ラムダ式で if だの switch だのがわらわら出てくるのは違う意味で
論外なので、まぎらわしいケースにまず出会わないから。
どうでしょ?
1.return 変数という形を使うとき、この変数は、計算の中間結果を保持するためにだけ存在している。
2.return文をあっちこっちに散りばめた、複数の出口を持つ関数が作られやすい。
3.関数が実行した最後の文がreturn文でないとき、関数の戻り値が何であるべきか定義する必要がある。
これは実は1つも賛成できない。
まず1なんだけども、変数Resultを使うってことは関数最後尾にC言語風にいうところの
return Result;
って行を挿入することに等しい。
でも、これってResultってだけじゃ何も意味をもっていなくて
return tmp;
って書いたのと情報量は変わらない。
僕は名前重要!主義者なのだからして、tmp だの val1 だのって変数は大嫌い。一例を挙げよう
かの有名なprintfの型宣言はこう
int printf(const char *format, ...);
でもこの戻り値ってつかったことある人ってまずいないよね?
で、何かの拍子にこの戻り値を調べたくなったとする。で関数の実装を見るわけだ
ここで
va_start(arg, format);
result = vfprintf(stdout, format, arg);
va_end(arg);
return result;
}
va_start(arg, format);
num_output_bytes = vfprintf(stdout, format, arg);
va_end(arg);
return num_output_bytes;
}
はたして、どちらが情報量が多いだろうか?
ここからチラシの裏。
ところで、今のプログラミング言語ってたいてい関数宣言に引数名いれますわな。
型チェック的にはまるで必要ないけど、わかりやすさのために。
なんで、戻り値はだれも名前をつけようとせんのだろう?
2.についても、積極的に複数出口推進派として全否定したい。
いや、あれですよ
「必要以上に」むやみやたらに出口が多いプログラミングはあかんとは僕も思いますよ。
でもたくさんがアカンから出口は1つが一番だ!ってのは、かなり飛躍があるでしょ。
ぶっちゃけ、ただの思い込みなんじゃないの? と。
たとえば
function calcTotal(numarray, n) {
var total = 0;
if (numarray != null) {
for (var i = 0; i < min(n, numarray.length); i++) {
total += numarray[i];
}
}
return total; // 1
}
というプログラムで、おかしな引数はわたしてないつもりなのになぜか0が帰る時があるとする
(もちろん、つもりってのが気のせいで呼び方が間違っているんだが)
そうするとこのプログラムだと return tolal; の行に total==0 の条件ブレークを貼らないといけない。
gdb とかでデバッグしてて条件ブレーク入れたら実行がやたら遅くなった。という経験を持つ人は多いと思うがインタプリタ言語はともかくとして、コンパイル型言語だと条件ブレークってのは普通に無条件ブレーク命令をプログラム中に埋め込んでおいて、ブレークして止まったときにユーザに見せる前にまず条件式を評価、式が真にならなかったら、ユーザープロンプトに戻らず自動的に実行を再開。ということをデバッガがこっそり実行しているだけなのだ。
そんなぼんぼんCPU例外起こしといて速度なんか出るわけないでしょ。
そういうわけで、運が良くて超遅くてイライラ。運が悪いと速度が遅くなった影響でどこかでtimeoutが動き出して
デバッグがそもそも不可能になってしまう。
デバッグを軽視しているコーディングスタイルってどうなのさ?
とか思いませんか。
職業プログラマーだと、自分がバグ0でもどこかのアホが1人でもちょんぼしたらデバッグは付き合わされるわけで。
(とゆーか、会社でそれなりのポジションにつけば、後輩のデバッグに付き合わされる時間がどんどん延びていくよね)
3.はホント?
C言語は、returnがなかったときの動作は未定義だけど、これが原因のバグって聞かないよ。
なぜならコンパイラが検出して warning だしてくれるから。
逆に perl のような最終評価結果をreturn値とする言語のほうがうっかり動いてしまって
デバッガ動かさないと原因がわからなくてイヤな思いすることが多いけどなぁ・・
という事で、オイラはラムダ式以外では最終評価結果を返す仕様はあんまり好きじゃないなぁ・・・
あ、ラムダはいいんですよ。ラムダ式で if だの switch だのがわらわら出てくるのは違う意味で
論外なので、まぎらわしいケースにまず出会わないから。
どうでしょ?
コメント
コメント一覧 (13)
ICPC(プログラミングコンテスト)でやらかして気がつかずにだいぶ時間を食いました。Null pointer にならず、少し先で唐突に落ちてくれるので原因が分からず悲惨に。たしか gcc は標準ではエラー出さなかったような気がします。
-Wall で普通にでるかと。
今調べたけど、-Wreturn-type が -Wall に含まれているとマニュアルに書いてある
もし、普段warning出力オプションをOFFにして開発してるなら今すぐ神に懺悔して涙で枕を濡らし改宗したほうが。。
うそです、ごめんなさい
しかしICPCとはすごいですね
あわててコンパイルコマンドを打っていたので -Wall すらつけてなかったんです(^^ (同情の余地ないですが)
そのあとで世界大会に行った先輩にこれも含めて色々改宗させられましたorz
関数名から戻り値の内容がわかれば、名前Resultの情報量は考えなくても良いと思います。
2.の反論ですが、それは言語仕様の責任ではなく、デバッガの仕組みの問題ではありませんか。そもそもブレークが使えないという話にも聞こえます。
関数名で示すというのは同意できません。
printfは、「フォーマットして出力する」のが目的であり、
戻り値は主要な関心事ではありません。
print_with_format_and_get_length()
なんて関数名、ゾッとします。
構文として、関数の戻り値に名前を付けるという
kosaki案に賛成です。ついでに戻り値が複数もてると
なおgood。
スルーされるかと思ってました。
methaneさんへ
たしかに、
print_with_format_and_get_length()
だとうんざりしますね。
print_and_length()
ぐらいで勘弁してください。
C言語の関数宣言も、IDL のように書けたのなら、よりわかりやすかっただろうなと思います。
田辺さんが部下持ちなら適当に、いまあるプログラムのIDLを書かせてみてください。
ぼろぼろ間違えてくれると思いますよ。(どのIDLを使うかによって難易度は違うと思いますが・・)
じゃあ、お前ならどうするんだ。といわれて解がないから、こういう愚痴記事が出来ている。という面もあるのですが・・(n'ω'`)
COMとかMozillaのコーディング規約みたいに、戻り値は関数によらずHRESULT型、とか決めちゃうと、ある意味、問題は解決するけど、失うものが大きい。
↑ C言語的に不自然な書き方を強いられるし、無駄に行数が落ちるので見通しが悪化する。
もちろん、彼らはそれが分かった上で、くだらんチョンボがなくせるなら割に合うと思ってやっているので、責められる謂れはまったくないのですが。。。
<a href= http://www.angelfire.com/aoyobu/2.html >am</a>
http://www.angelfire.com/aoyobu/1.html
革命の日々
<a href= http://www.freewebs.com/oixoch/1.html >This</a>
http://www.freewebs.com/oixoch/2.html
革命の日々
<a href= http://www.angelfire.com/deojja/3.html >15916</a>
http://www.angelfire.com/deojja/1.html
革命の日々
<a href= http://www.freewebs.com/wluqpg/3.html >81717</a>
http://www.angelfire.com/arixgb/4.html
革命の日々
<a href= http://www.rs-architects.com/ >Richard Skinner & Associates</a>
http://raru.adelaide.edu.au/craig/wow.html
革命の日々