スポンサーサイト

 --------
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
カテゴリ :スポンサー広告 トラックバック(-) コメント(-)

初心者が躓くかもしれないRGSS2の7つの小石

 2010-02-07
あなたは、どこで躓きました?
よく聞くところや実際私が躓いたところを紹介!

1.SystemStackError - stack level too deep
2.=(代入) と ==(等価比較)
3.配列の複製
4.end で SyntaxError
5.クラス変数とインスタンス変数
6.演算子の優先順位
7.イベントコマンド「スクリプト」での改行

1.SystemStackError - stack level too deep
そう、F12でリセットを行ったときに出るやつです。
これは、ハマりましたね。

さて、どんなときに出るのかな?
def deep(value = 0)
  begin
    deep(value + 1)
  rescue SystemStackError
    puts value
    exit
  end
end
deep
こういうとき。
同メソッドの2行目で自分自身を呼び出しています。
つまり、ここでメソッドの呼び出しが無限ループするわけです。

stack(積み重ね)
難しいことは、各自調べて欲しいのですが、
スタックというのは、メソッドの引数やローカル変数なんかを保存しておく場所です。

まず、deepメソッドが呼ばれ、引数や変数の値のメモを取ります。
で、メソッド2行目でdeepが呼ばれたので、
後で元の場所に戻ってくるために呼び出しもとのメモを加えます。
2回目のdeepでも同じことを行います。
すると、メモが積み重なっていって、うわぁぁぁぁぁっとなってしまいます。
これが、スタックオーバーフローでございます。
しかし、そうなる前にRGSS2が例外を発生させてくれます。
これが、SystemStackError です。

今にも倒れそうにグラついてるメモの山を見たRGSS2くんが、
「それ以上やったら、PCくんがメモの雪崩に押しつぶされちゃうじゃないか!」と言っているのです。
ところが、叱られたあなたは、
「何でエラー出んだよどこも間違ってないだろ!」と怒ってしまうわけですね。
PCくんがかわいそうです!少し反省してください。

あれ?何の話でしたっけ?すぐ脱線しちゃう。悪い癖ですね。
メソッドの無限ループで例外が発生することはわかってもらえたかな?
あ、レスキューしてたね。
サンプルの rescue SystemStackError 以下3行をコメントアウトして実行すると、
例外が発生すると思います。

あー、なんか長くなってきたね。
前に説明したことあるから、それ読んで。
http://cacaosoft.web.fc2.com/tkool/lecture/rgss2/006.html
http://cacaosoft.blog42.fc2.com/blog-entry-121.html


2.=(代入) と ==(等価比較)
if hoge = 3
  p hoge
end
こんな感じ。
hoge が 3 のときに処理を実行したいのだけれど、
代入しちゃってるから、常に 3 だったりしちゃいます。
false となるのは、false と nil のみなので、数値だと true 判定なのです。
どうしても、間違っちゃう人は、定数を左辺にしてみると良いかもですね。
if 3 = hoge
  p hoge
end
これだと、例外が発生するので間違いに気付きやすいです。
変数同士のときは知りません


3.配列の複製
ary = [Bitmap.new(32, 32)]
new = ary.dup
p ary.object_id == new.object_id        # => false
p ary[0].object_id == new[0].object_id  # => true
ary という配列を new に複製しています。
3行目の結果が false ですので、新しくオブジェクトが作成されているのがわかります。
4行目の結果は、true です。つまり、画像はどちらも同じオブジェクトということになります。
普通、このようの複製をした場合は、画像も一緒に複製されることを期待します。
要素まで複製されないことを知らないと、要素を操作したときに
両方の要素が変更されてしまうことになります。

どういうことかというと、
ary << 1
p ary.size == new.size # => false
new[0].dispose
p ary[0].disposed?     # => true
まず、ary にのみ要素を追加したので、ary と new の配列のサイズが違います。
そして、new の 画像を解放します。
解放した画像は、new のもののみですが、ary の画像も解放されています。
これは、どちらの配列の画像も同じオブジェクトだったためです。

これを回避するには、深いコピーをする必要があります。
ary = [Color.new(0, 0, 0)]
new = ary.dup
p ary[0].object_id == new[0].object_id # => true
new = Marshal.load(Marshal.dump(ary))
p ary[0].object_id == new[0].object_id # => false
例が悪かったですね。
画像は、マーシャルダンプできないんで、for文とか使って複製してください。
new = []
for bmp in ary
  new << bmp.dup
end


4.end で SyntaxError
これは、未だにやるのではないだろうか?
書きかけのまま実行してみたり、編集ミス、削除ミス。
end の数が合ってないときに出てくるよね。
これは、場所が特定できないと虱潰しに見ていくしかないから、
なるべくこまめに実行して、セクションはクラスごとに分けたほうがよさげ。

5.クラス変数とインスタンス変数
クラス変数とインスタンス変数の違いが良くわかってない気がする。
クラス変数は、クラスで共有する変数で、
インスタンス変数は、インスタンスごとに生成される変数です。
まぁ、知らなくても何とかなるかな?
私は使ったことあったかな??
class Hoge
  @@piyo = 0
  attr_accessor :fuga
  def piyo=(value)
    @@piyo = value
  end
  def piyo
    return @@piyo
  end
end
a = Hoge.new
b = Hoge.new
p a.piyo = 3  # => 3
p b.piyo      # => 3
p a.fuga = 6  # => 6
p b.fuga      # => nil


6.演算子の優先順位
not and or の演算子の優先順位が異常に低いです。
デフォルトでは、この演算子を使用しているので、
同じように使用しているのではないでしょうか?
たしか、一番低かったと思います。
def piyo(arg)
  p arg
end
def fuga
  return not true # => ERROR
end
p hoge = true and false # => true
piyo(false or true) # => ERROR
fuga
このようなエラーや不具合は、他のメソッドよりも処理の優先順位が低いためです。
もちろん () を使用すれば、回避できますが括弧を付けると不恰好になってしまう箇所もあります。
not and or の代わりに、! && || を使用すると、括弧が不要になります。


7.イベントコマンド「スクリプト」での改行
イベントコマンド「スクリプト」の入力欄では、改行は出来ないのか?
という声をよく目にしますが、もちろん可能です。
これは、スクリプトエディタでも同様です。
文法に従って正しい箇所に改行を入れてください。
詳しくは、各自調べていただいて、簡単に説明したいと思います。
基本的に演算子の後ろでは改行可能です。
hoge =
  1234567890
引数の区切りで改行が可能です。
Color.new(
  255,
  128,
  0
)
文字列の途中で改行を入れると、改行文字が入ってしまいます。
長い文章は、+ で連結します。
str = "あいうえお" +
      "かきくけこ" +
      "さしすせそ"

特殊な記号を使うことで、式の終わりを指定することもできます。
; で、式の終わり、\ で、式の継続を表します。
str\
= "ab\
c"; p str; exit
ただし、変数やメソッドの名前で切ることは出来ません。
コメント




 

 ※ コメント内にURLを含めるには、バッククォート(`)をURLの直前に付け加えてください。


管理人のみ閲覧許可 [?]

おぉ、役に立ってよかったです。

んー、それだと可読性が。。。
それに、if hoge == 3 としたいのに、
わざわざ unless hoge != 3 とはしないでしょ。

== と書かないといけないところを = と間違えて書いてしまう。
ということが言いたかったのですが。。。
【2010/02/09 21:23】 | CACAO | [編集]
おお・・・
大変参考になりました。特に3は。
4は凡ミスなだけに1生涯の友達ですね。よくやります。

>2を避ける別の方法
unless ○○ != ×× を使う。

例:
unless hoge != 3
p hoge
end

これで・・・回りくどくなっただけ?
【2010/02/08 22:22】 | たねQ | [編集]
トラックバック
トラックバックURL:
http://cacaosoft.blog42.fc2.com/tb.php/355-4b2e6eb3
≪ トップページへこのページの先頭へ  ≫
カレンダー
04 << 2017/05 >> 06
- 1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31 - - -

カテゴリー
最近の記事
02/28 お返事
02/14 お返事
01/21 お返事
01/12 更新情報
11/28 お返事

最近のコメント
03/16 お返事
01/21 お返事
11/30 z座標
11/20 z座標
08/03 お返事

タグクラウド

リンク
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。