永続化と評価の話

永続化
プログラムで生成したデータが次回実行時でも利用できる
マーシャル化
バイナリデータ化し、loadやdumpすることができるようにすること

Timeオブジェクトをファイルへ保存する方法はいくつかあり、

  • Time#strftimeで文字列として保存する
  • Time.atクラスメソッドで10進数で経過秒数を出力

これらの方法で作成されたファイルはRuby以外のプログラムでも利用可能。しかし、Marshal.dumpメソッドを使って永続性を持たせると、Rubyだけで利用することになるので注意すること。

マーシャルオブジェクトの制限

  • すべてのオブジェクトをマーシャルできるわけではない
    • プログラムの実行状態に依存し、他のプロセスに持ち込めない
    • 永続性が何かを一意に決められないもの(例:Fileオブジェクト)
    • クラス名を持たないオブジェクト(復元時に元のクラス名が必要となるから)
  • 保存する時にMarshalモジュールバージョンが異なるとデータを復元できない(TypeError例外を発生)
    • Marshal::MAJOR_VERSIONの場合、バージョンが異なる時
    • Marshal::MINOR_VERSIONの場合、現在のマイナーバージョンよりバージョンが大きい場合

さて、永続性のあるファイルを作りましょう。

t = Time.now()
File.open("time.data", "rb") do |file|
  Marshal.dump(t, file)
end

バイナリデータなので"rb"。"b"をつけるの忘れないように。
読み込むときは

require "pp"

File.open("time.data", "wb") do |file|
  pp(Marshal.load(file))
end

PPライブラリは清書「pretty print」、オブジェクトを目で確認するためのライブラリ。デバッグに使うといいらしい。私は今まで"p"使ってたんだけど、"pp"を代わりに使ってもいいのか。じゃあ、irbを使おう。

irb(main):001:0> require "pp"
=> true
irb(main):002:0> a = 1
=> 1
irb(main):003:0> p a
1
=> 1
irb(main):004:0> pp a
1
=> nil

ん?ppだとnilが返ってくる・・・。調べたら、

pp(obj, out = $>, width = 79) -> object 
指定されたオブジェクト obj を出力先 out に幅 width で出力します。出力先 out を返します。

aはオブジェクトじゃないから、nilだったんだ。そりゃそうだ、ppはオブジェクトのデバック用で使うんだよ。実際にコード書いてみないと、勘違いって見つけられないもんだなぁ。

評価

評価
式の最終的な値を求めることを評価するという

代入式の左辺だけが、評価抜きで未設定の変数を記述できる

a = 32  #ok
func(b)   #評価できないのでダメ


>>追記
「aはオブジェクトじゃないから、nilだったんだ。」本当は違う理由らしいです。調べるの宿題になってしまった・・・。