ある言語の引数評価戦略が、「値渡し」か「参照渡し」かを機械的に見分ける簡単な方法

  • 23
    Like
  • 10
    Comment

最近、自分の周辺で久しぶりに値渡しと参照渡しの区別についての議論をみかけました。参照渡しが意味するところについての勘違いというのは定期的に起こる傾向があるようで、それだけならともかく、解説書とかにも、「Javaは基本型は値渡しだが、参照型は参照渡しである」といった言説が平気で書かれていたりすることもあり、気が滅入ります。

自分としては、そんな誤解が広まることを良しとしないので、ここで誤解を解くための説明をしようかと思うのですが、自然言語でどんだけ丁寧に言ってもわかってもらえないことはあるので、機械的に判断できる、とても簡単な基準を紹介しようと思います。

まず、評価戦略を知りたい言語について、次のような関数を定義します。

void swap(int x, int y) {
  int tmp = x;
  x = y;
  y = tmp;
}

これは、引数を二つとって、その変数の内容を入れ替えることを「意図した」関数です。文法はとりあえずCっぽく書きましたが、その辺は各々の言語で適宜読み替えてください。Rubyなら、

def swap(x, y)
  tmp = x
  x = y
  y = tmp
end

といった具合です。ここで、引数の型の有無や、どの型であるかは問いません。floatでもdoubleでもlongでもいいです。ここまでが準備です。このswap関数を使って、

int x = 1;
int y = 2;
swap(x, y);
printf("x = %d, y = %d\n", x, y);

に相当するコードを実行します。

  • x = 1, y = 2が出力されるなら値渡し
  • x = 2, y = 1が出力されるなら参照渡し

これで終わりです。なお、ローカル変数があることは前提にしていますが、いま使われている言語でそれがない言語というのもまずなかろうと思うので、別に問題にはならないでしょう。

この判定方法は、通常の関数やサブルーチンを持つほとんどの言語において有効な方法だと思いますが、実行モデルが普通の言語とあまりにも違う場合には適用できないかもしれません。また、引数への再代入が不可な言語では、↑のようなプログラム自体を作ることが無理ですが、そのような言語はまず間違いなく値渡しです。