Code Aquarium

minazoko's blog -*- 水底のブログ -*-

(Racket) racket/gui で年賀状宛名書き

このエントリは Lisp Advent Calendar 2014 - Qiitaの8日目の記事です。

racket/guiで年賀状印刷してみようとした。

いろいろ未完成感が漂ってますが、取りあえずこんな感じのものができました。
mnzk/nenga-print · GitHub
年賀はがき画像はこの辺から拝借
Green's Desktop greeting_cards-HowTo

f:id:minazoko:20141208231632p:plain

「NEXT」で順繰りに表示して「PDF」でPDF出力します。用紙サイズとかあってませんが。

なんで作ろうと思ったか

racket/gui というか racket/draw ではグラフィックスの描画にデバイスコンテキスト (dc<%>インターフェース実装クラス)を使います。まあこれはよくある仕組みなんですが、このデバイスコンテキストファミリーに「pdf-dc」なるものを見つけました。
描画デバイスを抽象化するDCを使えば canvas への描画も pdf への描画も同じロジックでできてしまうんです。
ある意味当たり前のことながら、PDFまで対応しているって、ありそうであんまり無かったような気がします。
GUIでレタッチして、その結果をそのままPDFへ出力するなんてことが簡単にできそうです。実際簡単でした。

racketのOOP

classシステムは独特ですが、理解するとまぁ色々できて面白いです。
一つ分かり難く感じているのは 初期化ロジックのあたりですね。
派生クラスとスーパークラスの初期化の流れや初期値の渡し方。特に派生クラスで引数を加工してからスーパークラスへ渡すようなプログラムの書き方がイマイチよくわかりません。この辺も一度まとめないといけないかな。

Class vs Struct

どちらを使うか迷うんですが、個人的にはstructのclassに対する最大のアドバンテージはパターンマッチできるところだと思います。

  • 継承やメソッドを使った実装。mixin, traitを活用 => class
  • 取りあえずデータを構造化しておいて、必要な時にパターンマッチで分解 => struct

racketにはCLOSやClojureのようなマルチメソッドが無いので、structで総称みたいなことはやりにくいです。*1 その代わりにmixinやtraitでクラスに対する属性・操作をパーツ化できるようになっています。

もうちょっと・・・

UI上で、テキストユニットを選択して位置調整みたいな事もやる予定だったんですが時間切れになってしまいました。
ぼちぼちと機能追加なんかをしていくかもしれません。
データもソースに書きこんでしまってますので、外部から読み込みたいですね。

*1:一応genericというのはありますがマルチメソッドとしては使いずらい