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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

3回答

744閲覧

変数同士が連動して変更されてしまう条件?

torisan3

総合スコア50

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2020/06/22 03:54

編集2020/06/22 07:47

Rubyで、
変数を『=』で結ぶ時?に、単純な値の代入ではなく
『変数同士を同じものとして扱い、片方を変更すると、もう片方の変数の値も変更されてしまう』
……のような記述を過去見たような気がします。。

Ruby

1 d = [3, 1, 4] 2 c = d #cをdをしてみなす? 実際はcに代入しているだけの様子 3 4 p c #=>[3, 1, 4] 5 p d #=>[3, 1, 4] 6 7 c = [1, 5, 9] #cをdとみなしているので、dの値も変更される? 実際はcに代入しているだけの様子 8 9 p c #=>[1, 5, 9] 10 p d #=>[3, 1, 4] #[1, 5, 9]となる場合がある?

軽く試してみましたが、予想通りと言うか通常の代入になりました。
『●●を〇〇としてみなす』式の書き方や、そうなってしまう条件(?)
これと勘違いしているんじゃないか?等、何かありましたら教えてください。

ただの勘違いだったらすみません。
よろしくお願い致します。

■■6/22 15:10追記■■
破壊的メソッドはオブジェクト自身を変更するメソッドで
破壊的でないメソッドは結果のみを返し、代入(=)がある場合はその結果(返り値)のオブジェクトを新規作成し(?)、再代入する。

配列ではなく、単純な値(c = 1のような)の場合、
内部では、1が入っているオブジェクトを作成し、cはそこを参照しているだけ。(Cに1が入っているわけではない)
何かしらの方法でオブジェクトそのものの値を変更すれば、『puts c』の結果も変わる。
d = c とすればcとdは同じ所を参照する事になるが、
『c = c * 3』のような計算式(この場合『*』?)は、破壊的メソッドではないため、
結果である『3』を返し、新規オブジェクト『3』を作成し、cはそこのアドレスを参照しにいく。
それはdの参照とは関係がないため、dは『1』が入っているオブジェクトを参照したままで『puts d』は『1』のままである。
**単純な値の場合、破壊的メソッドがないため(?自信ない。。)**変数そのものに値が入っているように見えてしまう。

こんな感じでしょうか?
なんとなくは分かったのですが、
・=がある場合、新規オブジェクトを勝手に作っている?
・計算式は破壊的メソッドになる事はない?
・単純な値の場合、実質見た目が連動する事はない?
細かい所が詰め切れません。
以上3点が知りたいです。また明後日な事を言っていたら突っ込み頂けると助かります。

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

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

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

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

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

torisan3

2020/06/22 06:41

a = b.concat(c) でaとbが同じオブジェクトを参照しているというのが、少し理解が難しく何度も読み返しましたが、参考になりました。ありがとうございます。
guest

回答3

0

代入(=)がある場合はその結果(返り値)のオブジェクトを新規作成し(?)、再代入する。

返り値自体がオブジェクトの値であり、それを代入します。参照の値渡しってヤツです。

『c = c * 3』のような計算式(この場合『*』?)は、破壊的メソッドではないため、

結果である『3』を返し、新規オブジェクト『3』を作成し、cはそこのアドレスを参照しにいく。

c.object_id(c * 3).object_id を比較してもらうとわかると思いますが、この2つは別のオブジェクトですので、Integer#*は破壊的変更を行うメソッドではないです。そこの理解は良いとして、順序としては「新規オブジェクト『3』を作成し、戻り値『3』を返している」となります。(厳密には数値のオブジェクトは値によって固定なので新規という表現はあまり適していないかもしれません。)

変数の内部で何かが起きているという風に考えてらっしゃるのかもしれませんが、変数は箱であってそこにオブジェクトを入れているだけです。オブジェクトにただ名前をつけているだけと言った方がわかりやすいかもしれません。

もしかしたら数値を「単純な値」としているのに「オブジェクト」の話が出てきてしまっているところが問題の原因なのかもしれません。Rubyの場合、数値であってもオブジェクトですので、例えばRubyで3と書けば3になるんですが、厳密にはInteger(3)3にあたります。

そのメソッドが破壊的な変更をするかどうかは freeze を使って確認してみると良いです。

rb

1array = [1, 2, 3] 2array.freeze 3array << [4] # FrozenError

このように、フリーズしたオブジェクトに対して破壊的変更を行うと FrozenError を吐きます。

この回答は質問の本質的回答ではなく追記についてのみの回答ですのでBAは不要です。

投稿2020/06/22 06:51

編集2020/06/22 06:59
Mugheart

総合スコア2349

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

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

torisan3

2020/06/22 07:32

>返り値自体がオブジェクトの値 ~ 参照の値渡し >オブジェクトにただ名前をつけているだけと言った方がわかりやすいかもしれません。 これらの文がしっくりきました、ありがとうございます!
guest

0

ベストアンサー

ええと、

Ruby

1d = [3, 1, 4] 2c = d #cをdをしてみなす? 実際はcに代入しているだけの様子

「cとdとしてみなす」のではなく、「cもdも[3, 1, 4]と結びつけられた」のです。

Ruby

1c = [1, 5, 9] #cをdとみなしているので、dの値も変更される? 実際はcに代入しているだけの様子

こうすると、「cは[1, 5, 9]と結びつけられた」のですが、相変わらすdは[3, 1, 4]と結びつけられたままです。

いっぽう、「cもdも[3, 1, 4]と結びつけられた」状態で、対象の配列自体を書き替えるような操作、たとえばd << 2みたいな破壊的な追加を行なうと、配列が[3, 1, 4, 2]のように書き替えられるので、その後cの内容を表示すると……あとはご自分の目で確かめてみてください。

投稿2020/06/22 04:43

Daregada

総合スコア11990

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

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

torisan3

2020/06/22 06:22

質問分に追記を行いました。参照頂けると助かります。
torisan3

2020/06/22 07:59

最初の質問に対しての回答が比較的分かりやすかったので BAとさせていただきました。回答ありがとうございました。
guest

0

単純な値の代入ではなく

『変数同士を同じものとして扱い、片方を変更すると、もう片方の変数の値も変更されてしまう』
……のような記述を過去見たような気がします。。

Rubyの代入は常にそうなります。オブジェクトの参照を代入する形なので、破壊的変更は両者に影響が及びます。

投稿2020/06/22 04:04

maisumakun

総合スコア145184

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

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

maisumakun

2020/06/22 04:05

c = [1, 5, 9]は別なオブジェクトを代入しているので、全く無関係です。
maisumakun

2020/06/22 04:06

c = dの直後に、d << 8のように、配列自体を変更するようなことを行ってみれば、cにも同じ結果が出ることがわかるかと思います。
maisumakun

2020/06/22 04:09

新しいオブジェクトを作って変数に代入する「再代入」と、オブジェクトそのものの状態を変える「破壊的変更」の違いに注意してください。
torisan3

2020/06/22 06:23

質問分に追記を行いました。参照頂けると助かります。
maisumakun

2020/06/22 06:55

> 何かしらの方法でオブジェクトそのものの値を変更すれば、『puts c』の結果も変わる。 理論上はそうですが、Integerの値を破壊的に変更する方法は用意されていないため、そのようなことは不可能です。
torisan3

2020/06/22 07:47

単純な数値の場合は意識しなくても良さそうですね。 ここまで来て最初の回答の意味が理解できました。 お付き合い頂きありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問