質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Q&A

解決済

8回答

2844閲覧

オブジェクトを共有できる形で渡す(呼ぶ)評価戦略の名称

raccy

総合スコア21735

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

6グッド

11クリップ

投稿2017/07/17 22:33

編集2019/05/02 13:12

正格評価を行うほとんどの命令型プログラミング言語において、関数等における引数の渡し方(呼び方)は三種類に分けられます(他にもあるのですが、言語が限られてマイナーですので除外します)。第一の渡し方は「値渡し(pass by value)」、第二の渡し方は「参照渡し(pass by reference)」ですが、最後の第三の渡し方についての名称が今回の質問です。

第三の渡し方は、Javaの参照型、C#の参照型、ECMAScript(JavaScript)のオブジェクト型、Python、Ruby等の現代的なオブジェクト指向でオブジェクトを扱う場合に多く用いられています。オブジェクトそのものコピーして渡すのではなく、オブジェクトを共有できる形で渡す方法です。しかし、この方法について、多くの記事やサイトで__参照渡し__の名称が使われ、多くの誤解を産んでいると思われます。この間違った名称の付け方は、この渡し方に対する名称が統一されず、うまく浸透していないのが原因では無いかと思います。

ここまで読んで、第三の渡し方の名称は「○○渡しの事だ」とぱっとわかる方がどれだけいるのでしょうか?こんなのわかって当たり前と思えないほど、無理解が広まっているのでは無いかと思っている次第です。

と言うことで、第三の渡し方の名称について、統一し、啓蒙しようと思うのです。しかし、何に統一すれば良いのかを迷っているため、皆様の意見を聞きたいのがこの質問です。下記に名称の候補あげますが、これ以外でもかまいません。どの名称が良いのか、なぜ、それが良いのかの説明も添えてお答えください。

  • 共有渡し(pass by sharing)
    共有とは何を示すのかもわかるようにお願いします。
  • オブジェクト渡し(pass by object)
    オブジェクトとは何を示すのかもわかるようにお願いします。
  • 共有オブジェクト渡し(pass by object-sharing)
    上二つ合わせた形で冗長ですが、なぜ冗長な表現にすべきも併せて説明ください。
  • 参照の値渡し
    対訳となる英語なし。Java等における実装を示す名称と思われますが、Rubyの即値のように実装上は値渡しになる場合は、どう解釈すべきかも併せて説明ください。
  • 参照渡し(pass by reference)
    C#のref付きの第二と参照型の第三の両方の渡し方もある言語では、どのように区別するのかを併せて説明ください。
  • アドレス渡し(pass by address)
    C#のポインタ(アドレス)に対する第一と参照型の第三の両方の渡し方もある言語では、どのように区別するのかを併せて説明ください。
  • ポインタ渡し(pass by pointer)
    C#のポインタ(アドレス)に対する第一と参照型の第三の両方の渡し方もある言語では、どのように区別するのかを併せて説明ください。
  • 値渡し(pass by value)
    値渡しの一種なのだから、そもそも区別しないという。Cなどといった通常の値渡しとの違いはどう考えるべきかを併せて説明ください。
  • 名称無し
    評価戦略についてそれぞれ名前をつけてカテゴライズすること自体が間違っているということ。なぜ、そういったカテゴライズすること自体が間違っているのかを説明ください。
  • コードで説明
    コードで第一で、とにかくコードで説明してしまうと言うこと。詳しくはthink49さんの回答を参照してください。
  • 共有呼び、すなわち参照の値呼び
    必ず二つの名称を続けて言うこと。また、「○○渡し」でなく「○○呼び」になります。詳しくはxebmeさんの回答を参照して下さい。

また「○○渡し」より「○○呼び」の方が良いという意見があれば、併せて記述いただければと思います。


問題解決と言うより、意見募集のような形になって申し訳ないですが、一人で悩んでも、納得できる決定ができませんので質問しました。ただ、こういう質問も許されるのが、某スタック・オーバーフローには無いteratailの緩くて良いところだと思っています。


【追記(2019-04-23)】

長い間(一年以上)、他に回答が来なかったのでベストアンサーを選んでしまっていますが、回答していただいても構いません。Qiita界隈では「参照の値渡し」というべきでは無いと考える方がおられるようですので、そのような方の回答をお待ちしております。


参考資料

GlassGrass, xebme, Lhankor_Mhy, umyu, LouiS0616, BluOxy👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakura_hana

2017/12/26 00:31

無知で申し訳無いのですが、「オブジェクトそのものコピーして渡すのではなく、オブジェクトを共有できる形で渡す方法」が「参照渡しではない」について説明されているサイト等を教えて頂けますか?(ばっちり参照渡しだと思っていました) これを機に勉強し、初心者なりに「この名称だとわかりやすいのでは」と提案させて頂ければと思います。
raccy

2017/12/26 09:21

参考資料を追加しました。実は、自分でこの動きの解説した記事をQiitaあたりに書こうと思っていたのですが、今まで自分の発言でも「参照の値渡し」と「共有渡し」で結構表記ゆれしていることがあったので、みんな意見を聞いてみたいということで投げたのがこの質問でした。もっと色々な意見を聞きたいので、この表現はわかりにくいとか、そういった意見でも良いので回答があると嬉しいです。解説の記事作成は…い、いつかやりたいなー
guest

回答8

0

こんにちは。

確かに用語に混乱が見られるので、自分なりに整理してみました。
結論としては、「渡し方には値渡しと参照渡しの2種類しかない」ということになりました。
質問にある第三の渡し方は単なる「値渡し」であり、渡す内容が「reference typeのポインタ"値"」であるという解釈です。
この解釈に沿うと、全ての動作が矛盾なく説明できると思います。
ほとんどの言語での標準が「値渡し」であり、C#でrefキーワードを用いた場合等の特殊な場合のみ、値への参照そのものを渡す「参照渡し」に該当することになります。
第三の渡し方のようなものが存在するように見えるのは、引数に値を引き渡す際に、その「値」として持っているものがデータそのものである場合(C#の値型)と、ヒープ上のオブジェクトを指すポインタ値(参照型)である場合の違いであり、それは渡し方とは全く関係ないのです。

投稿2017/07/20 05:22

tamoto

総合スコア4128

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2017/07/20 05:33

C++の場合、「コピーしての値渡し」がありますが、それとはどう区別しましょうか。
tamoto

2017/07/20 05:43

すみません。C++には全く詳しくないのですが、 「コピーして値渡し」とは、単なる値渡し(構造体の値そのものを引数に引き渡す)というわけではないのでしょうか?
maisumakun

2017/07/20 06:14

C++の場合、それがクラスに対しても存在するのです(やる人はあまりいないとは思うのですが)。
tamoto

2017/07/20 06:41

なるほど、それは知りませんでした。 ポインタを引き渡す場面でオブジェクトの中身までコピーされるということでしょうか……。そういうことであれば、「オブジェクトをクローンしてから新しいオブジェクトのポインタを値渡し」という、「言語特有の機能」に該当する気がします。 参考までに、コピーされるオブジェクトのフィールドがポインタ値を持っていたときはDeep copyになるのでしょうか?
tamoto

2017/07/20 06:46

あ、もしかして、C++は、C#の参照型等に存在する「参照型のオブジェクトはポインタ経由でしか取り扱えない」という制限が撤廃されて、「参照先のデータそのものを変数に入れることができる」という意味ですか? それだったら、単純に参照先のオブジェクトの「値」を値渡ししているだけだと思います。
raccy

2017/07/20 21:59

「値渡し」の一種にすぎないのだから「値渡し」以外の用語を使うべきでは無い、カテゴライズを分けて考えるべきでは無い、という立場でよろしいでしょうか? 一つ確認なのですが、ポインタを値渡しする場合、「ポインタ渡し」や「アドレス渡し」と言っている人達もいます。このような言い方もすべきでは無い、ということでよろしいでしょうか?
tamoto

2017/07/20 23:25 編集

そうですね、最終的には全てが「値渡し」になるわけですが、値を指し示す参照を値そのものであるかのように渡す言語機能を「参照渡し」と呼んでもいい、という考えです。 ポインタ渡しは値渡しと同列の存在ではなく、「値渡しの内、その値としてポインタを渡している特殊なケース」として「ポインタ渡し」と呼んでいるものと解釈できます。そう考えると、ポインタを渡しているんだから「ポインタ渡し」だ、と言うのは納得できます。例えば文字列を渡す場面でわざわざ「オブジェクトを渡す」と言い換えなくてもいいということですね。 まあ、その時「何のポインタを渡しているのか」を明確に表現していないことが多いのがこの質問の混乱の元凶な気がしますが。
raccy

2017/07/21 13:11

「言語機能を『参照渡し』と呼んでもいい」の一言でわからなくなってしまいました。tamotoさんはこの評価戦略を時には「値渡し」時には「参照渡し」と二つの名前で呼ぶし、どちらでもかまわないという考えなのでしょうか? 「ポインタ渡し」の話は、質問で聞いている渡し方と同じ「値渡し」なので、おなじくカテゴライズすべきでは無いという意見ではないのかというのを聞きたかったのですが、こちらは、カテゴライズしてもいいという話で良いのですよね。
tamoto

2017/07/21 14:20

えっと、すみません、ちゃんと整理してみました。 * 評価戦略としては、全ては「値渡し」である * 「値渡し」で渡す「値」には種類があって、それはデータだったりポインタ値だったりする * 「値渡し」であるが、値としてポインタを渡しているものを「ポインタ渡し」と呼んでもいい(冗長に言うと「ポインタの値渡し」のこと) * 「値渡し」の内、値としてポインタを渡すが、それを言語機能が隠蔽していて、まるでデータそのものを渡しているように見せかけているものを指して「参照渡し」と呼びたい(質問の「第二の渡し方」、C#のref等) 「渡し方」としての分類では全てが「値渡し」になってしまうので、「渡すものの種類」にフォーカスして呼び方を変えたいという意味です。値(データ)「を」渡す、ポインタ「を」渡す、参照「を」渡す、と呼び分けるのが混乱が少なく済むかなーと思っています。
raccy

2017/07/21 16:32

すいませんが、 * C#のrefが付いている渡し方は「値渡し」ではない(仕組みが全く異なる) * 質問で聞きたいのはC#でいうと参照型かつrefがない場合の渡し方の名称 という理解で私は質問したつもりなのですが、tamotoさんのコメントからすると、私の理解しているものとかなり隔離があるように思えます。私は別に何かを「参照渡し」と呼びたいとは主張しているのではありません。むしろ、そう呼ぶことが妥当なのか、それとも妥当では無いのか、を聞きたいから質問としてあげているのです。 とにかく、refの有り無しに関わらず、C#での参照型を引数にした場合は「参照渡し」と呼ぶがtamotoさんは思っているであっているのでしょうか?(私自身がそれが正解だとも間違いだとも判断しているわけではありません)
tamoto

2017/07/21 17:08

申し訳ありません、うまく伝えられていないようです…… C#のrefキーワードは、渡そうとしている変数そのものの「アドレス」を取得してそれを値渡ししているものと認識していますが、これは間違いでしょうか? 参照型かつrefがつかないオブジェクトの変数を渡す場合は、元々その変数に入っている「参照型オブジェクトへのアドレス」をそのまま値渡ししているものという認識です。 仮に、参照型にrefをつけた場合は、「参照型オブジェクトへのアドレス」が入った変数そのものの「アドレス」を取得してそれを値渡ししているものと表現できると思っています……
raccy

2017/07/21 22:08

どうやらrefについての考え方から私とtamotoさんに隔離があったみたいですね。やっと理解できました。 何が正解で何が間違いかを私はここでいうつもりはありません。時として、前提を多く持つことは、考えを狭めてしまい、多くの人の貴重な意見を聞き逃してしまう可能性があるからです。そのような考え方もできるということでとても参考になりました。ありがとうございます。
tamoto

2019/04/25 08:05

質問が動いていたようなので、今一度整理したものをここに記しておきます。 * 渡すものによらず、全ては「値渡し」である。 * 「参照型渡し」等はただの「値渡し」なので、呼び分ける必要はない。 * C# の ref のような、値への参照を引き渡す特別な言語機能が「参照渡し」である。
guest

0

Javaからみた評価戦略

Java の場合、引数はすべて値のコピーでしかも正格です。縦軸の型をみるとJavaはローレベルな言語なのがわかります(関数型インタフェースの組み合わせ爆発を招く原因になっています)。横軸の引数の渡し方は業界標準(古くからある実装技術)と思うものを挙げました。

variable typecall by valuecall by referencecall by name
primitive type--
reference type--

ラムダ式が登場して call by name の機能が注目されたので以下のようにも書けます。call by sharing も追加しました。わかるのは、概念が直交していない、機能に共通部分か、依存関係があることです。

variable typecall by valuecall by referencecall by sharingcall by name
primitive type◯*1---
reference type◯*1-◯*2◯*3

  • *1 「call by value」は省略できない。理解するには、スタックに引数を積む機能とヒープのオブジェクトを参照する機能を知る必要がある。この知識を要求するのはやはりローレベルだと思う。
  • *2 「call by sharing」理解するには、*1 があればよいが、スレッドごとのスタックからヒープのオブジェクトが共有参照されることを付け加えてもよい。
  • *3 「call by name」理解するには、遅延評価(引数として渡された式が、呼び先で式を使う都度、評価される)を、引数の関数型インタフェース(Supplyer)のapply()メソッドを呼ぶことで実現している。さらに式が参照する変数も「値渡し/コピー」として渡されることを知る。(関数は引数をとることができるが 、引数を取らない関数に限定)

理解のレベルの考察
必要なのは call by value だけ。プログラミングするうえで困るから。それ以外は、既存のJava機能の帰結か、追加機能として理解すればよい。

機能実現の抽象レベルの考察

  • call by value ローレベルな言語実装(オブジェクト指向以前から存在する標準的な技法)
  • call by sharing ヒープにオブジェクトが存在することから帰結する意味論ですね。オブジェクト指向の登場のときオブジェクト共有は新しい概念だったかもしれない。
  • call by name ローレベルな言語実装(ALGOL 60 から存在する標準的な技法)分散処理で関数型言語の優位性が注目されるなかで、オブジェクト指向の世界で関数型インタフェースを定義し、thunkと同様な機能を実現した。javascriptがこの機能を持っていることを改めて認識。

Java における call by sharing の位置付け。「オブジェクトの共有」は暗黙の了解事項であるが名前を付けて意識するほどのことではない。しかし他の言語については、上の関連表を書いて考察しない限り確かなことは言えない。CLUの場合はどんな表になるのかは興味がある。

wikipediaに記述するなら、評価戦略という観点から、歴史的順序、標準化の程度、依存関係、抽象化の度合いなどを、どう規定するかが著者に求められませんか?もちろん、逆引き用語集のように網羅的、索引的な記述をしてもよいが、作業量は増えます。その作業がかえって観点確立に役立つかもしれないけれど。

Javaの引数渡しの思考実験 (2019-05-02)

Javaで、1979年の議論を実現するには次のようにする。荒唐無稽ですが。

  • Call by Value オブジェクトをシリアライズして渡す。呼び元のオブジェクトには全く影響を及ぼさない(mutableのみ)ただし高オーバーヘッド。
  • call by reference 仮引数をfinal宣言して破壊的代入を許さなくする。あるいは、(できるなら)メソッド呼び出しをネストしたブロックにインライン展開、内部ブロックから実引数を直接参照する。できない場合が多い。

CLU (2019-05-02)

CLUにプリミティヴ型変数はなく参照型変数しかない。関数呼び出しは仮引数に実引数の参照をコピー代入することで行う。Javaにあわせて表を作ると以下のようになる。

variable typecall by valuecall by referencecall by sharingcall by name
reference type--

以下は言語の設計過程で行われた検討。

オブジェトをヒープ、スタックのどちらに置くか

Simula 67 がCLUの目指す設計に最も近かったが、Simula 67 はオブジェクトをスタック、ヒープの両方に置く方式を採用。CLU はすべてのオブジェクトをヒープに置く。理由は、状態遷移する mutable オブジェクトを採用したため可変長オブジェクトの更新にはヒープが有利だったのと、オブジェクトの生存期間をプロセジャのスコープより長くしたかったから。当然 GC を採用した(懸垂参照(ポインタ)の議論がちょっとある)。

ヒープ、スタック

ヒープとシングルスタックを採用する。並行処理(マルチスタック)を考えたが途中で放棄した。スレッド共有という考えはない。

オブジェト

built-in type 、 user-defined type 、 procedure / iterator の三種類。

  • built-in type Javaにおけるプリミティヴ型 (immutable)、配列などの集合型 (mutable/immutable)。
  • user-defined type ユーザーが定義するクラス(属性と振舞を持つ。カプセル化を実現)。clusterと呼ぶ。(function cluster)
  • procedure / iterator 関数(第一級のオブジェクト)

cluster (クラス) に継承という考えはない。パラメトリック・ポリモーフィズム(Javaのジェネリックスに相当。型変数を伴いコンパイル時にチェック)を採用。cluster は抽象データ型のアイデアを実装。抽象、つまり公開する振る舞い(Javaのインタフェースに相当)と実装、表現(representation)とを分離、定義する。

オブジェクト共有

スタック上の変数はオブジェクトの実体ではない。オブジェクトの実体はヒープに存在する。変数はオブジェトを参照するのみ。ここから、複数の変数が同じオブジェクトを参照(共有する)という事態が起こる。共有の本質は参照のコピー代入である。共有はどこで起こるのか。

  • スタック上の複数の変数がヒープ上のオブジェクトを共有する。
  • cluster の private 変数によって、ヒープ上の複数のオブジェクトが別のオブジェクトを共有する。再帰的な自己共有や、循環的な自己共有も可能。
  • 関数呼び出しによって、呼び元の実引数と呼び先の仮引数が、ヒープ上のオブジェクトを共有する。

代入においてオブジェトの実体コピーとは何かという問いがたてられ、深いコピー/浅いコピーの違いや、真の実体を代入するために、by-reference パラメータを使う代入(Alfard)などが検討された。

call by sharing 共有の何が新しいと思ったのか 1979

代入とは

  • オブジェクトの本体はコピーされない
  • 代入はオブジェクトの状態に影響を与えない
  • 代入後、オブジェクトは変数によって共有される

引数渡しとは

  • 仮引数は呼び先のルーチンのローカル変数とみなす
  • 実引数の式が評価され評価結果のオブジェクトが仮引数に代入される(ローカル変数の初期化)
  • この手法は、伝統的な引数渡しのなかに該当するものがほとんど見当たらない(LISPの引渡しに似ている)

伝統的な引数渡しとの相違点

  • call by value オブジェクトの本体を変更したら、呼び元にも変更が見える(mutableな場合)
  • call by reference 呼び元の変数のエイリアスではない。オブジェクトの本体を指している

したがって、call by sharing と呼ぶことにする。

Barbara Liskov et al., 'CLU Reference Manual', MIT Laboratory for Computer Science, Cambridge, MA, 1979

設計にかかわる議論は78項目にわたって記述されている。それらは未読。
Programming Methodology Group, CLU Design Notes, MIT Laboratory for Computer Science, Cambridge, MA, 1973-1979.

手元の記事には実装の詳細が一部だけ掲載されている。拾い読み程度。読まないかもしれない。
B. Liskov, A. Snyder, R. Atkinson et al., 'Abstraction Machanisms in CLU', CACM vol. 20 no. 8, 1977
オブジェトディスクリプタの解説では定数はスタックに置かれるようだ。その他はヒープに置く。

**by objectという用語 1992 **
1992年にリスコフは call-by-sharing という用語を使っていない。call-by-object は記述がなく、"by object"が登場するのは、変数共有を排除することで推論が容易になるというところだけ。

In fact, CLU procedures do not share variables at all. In addition to there being no free variables, there is no call-by-reference. Instead arguments are passed "by object"; the (pointer to the) object resulting from evaluating the actual argument expression is assigned to the formal. (Thus passing a parameter is just doing an assignment to the formal.) Similarly, a pointer to a result object is returned to the caller. We have found that ruling out shared variables seems to make it easier to reason about programs.

Barbara Liskov, 'A History of CLU', MIT Laboratory for Computer Science, Cambridge, MA, 1992

free variables は LISP の用語で(束縛されない)自由変数と訳せる。ここではグローバル変数のこと。
"by object" は、call-by-reference を指すとも、オブジェクトの本体を渡すともとれる。
object resulting from evaluating the actual argument expression は、正格処理として実引数の式を評価して結果オブジェクトを得ること。

1979年から1992年までの間に、call-by-sharing を使わなくなった理由は不明。

CLUを調べることで、他の回答者の議論になんとか追いつくことができました。概要だけみるとCLUは、Javaや、pythonの祖先といってよいほど似ている。pythonはCLUの嫡子でしょう。抽象データ型には触れなかったが、ほんとうの研究の成果はここにあると思います。その他、仕事で出会った古いALOGOLコードにCLU由来の考えがあったのを思い出した。

命名

英文 wikipedia で call by sharing は共通合意ではないといっているが、1979年の議論は解説する必要があるでしょう。1992年にはオブジェクトのポインターを代入すると言っているので、値渡しの範囲に分類できる。call by object は資料の中に見つけられなかったので採用しません。

英語に便利な言い方があります、等値の ', or'(すなわち)を使います。

call by sharing, or call by reference value
共有呼び、すなわち参照の値呼び

すごく常識的になりました。内容に誤りがあればご指摘ください。

投稿2019/04/28 10:27

編集2019/05/02 10:15
xebme

総合スコア1085

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

raccy

2019/04/28 13:15

> Java における call by sharing の位置付け。「オブジェクトの共有」は暗黙の了解事項であるが名前を付けて意識するほどのことではない。 結局の所、xebmeさんは「値渡し」派と言うことであってますでしょうか?
xebme

2019/04/28 14:40

ひかえめにJavaだけの立場を述べました。結局のところ「あっている」といえるほど知りません。「あっている」か「あってないか」、性急ですね。 私は、全体をまとめる観点が大切ではないかと思うので回答しました。Javaに関数インタフェースが追加されて見方が変ることのほうが面白い。他の言語のことも知りたいです。
xebme

2019/04/28 16:29

ではこうしましょう。言語の意味論から「共有呼び」を採用します。それを実装するのは「値呼び」です。これで、意味と実装の観点を導入しました。さらに依存という観点も導入しました。言語に機能追加されると意味が変わることがあります。歴史的観点。
hayataka2049

2019/04/28 19:09 編集

>「オブジェクトの共有」は暗黙の了解事項であるが名前を付けて意識するほどのことではない。 という論法は面白いと思いました。 同じ考え方で行くと、Python等(CLUも含まれると思うが、しっかり確認していないので話半分に。マニュアルはhttp://publications.csail.mit.edu/lcs/pubs/pdf/MIT-LCS-TR-225.pdf で見れる)ではそもそもprimitive typeが存在しないので、内部的に参照値が値渡しされることは暗黙の了解事項であるが「参照の『値渡し』」と名前を付けて意識するほどではない、共有渡しと呼称して共有される現象を捉えられれば十分……という感じになるのではないでしょうか(共有渡しを推す人間に言わせれば)。
xebme

2019/04/29 02:16

Javaの場合の意識づけは「スレッドセーフ」になります。ヒープ上のオブジェクトが複数スレッドから更新可能な場合です。他の言語はこのあたりどうとらえているのか興味があります。 CLUのマニュアルありがとうございます。ACM Digital Libraryでも見られるのですが今年はDLを契約していないので助かります。読むのにしばらく時間がかかります。
hayataka2049

2019/05/01 20:49

更新頭が下がります。 並列処理について思ったのですが、共有渡しだけの言語は必然的にスレッド並列化の妥協が伴うんですかね。python,rubyはGILですし、javascriptは非同期処理できるけどスレッドそのものはシングルスレッドだけです。スレッドセーフにする手段がないと考えると納得できるような。
raccy

2019/05/01 23:22

"call-by-object"について引用されている英文はまさしく今回質問の主題にしている評価戦略の説明に該当するとしか私には思えないのですが、xebmaさんは該当しないという考えてあってますか?
xebme

2019/05/02 10:21

hayataka2049さん、資料の提供ありがとうございました。勉強になりました。共有については、今の言語は並行処理を考慮する必要があることをいいたかっただけです。CLUは、LISPベース、ALGOLシンタックスシュガーの言語だそうです。Open Dylanを思い出しました。
xebme

2019/05/02 10:27

raccyさん、資料のなかにcall by objectは見つけられませんでした。'by object'のみ。それが該当の引用文です。wikipediaにはcall by objectの記述があるのですが、確かめられないのではずしました。理由はわかりませんが、リスコフの意見は、時間と共に変化したのではないかと思います。
raccy

2019/05/02 10:34

結論がなかなかはっきりしなかったので、混乱していたのですが、xebmeさんは「共有呼び、すなわち参照の値呼び」と必ずセットで言うという結論で良いですか?たとえば、「Javaの参照型は共有呼び、すなわち参照の値呼びの評価戦略を用いて関数に渡される。共有呼び、すなわち参照の値呼びであるため、ArrayList等のmutableなオブジェクトを渡している場合、関数内でのオブジェクトへの変更が、呼び出し元のオブジェクトにも影響を及ぼすことになる。」といった文章になるという事であってますか?
xebme

2019/05/02 10:44

はい。まさにその通りです。
raccy

2019/05/02 13:11

二つの呼び名を常に必ずセットで述べるという発想はなかったので、xebmeさんの回答を質問の一覧に追加させて頂きました。
guest

0

ベストアンサー

参照の値渡し

Rubyの場合も、即値となってしまうのはあくまで実装の最適化に過ぎず、概念上は「参照の値渡し」と解釈して問題ないでしょう。イミュータブルなものを渡すときは「純粋な値渡し」でも「参照の値渡し」でも渡された側でできることは何も変わりません。

…というより、.NET系の「値型・参照型」×「値渡し・参照渡し」のように何通りも渡し方がある言語ならともかく、たとえばRubyは引数の渡し方が1通りしかないので、言語内の事情だけ考えれば名前をつける必要もない、ということになります。

投稿2017/07/17 22:48

maisumakun

総合スコア145208

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

raccy

2017/07/19 11:17

言語としての概念上の話だから、実装に引っ張られる必要は無いんじゃ無いかというのは、その通りですね。あとは、「参照の値渡し」という名称の方がこんな所がいいところみたいな物が欲しいところです。 Rubyのように一つの方法がない場合でも、他言語を含めた形で説明するとなるときちんと名前が欲しいところです。他のプログラミング言語を全くしないってすごく特別な環境だと思いますし、他言語との比較としても、共通した用語というのは必須じゃないのかなーと思ったりします。
raccy

2019/02/22 15:29

いい加減、自分の中の表記揺れをなんとかしたかったので、「参照の値渡し」に決定しました。ついでに、Wikipediaに英語版の翻訳として「参照の値渡し」で追記しました。最初に言ったもんが勝ちという奴です。 ということでteratailではこの名前で広めたいと思います。
guest

0

終わった質問と思っていましたが、再開されたようなのでJavaScriptにおいての私見を。

用語の選別

率直に申し上げれば、掲示された、どの用語を選んでも大差はないと思います。
仮に「参照の値渡し」という用語で説明したとして、別の場所では別の人が「共有渡し」と呼ぶこともありえます。
仕様で規定されていない以上、どの用語も独自用語ですから、全ての人が使う用語を統一する事は出来ません。

最終的なゴールを「読んだ人がその概念を理解し、有識者の説明、プログラミングの書籍、技術情報サイト...etc、でその概念を正しく読みとる事」に設定するとして、一つの用語に拘るのはリスクが高いと考えます。

[解決策1] 外部サイトで全てを説明する

結局のところ、「全て」を説明するのが最もリスクが低いと考えます。

  • 該当概念をコード付で説明
  • 2019/04/24現在はECMAScript仕様出用語化されていないこと
  • 著者によって、「参照の値渡し」「共有渡し」...etc(可能性のある用語を全て書いておく)、と呼ばれることがあること(※1)

毎回、全てを説明するのは大変ですし、仕様で用語規定されたら、不正確な用語になってしまうリスクは常にありますので、自分に編集権限のある外部サイトにその説明を書いておき、毎回、そちらに誘導するのが現実的だと思います。
(私はその目的では、GitHubを使いますが、自分の好きなサイトで問題ないと思います)

※1 説明は事実的であるのが望ましいと考えます。
あるべき論を語ると、初めに読んだ説明に引きずられて思い込みが発生する可能性があります。
「あなたは参照の値渡しと書かれましたが、某所では共有渡しと表現すべきであると書かれていました。どう思いますか。」のようなやり取りが発生するのは不毛です。
理想的にはどの用語が来ても読めるであり、表現方法は本人の意志に委ねる事になると思います。
(必要であれば、「事実」を書いた上で、それが個人的意見である事を前置きした上で持論を語ります。)

[解決策2] コードで説明する

真に確実性を追求するのであれば、独自用語を使わずにコードで説明が最良と思います。
例えば、次のように説明します。


JavaScript

1function sample (object) { 2 object.a = 2; 3 object = []; 4} 5 6var object = {a: 1}; 7 8console.log(JSON.stringify(object)); // {"a":1} 9sample(object); 10console.log(JSON.stringify(object)); // {"a":2}

JavaScriptではオブジェクトのプロパティ書き換えが共有される為、2回目のコンソール出力では、関数sampleでプロパティ書き換えされた後の値が出力されます。
しかし、変数は共有されない為、2回目のコンソール出力で [] が出力される事はありません。
(2019/04/24現在のECMAScript仕様においては、いわゆる参照渡しは存在していません)


コードに付随して日本語の範囲でロジックを説明してやれば祖語は発生しません。
最終行では言葉(参照渡し)を使ってしまっていますが、これは他所サイトの説明を読んで誤解されない為の配慮であり、自分の説明を相手に伝える目的のみであれば不要な一文です。

ちなみに、既存の概念であってもこの方法は有効だと私は考えています。
質問者の中には既存の概念を間違えて覚えている方がおり、そういう方に言葉で説明すると、間違った概念の上で解釈してしまいます。
ですので、私はよく言葉ではなく、コードで説明して下さいと主張しています。

※余談ですが、ロジックを頭の中で組み立てる時には、日本語を使わずにほぼコードだけで考えている自分がいます。
コード<->日本語の変換時間がロスになっていて、コードだけで考える方が思考が加速して楽しい。
私にとっては「コード」が主役で「言葉」は無くても困らないもの。
だから、新しい内容を覚える際には「専門用語」よりも「原理」を先に覚えます。
専門用語は原理を他人に説明するのに少しだけ時間を節約できる効果がありますが、自分が覚える分にはなくても困りません。
他人に説明するには、世界共通語の「コード」で説明すればいいので、「専門用語」の優先順位は低くなっています。

言語の違い

今回、raccy さんは複数の言語について、統合的に質問されていますが、用語や概念については、言語毎に微妙な差異があります。
他言語経験者が未経験言語の学習時に「習得済言語の概念」にとらわれて戸惑うケースはよくあることですので、言語別に説明するのが無難だと思います。

特に今回は定義が不確定なものを説明しようとしているので、言語の違いによる齟齬は出来るだけ抑えるのがベターと思います。

更新履歴

  • 2019/04/24 21:35 「[解決策2] コードで説明する」を追記しました

Re: raccy さん

投稿2019/04/24 02:40

編集2019/04/24 12:35
think49

総合スコア18170

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

raccy

2019/04/24 10:13

終わったと言うより、1年以上も回答が追加でつかなかったので、ベストアンサー付けずに放置するなと言われる前に当時取りあえず納得できそうなmaisumakunさんの回答にベストアンサーにしたんです。ちょこちょこ、この質問は誘導するように書いてたはず何ですが、足りなかったみたいです。 うーん、結局think49さんからみると、統一とかそういうことは無理って感じなのでしょうか。なんか、振り出しに戻った感じです。 もともと、この質問はQiitaで解説の記事を書こうかなと思い、参考にWikipediaをみたら日本語版に"call by sharing"の項目が無かったので、英語版でも翻訳しておこうかなと思っていたときに、「なんて呼べば良いのかわからない」というところから始まっています。今の日本語版Wikipediaに書いてある「参照の値渡し」はベストアンサーを選んだ時点でのひとまずの成果です。 うーん、結局、本当に正確に書くなら、Wikipediaの評価戦略も、言語毎に書くとかが必要になってくるのでしょうか。私自身は、PythonやRubyやJavaの参照型等は同じだと思っていますし、定義も曖昧とは思っていないのですが、かといって、うまく表現できないと言うことは、曖昧なのでしょう。連休中にWikipediaの評価戦略の項目を整理しようかなと思っていたのですが、私では能力が足りなさそうです。
think49

2019/04/24 12:42 編集

親記事に追記しました。 基本的にプログラミングにおいての私はデジタル人間なので、確実(1)と不確実(0)の二種類で物事を判断しています。 独自用語は不確実(0)なので、揺らぎを敬遠するのであれば「独自用語に頼らない」という結論になります。 ただ、この問題に関しては追記した「コードで説明する」が一番確実かと思いました。
raccy

2019/04/24 14:13

えと、私の解釈があっていればですが、think49さんの考えとしては「そもそも何かの名前を付けて説明しない」「コードで実例を挙げながら説明する」と言うことでしょうか?もし、think49さんが本を書くなり、何かの記事で解説する場合、見出しとしてはどうなるでしょうか「○○渡しの解説」ではなくて「JavaScriptのオブジェクトを引数にしたときの評価戦略」みたいな見出しで、そこに「○○渡し」みたいな表現は一切入れないと言うことであってますか?言ってしまえば、質問の例で言うと「名称無し」にあたると思うのですが、むしろ、「コードで説明」とかでしょうか? こう、一言で表現しても貰うと助かります。質問の羅列した例のなかにthink49さんの考えも追加したいので。
raccy

2019/04/24 14:13

あ、解決策1は全部羅列と言うことでしょうか?
think49

2019/04/24 23:14

「コードで説明」です。日本語の説明は仕様定義された用語のみを使います。 対策1は独自用語を入れましたが、必要性は低い考えです。
think49

2019/04/24 23:21

対策1は誤解を最大限少なくする為に全ての独自用語を入れます。対策2は入れません。 この手の用語は概念が一人歩きする傾向があり、ノイズでしかないと思うこともあります(皆さんのあるべき論を見て、そう感じました)。 それは本質的ではないので、「原理」が確実に伝わる手段に切り替えるのが現実解と思います。
raccy

2019/04/26 17:04

「コードで説明」を追加しました。 全てを記載するという「全て網羅」の方は私では網羅しきる自信が無い(そもそも、最初の質問では網羅し切れておらず、次々追加していきましたし、まだ追加があるかも知れませんし)ということと、「全てを網羅」の中に「全てを網羅」も含まれるような気がしてきて、言ってしまえば、自己言及みたいになる気がしたからです。「全てを網羅」の一つに「全てを網羅」があるのだから、"「○○、△△、□□、「○○、△△、□□、○○、△△、□□、... "と言うように永遠に表現が終わりません。自己自身を含むのが悪いと思うので「自己自身を含まないものを全て網羅」としてしまうと、「自己自身を含まないものを全て網羅」が自己自身を含まないのであれば、「自己自身を含まないものを全て網羅」は「自己自身を含まないものを全て網羅」に含まれることになって矛盾し、「自己自身を含まないものを全て網羅」が自己自身を含むのであれば、「自己自身を含まないものを全て網羅」は「自己自身を含まないものを全て網羅」の中の一つであるからには自己自身を含むはずなので、同じく矛盾してしまって、よくわからなくなったからです。
guest

0

個人的に思うベターな順で並べます。

最良: 共有渡し
ギリ許せる: 参照渡し

できれば使いたくない、ケースバイケース:共有オブジェクト渡し, アドレス渡し, ポインタ渡し, 参照の値渡し

論外:オブジェクト渡し, 値渡し, 名前無し


共有渡しについて

いろいろな面で、こう呼ぶのが一番自然です。半ば消去法的にですが、一番いいのはこれと考えます。

唯一の難点は、普及していないことです。

共有とは何を示すのかもわかるようにお願いします。

呼び出し元と呼び出し先で同じオブジェクトが共有されます(オブジェクトの実態はメモリ領域への参照とオブジェクトを取り扱うための然るべきプロトコルなど、後半部分はパラダイムというか実装によって若干変わる)。

関連するものとして、オブジェクト渡しは「共有される」という現象が名前に入らず、それこそ「オブジェクトの値渡し(そういうものがあれば)」と区別する手段がないため論外。共有オブジェクト渡しは動作の説明としてはいいと思いますが、冗長なのでできれば使いたくない枠。

参照渡しについて

これで説明している書籍等もあると思いますし(出典を示せないのでとりあえずこういう書き方にしておきます)、一定の市民権を得ている以上、無視するべきではないと思います。

このトピックで問題にしている「参照渡し」とC++やC#, PHP等で使われる「参照渡し」は同綴異義語とみなし、一般的な場面では文脈から判断することにします。仕様書、ドキュメント、マニュアル、初心者向け解説など取り違えが許されない場合、適切な注意書き等を付記することにします。

C#のref付きの第二と参照型の第三の両方の渡し方もある言語では、どのように区別するのかを併せて説明ください。

言語ごとに仕様等で呼び方を規定していると思うので、個別の言語についての記述ではそれに従います。

一般的な文脈で区別が必要な場合、「参照渡し(Cでいうポインタ渡し)」「参照渡し(C#でいうref)」のように区別するか、「参照渡し(俗に言う共有渡し・参照の値渡し)」「参照渡し(俗に言う共有渡し・参照の値渡しではない)」とするか、いずにせよ区別の方法はいろいろあると思います。

アドレス渡し, ポインタ渡しについて

アドレス、ポインタが言語仕様上で規定されている言語でのみ使いたいと思います。

参照の値渡しについて

たくさん問題があり、「参照渡し」とどっこいどっこい程度だと思っています。

  • そもそも「参照の値」が言語仕様上で定義されない言語では使うべきではない。アドレス渡し、ポインタ渡しと同じ。
  • 「参照」と「値渡し」への理解を前提知識として要求する。pythonをはじめてのプログラミング言語として学び始めた小学生にどう説明するか? 「共有渡し」なら「共有されるんだよ」と説明できます(「オブジェクトを名前に束縛する」は先に、「関数」「コールスタック」は同時に理解させておく必要があります・・・)。
  • 「参照の値を渡す」というのは動作や実装の説明であり、「値渡し」や「参照渡し」と同レイヤの説明ではない(「値渡し」と言う代わりに「値をコールスタックにpushして・・・」と説明するのと同じです)。そもそも論として、参照の値を渡さない実装で同じものを実現していたときどうするつもりなのか。
  • 市民権を得ていない。おそらく共有渡しと同程度に通じない。
  • しかも長くてダサい。
値渡しについて

さすがに無謀。

名前無しについて

特に支持する理由がありません。

投稿2019/04/23 19:02

編集2019/04/24 09:47
hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

raccy

2019/04/24 10:15 編集

「参照の値渡し」のまずい点は凄く理解できます。Javaみたいに仕様書で「値が入ってます!」と明記している言語では良いですが、PythonやRubyだとその表現が???になるんですよね。言語をよく知れば知るほど。 「参照渡し」は実際にそのような注記があるのは見たことが無いです。そういう注記が目立つところにない場合、書き手が言語特有のものであると思っていても、読み手がそう捉えることは少ないんじゃ無いかなと思います。 結局、「共有渡し」が落とし所なのでしょうかね。他の分析もしているので、もっと早く回答してくれたら、この回答をベストアンサーにしていたと思います。取りあえず、裏ベストアンサーにオレオレ認定しておきます!
guest

0

結論から言えば、Java では引数の渡し方はただ一通りしかないので、それを「値渡し」のような用語を使って説明するのはむしろ混乱の元だと思います。

Java で一見値渡しのように見えるもの、参照渡しのように見えるものは、データ型の性質によるものであって、メソッドの引数の属性ではありません。プリミティブ型であれば、代入でも、メソッドの戻り値でも、引数でも値のコピーが渡されますし、参照型なら、代入でも、戻り値でも、引数でもオブジェクトへの参照が渡されます。引数の時だけ、特別なことが起きているわけではありません。

それを「引数のXX渡し」のような言葉で説明してしまうと、C# のように本当に値渡しと参照渡しがある言語に移行した時、用語の齟齬が起きて混乱するのではないでしょうか。

投稿2017/07/19 14:55

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

raccy

2017/07/19 15:00

つまり、すべて「値渡し」と呼ぶべきと言うことですか? それとも、名称を付けること自体が絶対にしてはいけないことであり、他の言語と比較したりすること絶対にやってはいけないことと言うことでしょうか?
退会済みユーザー

退会済みユーザー

2017/07/19 15:32

他の言語と比べるのであれば、他の言語と同じ用語の使い方をすべき、という意味です。Java の引数の渡し方は、C# でいう「値渡し」そのものですよね。 例えば、すでに Pascal を学んだ人が Java の引数を学ぶときにに「これは Pascal の参照渡しみたいに動作するのか」と理解のとっかかりするのは、ありだと思います。しかし、Java を一から勉強するのであれば、参照型の引数の副作用については、データ型をしっかり理解することで、理解すべきだと思います。
raccy

2017/07/19 21:48

C#の参照型については「値渡し」というべきと言うことで良いのでしょうか?評価戦略の話をするにあたって、そもそも「値渡し」と区別すること自体が間違っているという理解でよろしいでしょうか?
raccy

2017/07/20 21:55

質問に「値渡し」と「名称無し」を追加しました。結局、hideki1234さんは「値渡し」と「名称無し」のどちらの立場なのでしょうか? 私は、hideki1234さんの考え方自体が間違っているとは思っていませんし、納得できる部分もあります。しかし、今回の回答の短い内容では、Javaの場合はこう、のような特定の言語の場合しか考えてないように見えることと、名称を付けるなといいながら、C#の「値渡し」だと言ってみたり、どっちなのかと思う次第です。
guest

0

  • 理想的には「オブジェクトなどを参照する値」を「参照」と呼ぶことが誤解を招く原因で, それとセットで「◯◯渡し」と改称すべき.
  • 但し現実的にはそれは実現が難しいと思われるので「参照の値渡し」が落とし所. また本来の参照渡しのほうも混同され易い状況のために別の名前が欲しい

かなと思います.

投稿2019/04/23 15:56

kagilinn

総合スコア354

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kagilinn

2019/04/23 16:03

前者について「共有渡し」でなく「◯◯渡し」としたのは, オブジェクトなどを参照するための値について「共有」と呼んでしまうとそれもまたちょっと変な感じがするためです. 候補としてありそうなのは「リファレンス渡し」辺りでしょうか…苦しい語ですが.
kagilinn

2019/04/23 16:19 編集

また前者は「参照という語は改称すべし」という主張なのに対して, 後者の現実解については「参照渡しは改称すべし」ではありません. あくまで「参照渡し」を維持した上で, その本来の意味への別名が欲しいという感じです.
raccy

2019/04/24 09:52

Javaだと仕様書で"reference value"と書いてあるのでそのまま「参照値」でもいいんじゃ無いのかと思ったりします。ただ、この言葉は凄く実装よりで、ちょっと危ない気がしますが。あと、「リファレンス渡し」だと「リファレンス」->「reference」->「参照」って同じじゃ無いか!ってツッコミがありそうです。とりあえず、用語はカタカナ語にしておくとできるビジネスマンっぽいって感じだけで、意識高い系みたいな中身スカスカのように見えちゃいます。 実現が難しいからやめる…よりも、困難に立ち向かうために、理想を考えて、○○にうまる部分のアイデアがもっと欲しかったなと思います。あ、私は思いつかないので、すいません。
kagilinn

2019/04/24 10:55 編集

理想的な単語, 考えてはいたのですがはじめに浮かんだのは「ポインタ」でした. 何らかの実体を指し示すもの, という語ですので, 意味的にはしっくり来る気がします. …ただし, 恐らくお気付きのようにこの用語には最大の問題点があります. メモリの番地を扱う, という意味が既に与えられてしまっていて, 結局は別の混乱を呼ぶこと間違いなしです. (実装的には参照もアドレスなのだろうとは思いますが...) その日本語版としてありそうなのは「指標」でしょうか. というか中国語でポインタをそう言うっぽいですが.
guest

0

英語の文献をたどる際にわかりやすいよう、**英語に合わせて「共有渡し」**がいいと思います。

※評価戦略読んでがっつりかえました、そしてまだ考えが全然まとまってません。コメントくれた方ごめんなさい。

投稿2019/04/23 12:44

編集2019/04/23 22:56
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

raccy

2019/04/23 15:22

結局の所、質問に対する回答としては、ppnさんの結論は「参照操作」と言うことでよろしいのでしょうか?
退会済みユーザー

退会済みユーザー

2019/04/23 17:35 編集

すみません、考えを整理しなおして書き直しておきました。
退会済みユーザー

退会済みユーザー

2019/04/23 17:35 編集

--削除--
hayataka2049

2019/04/23 19:13

蛇足部分についてですが、そもそも変数という言葉がなにを表すと考えているのでしょうか? あたりまえですが、Cの変数とPythonの変数とLISPの変数とPrologの変数はまったくの別物です。変数がまったく存在しないがサブルーチンは使えて、値とアドレスのどちらでも渡せるという言語も考えられなくはないでしょう(アセンブリ言語みたいな)。 変数とつければいい、ということはないと思うのですが。
退会済みユーザー

退会済みユーザー

2019/04/23 19:27 編集

なるほど、それほど違いがあるのですか。改めて言われると、値を入れておくものという認識でしかありませんでした。では「参照」は何を指すのでしょうか?変数に相当するものを呼び出し先に共有するという認識は誤りでしょうか。もしかしたら私はそのあたりを勘違いしているのかもしれません。
hayataka2049

2019/04/23 19:40 編集

ppnさんの言っている「変数」を「メモリ領域」に置き換えると割としっくり読めます。おそらく、「メモリ領域」のつもりで「変数」と言っているのでは。 オブジェクトも基本的には、言語機能で便利なアクセス手段が提供されているメモリ領域です。
退会済みユーザー

退会済みユーザー

2019/04/23 20:21 編集

評価戦略というものを知らなかったので読んでみましたが(回答前に読むべきでした)、「参照渡し」でいう「参照」は「変数への暗黙の参照」だそうです。評価戦略の話であれば表現の短さに納得できましたが、むしろ「参照化渡し」としてほしくなりました…。
退会済みユーザー

退会済みユーザー

2019/04/23 20:35 編集

「変数」=「メモリ領域」とのイメージもありますが、もっと抽象的に「(実装は何か知らないけど)何かしらの値の入れ物」というイメージでいます。オブジェクトについても、どこかになにかしらの形で実体があって、参照型の変数にその実体への参照が入っている(オブジェクトを変数に割り当てている)という認識でいます。それぞれの厳密な定義を調べたわけではないのであれですが。
hayataka2049

2019/04/23 22:16 編集

変数=(値を格納している)メモリ領域というのは、かなり狭い捉え方のはずです。 たとえばPythonの変数は「ただの名前」で、evalすると別途用意されている変数テーブルをその名前で検索して名前に束縛されているオブジェクトを返す・・・という仕組みです。LISPなどもっと徹底していて、「変数名」もシンボル型というオブジェクトとして扱っています。 変数=値の入れ物はそこまで強い一般性はないかと。
退会済みユーザー

退会済みユーザー

2019/04/23 22:58 編集

なるほどそう言われれば、LISPは環境がどうこうみたいな話があった気がしますし、Pythonはラベルがどうこうという話があった気がします(うろ覚え)。なるほどわかった気がします、変数のイメージが偏っているせいで「変数渡し」としちゃってませんか?ということでしょうか。確かに、そういわれるとそう思えてきました。ただ、「変数参照渡し」という表現でいけば特に問題はないように思えます(だめでしょうか…。
hayataka2049

2019/04/23 23:22

呼び出し元で特定の変数に結びつかないケースも当然あるのでは? pythonでいう、 sum([0,1,2]) みたいな例で、[0,1,2]はlistのリテラルであり、実行時にはメモリ上にリストオブジェクトが生成されますが、これは呼び出し元のいかなる変数にも束縛されません。
退会済みユーザー

退会済みユーザー

2019/04/24 05:50

それは「参照渡し」ではなく、「参照の値渡し、共有渡し」ではないでしょうか。特定の変数に結び付くケースを「参照渡し」と呼ぶと思います。
hayataka2049

2019/04/24 08:35 編集

確かにそうですね。原理的に変数名を使わない場合は「参照渡し」の話題とは無縁です。 「参照渡し」は「変数の参照渡し」とでもするべき、という意見には基本的に賛同します。あるいはエイリアス渡しとかでもいいでしょう。 # 追記: # ただしすでに決まっていて受け入れられているものは安易にいじるべきではない・・・というのが前提です。 # 特に特定の言語で規定されていてみんながそう呼んでいるというものであれば、仮に多少違和感のある命名であったとしても、変更するメリットとデメリットを天秤にかけて変更しないという選択は合理的な可能性が高いです。
退会済みユーザー

退会済みユーザー

2019/04/24 06:30 編集

はい。sum(...)はもしかしたらpythonでいうところの「参照渡し」なのかもしれませんが、抽象的な概念(「評価戦略(英語wiki)」がそれにあたる?)における「参照渡し」の仕様と異なるのであれば、別物とすべきと思われます。もし、「評価戦略」が言語間で仕様の異なる同じ呼び名のものを同じ呼称にまとめましたってだけなら、「評価戦略」には言葉を区別する以上の意味はなく、抽象的な概念とは言えなくなくなってしまうと思います(といいつつ実際はその節があり、ぇぇのんかそれでという気がしてますが。たぶん、抽象的な概念として定義しなおしたわけじゃないんだろうなというきがします。抽象的な概念という言い方が適切かは微妙ですが)。
hayataka2049

2019/04/24 06:33

すみません、pythonの評価戦略は共有渡しだけです。 sum([0,1,2])は参照渡しの文脈とは関係ない話題でした。スルーしてください。
Zuishin

2019/04/24 07:12 編集

「変数の」と限定する意味はないと思います。 参照渡しは値のコピーにかかるパフォーマンスの劣化がほとんど無いので、無名の値を参照渡しする戦略は十分考えられます。エイリアスは説明であって本質ではありません。
Zuishin

2019/04/24 07:10

hayataka2049 さんもおっしゃっていますが、変数=メモリ領域ではありません。メモリ領域は参照を作ることができますが、変数は必ずしもそうではありません。 本質的に違うものをわざわざ名前に入れる必要はないと思います。 例えば C# には Span<T> という構造体があり、この構造体は名前のついていない、つまり変数でないメモリ領域を参照渡しします。
Zuishin

2019/04/24 07:29 編集

「変数の参照渡し」より「値の参照渡し」の方が正確な表現になりますが、わざわざそのような冗長な表現を使う必要はないはずです。 もし使うとなれば値を参照渡しする「値の参照渡し」は「値の値の参照渡し」になってしまいます。
退会済みユーザー

退会済みユーザー

2019/04/24 07:18

無名の場合でも変数に相当するものを用意しなければ参照を渡すことができないと思いますがどうでしょう。その場合、無名の変数が内部的に用意されることになりませんか?
Zuishin

2019/04/24 07:20 編集

「配列の一部」は変数ではありません。
退会済みユーザー

退会済みユーザー

2019/04/24 07:21 編集

なるほど値から遡って参照を取得するという考え方を持っていませんでした。しかし、値からさかのぼれるのであればそれは値ではなく、値とは別の何かなのでは…?
Zuishin

2019/04/24 07:21

評価できるものは値です。
hayataka2049

2019/04/24 07:37 編集

>Zuishinさん >参照渡しは値のコピーにかかるパフォーマンスの劣化がほとんど無い まず、さすがにこの質問で「参照渡し」と書いている以上、俗に言う「真の参照渡し」の話と理解しました。 参照渡しの実装はまったく知らないので「どういうことだろう」と思い調べてみたら、こんなのが出ました。 https://qiita.com/tajima_taso/items/a62747739deee88078da http://tanakahisateru.hatenablog.jp/entry/2013/12/12/012728 ZUishinさんの意図している「パフォーマンスの劣化がほとんど無い」は内部的には(基本的な仕組みとしては)ポインタ渡しと等価なので速い、という理解で合っていますか?(上) もちろん、PHPみたいな実装だと(使い方をミスると)容易に台無しになる、と。(下) # 逆にPHPは素朴な「共有渡し」がないのか・・・オブジェクトを変更した瞬間にコピーが作られるので、表面的には値渡しに限りなく近いんですね。引数をいじりまくって壊しても呼び出し元に影響しないと(逆にいじることを意図して使うなら参照渡し以外の手段がない・・・)
Zuishin

2019/04/24 07:24

参照渡しはポインタを使って実装されていることが多いのではないかと思います。C# の参照渡しはポインタをユーザーが使わなくてもいいように作られたものです。しかしそれは実装の話に過ぎません。
Zuishin

2019/04/24 07:27

PHP の参照渡しも、もしポインタではないのならパフォーマンスは落ちるかも知れませんが、ならばポインタを使えばいいだけなのではないかと思います。
退会済みユーザー

退会済みユーザー

2019/04/24 07:31

wiki(英語版)を引用するのは良くないかもしれませんが、そこには次のようにあります: `参照による呼び出し(参照渡しとも呼ばれます)は、関数がその値のコピーではなく、引数として使用されている変数への暗黙の参照を受け取る評価方法です` 「変数への参照に評価して渡す」ということをしない「参照渡し」はそれ独自の「参照渡し」であり、一緒にすべきでないのでは?
Zuishin

2019/04/24 07:35

C# は JIS に登録されています。現行バージョンが登録されているかどうかはわかりませんが、そこでは「参照渡し」と名付けられています。 変数云々は説明であり本質ではありません。変数でないものが現れたら書き換えるべきものであり、いまだ書き換えられていないのはそこまで手が回っていないということに過ぎないでしょう。
退会済みユーザー

退会済みユーザー

2019/04/24 07:44 編集

いや、変数の中身を変える目的に焦点を当てず、渡されるのが値に対する参照であること自体に焦点を当てるのであれば「参照渡し」でいいのか…。ただそれだと、「参照の値渡し」を「参照渡し」と呼べてしまいそうですし、複数の変数が同じ値を指していた場合は指す値全てが変わってカオスになる気がする。評価の目的ごとに呼び分けないと実装によって機能が大きく変わってしまう…。
退会済みユーザー

退会済みユーザー

2019/04/24 07:39

それはC#の「参照渡し」にすぎないのでは。
Zuishin

2019/04/24 07:42

C++ でもそうです。そしてこれは評価戦略に書かれた参照渡しに合致します。
Zuishin

2019/04/24 07:44

むしろ C++ と C# の実装を見て名付けられたものだと思っていますが、そうでなければそれ以前の論文があるはずです。どれですか?
Zuishin

2019/04/24 07:48

大事なことですが、この名前は公的機関に登録され、すでに社会で広く使われているもので、ppn さんに命名権はありません。
Zuishin

2019/04/24 07:51

私としては、渡し方を三種類とする Wikipedia の方に違和感を覚えます。参照の値渡しに書かれている特徴は参照型の特徴であり、渡し方には無関係です。現に Qiita の例の記事ではローカル変数への代入で説明できています。
退会済みユーザー

退会済みユーザー

2019/04/24 07:54 編集

いえ、C++、C#に限らずでいえばあります(実際できるかは別として)。プログラミング言語全般にわたる抽象的な概念として登録して初めて、そういえます。また、登録内容を変更できる立場であれば可能です。
Zuishin

2019/04/24 07:56 編集

参照渡しがない言語では登録できません。またあなたはその立場にありません。何を言っているのですか?
退会済みユーザー

退会済みユーザー

2019/04/24 07:56

つまり、C#で登録されていたとしても、それはC#に限った話なので、その登録に呼び名を尊重するよう強制される必要はないということです。
退会済みユーザー

退会済みユーザー

2019/04/24 07:56

というか、話がぶれてますよ。
Zuishin

2019/04/24 07:57

Wikipedia では、C++ と C# で実装されている戦略について述べられています。
Zuishin

2019/04/24 07:58

ブレているのではなく、あなたが本筋をとらえていないだけのように思えます。
hayataka2049

2019/04/24 08:19 編集

>Zuishinさん >エイリアスは説明であって本質ではありません。 個人的に、 swap(a, b) とか(a,bが値型なら値の書き換え、参照型なら参照の書き換えが当然できるべきとします) preg_match('/^(.*?)-(.*?)/', $str, $match); ((下)URLから引用。matchは呼び出し時点で呼び出し元に存在しない変数) とかあたりを「参照渡しの顕著な例」と思っていて、これは呼び出し元の名前空間を操作することで実現していると解しています。だからエイリアスってことでしょ・・・と思っていたのですが、その「参照渡し」とZuishinさんの書いているC++, C#の「参照渡し」はまた別ですよね?
退会済みユーザー

退会済みユーザー

2019/04/24 08:14 編集

なるほどそれをお聞きすればいいのか、本筋とはなんでしょう?「参照渡し」の「参照」とはなんでしょうか?wiki(英語)を参考にする限りでは、「参照による呼び出し(参照渡しとも呼ばれます)は、関数がその値のコピーではなく、引数として使用されている変数への暗黙の参照を受け取る評価方法です。」とあり、「参照」は「変数への暗黙の参照」であり、本筋と思われる一文として「これは通常、関数が引数として使用されている変数を変更(つまり代入)できることを意味します」とあります(google翻訳)。それを、「値に対する参照」を渡すことを含める拡大解釈してゆくのであれば、評価の目的に沿ってそれらは呼び分けられるべきではないでしょうか(C++などの仕様書は探し中です;;) というのも、目的あっての渡し方とするほうが適切だと思います(C++,C#に限らない評価戦略の話をする場合はなおさら)。
hayataka2049

2019/04/24 08:06 編集

あ、いや、エイリアスはC++, C#の用語で、そういう意味ではないんですね。指し示す先が固定されたポインタだからエイリアスか。 失礼しました。
Zuishin

2019/04/24 08:14

参照渡しの参照とは、それぞれの言語で実装された参照渡しの参照です。
Zuishin

2019/04/24 08:18

参照渡しという物理法則や法律があるのではなく、その戦略に名付けられた物です。しかしそれは参照の値渡しとはまるで違うものなので、一緒にすべきではありません。ppn さんのバイブルである Wikipedia にはこれらが同じものだと書いてないでしょう?
退会済みユーザー

退会済みユーザー

2019/04/24 08:19

「それぞれの言語で実装された参照というものを渡すことを参照渡しとよぶ。」ということでしょうか?
Zuishin

2019/04/24 08:20

ppn さんの主張は「参照渡しという名前は気に入らないから変えよう」というもので、私の主張は「登録され広く使われていて何の問題もないのにめんどくさいこと言うな!」です。
Zuishin

2019/04/24 08:24

それぞれの言語で実装された参照渡しで使われているのが参照渡しの参照です。新しい言語を作ったなら命名権はあなたにありますから、自由に名付けて結構です。しかし参照渡しを使う多くの言語では参照渡しと名付けられており、そうでない言語でもあなたに命名権は無く、また存在しないものに名付ける意味もありません。
Zuishin

2019/04/24 08:28

そして、言語によらない一般的な概念としては、参照渡しは帰納的に名付けられたもので、既存の言語に準じます。
退会済みユーザー

退会済みユーザー

2019/04/24 08:31 編集

すみませんがわたしには、命名がめんどうだからC++を踏襲して「ふわっ」とさせてお茶お濁した命名にしか見えていません。C++、C#の仕様書を読み直せばまた違うのかもしれませんが。
Zuishin

2019/04/24 08:31

回答の編集履歴を見ましたが、これより良い命名はありませんでした。
退会済みユーザー

退会済みユーザー

2019/04/24 08:51 編集

「参照渡し」そのものについては、「言語の定義に依れ、『参照渡し』のない言語にほかの言語の『参照渡し』を持ち出して共通の話題にするなという理解でよいでしょうか?
退会済みユーザー

退会済みユーザー

2019/04/24 09:04 編集

C#においての呼称に関しては正直そのままでも全然いいのですが(変えるとたしかにややこしいので)、「明解でない名」であることは気になります(明解っちゃ明解ですがもやっとします)。Zuishinさんのおっしゃられるように物理法則や一般化された話でなく、私がちゃんとした理解を持ち納得できるまでは個人名や作戦名みたいなもんだとして、問題を棚上げしておこうと思います。ご指摘ありがとうございました。
Zuishin

2019/04/24 09:21 編集

少なくとも「参照渡し」を検索した時に真っ先に出てくる侍エンジニアのような真似はすべきでないと思います。 理由はあちこちで説明した通り、JavaScript に参照渡しが実装された時に混乱するというのと、C# と JavaScript の両方を学んでいる人が混乱するというのと、侍クォリティーを鵜呑みにしたら恥ずかしいからです。
raccy

2019/04/24 09:44

初期から回答が大きく変わってしまいどうコメントしたら良いのかよくわかりませんが、もし、考えがまとまらないのであれば、一つの独立した文章として書きたいことを全て書いてみることをお勧めします。自分の考えを過不足なく相手に伝えるようにはどうしたら良いのか、自分の考えが正しいと証明するにはどのような文献を探せば良いのか、そもそも、自分の考えは本当に正しいのかという視点に立ちながら、文章を一つ書くと、見えなかった点、不十分な点がみつかり、より理解が深まると思います。 まぁ、そういう私はちゃんとできてないんでけどね。そうやって文章を書こうとしてまとまりきらなくて没になった記事もどきがBoostnoteに数十個ほどありますから。 なお、皆さんのコメントについては話が脱線しつつあるように思えるので、今の議論にあった質問を立てて貰えたらと思います。
退会済みユーザー

退会済みユーザー

2019/04/24 10:03

@Zuishinさん、@raccyさん 承知しました。脱線ばかりで申し訳ありませんでした。ちゃんと規格書を入手できるか、十分な情報が記載されている文献が見当たれば、「XX言語における参照渡しとはなにか」というような題で文章を起こそうと思います。思い違いや思い込みをご指摘いただけたので前より多少は理解を進められそうな気がします。いつになるのか怪しいですし、私の場合しばらく眠らせておいた方がいいかもしれませんが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問