EmueraでPACK/UNPACKできるかなーと思って試してみた。たとえばRubyではバイナリ列はStringオブジェクトと変わらないので、同じようなことができないかと思ったわけだ。で、EmueraにはUNICODE関数とENCODETOUNI関数があるのでこれを使えば数値と文字列とを相互に変換できる。
試行錯誤の経緯は11月1日の雑記を見てもらうとして、実際にできあがったERBとERHをまとめたものをアップロードした。以下からダウンロードできる。
BINARRAY.zip
ERHを使っているので、Emuera1808α以降のみ対応。ERHについてはこのまま正式に採用される仕様らしいので多分大丈夫……なはず。
数値型配列をループしながら一要素ずつPACKして文字列に格納する。
文字列から格納した数値を取り出すには、UNPACKを呼んで、広域配列変数TMPに格納された値をループしながら読み出せばいい。
VARSET LOCALS LOCAL:0 = 1, 32, 4000, -50000, 100000, 0, 8, -128 REPEAT 8 LOCALS += PACK(LOCAL:COUNT) REND LOCAL = UNPACK(LOCALS) REPEAT LOCAL PRINTFORML {TMP:COUNT} REND
関数に可変長の配列を渡すときに使えるかもしれない。もちろん適当なデリミタで繋げて文字列として渡してもいい(というかそっちの方が分かりやすいだろうし処理も軽い気がする)が、そうしない方法の一つということで。
ゆくゆくは型情報を埋め込めるようにして、数値と文字列両方を格納できる配列にできたらいいなあとか考えているが、展開した結果を格納できるのが数値か文字列のいずれか一種類だけなのでまあどうしようもない。
数値を文字列に格納してしまう手はあるが、64bit整数は8byteで済むのに文字列にしたら5桁から10byte以上使うようになるし最大で39byte(※マイナス符号付の場合、正の数なら38byte)も使うのでちょっとなーという感じがある(もっとも、4桁以下の数に収まるのなら問題ないどころか、3桁以下ならむしろ有利になったりするのだが、あくまでメモリ量だけで見るなら、という話で)。
固定長の数値変数より可変長の文字列の方が参照/代入のコストがでかいし。
うーんやっぱり一要素ずつ取り出して型判別するのがいいんだろうなあ。構造体っぽいものを作るならどうせ一要素ずつしかアクセスしないと思うので、それならそれでいい気もする。バイナリ列に各プロパティの情報を埋め込むと容量の無駄遣いなので、バイナリ列を生成する側/取り出す側で各プロパティの情報を持つ方が、というかアクセスするためのAPIを叩くとかした方がいいだろうな。
どのみち先頭に構造体の種類を示すIDか何かを埋め込む必要はあるんだけど、それくらいなら問題にならない。1byteじゃちょっと心もとないが、2byteある。というか1万もあれば充分だろうという気がする。3万も4万もIDが必要になる……ってことはないだろう。
まあそのうち考えよう。ひょっとするとENCODETOUNIの戻り値をLOCALSで受け取れるようになったりするかもしれないし。
コメントをかく