2011-01-17 7 views
1

誰かが何がここで起こっているのを教えてください:学習ルビー:ブロック虐待を経由して作る無限次元配列

a = [0,1,2] 
a.each {|x| a[x] = a} 

結果は[[...], [...], [...]]です。 a[0]と評価した場合は[[...], [...], [...]]となります。 a[0][0]と評価した場合、私は[[...], [...], [...]]を無期限に受け取ります。

無限次元の配列を作成しましたか?どのように/なぜこれはおそらく機能するはずですか?

+0

なぜですか?位置a [x]にはaを見つけることができます。これは[x]をもう一度呼び出すことができます。次元性は常に直交性とも関係します。この前提はここでは示されていません。 – flq

+1

これはブロックとは関係がないことに注意してください。 'a = []; a [0] = a; a [1] = a; a [2] = a'はまったく同じ結果になります。 – sepp2k

+0

ブロックを使用すると、無限次元の配列を実際に(あまり)作成することはできません。 'blk = proc {| i | Array.new(10、&blk)}; a = Array.new(10、&blk) '。これは、Rubyが無限再帰を処理できないため、SystemStackErrorを引き起こします。 – Nemo157

答えて

3

基本的には、aのすべての要素をリスト自体を参照するように変更しました。リストには、自分自身を再帰的に参照している:

a[0] # => a 
a[0][0] # => a[0], which is a 
a[0][0][0] # => a[0][0], which is a[0], which is a 
... 

# =>は「この行があると評価」のためRubyismです)

をあなたはそれが無限ではない、それを見てどのように応じて。それは多かれ少なかれ、両面に書かれた「転がしてください」と書かれた紙のようです。

Rubyが[...]を印刷する理由は、リストが再帰的であることを発見するのに十分であり、無限ループにならないことです。

ちなみに、eachの使用方法は少し慣れないものです。 eachはリストを返します。通常は、この戻り値を変数に代入しません(変数を参照しているので、この場合はaです)。つまり、コードで[0,1,2]aに割り当て、a(各要素をaに設定)にループし、aaに割り当てます。

+0

ああ...そうだ。私はあなたがこれを行うことができる言語で遊んだことはないと思います。 – JnBrymn

+2

@ジョン:ほとんどの言語でこれを行うことができます。 C、C++(明示的なポインタまたは参照を使用)、Java、C#、Pythonなどを含む。 – sepp2k

+0

ああ...そうだ。そして私はちょっとばかばかしい気分になり始めています。振り返ってみると、これはすべて明らかだったはずです。 – JnBrymn

1

私はそれが自己参照のデータ構造だと思います。 a [x] = aはaのポインタを[x]に入れます。