proglog

主にプログラミングに関する断片的メモ

[windows][soft] pdftohtmlでr5rsをhtmlに変換

R5RS (Revised^5 Report on Algorithmic Language Scheme) 日本語訳にあるR5RSをhtml形式にしたい。
windowsで。


TeX(pLaTeX2e)やらPostscriptをhtmlに変換する方法はよく分からない。
それとも既にどこかにあるだろうか。
それは分からないけど、取り敢えず、PDFになったものを変換することに。


以下の手順でわりといい感じに。

  1. Desktop Linux - PDF を HTML に変換するで紹介されているpdftohtmlを使う。

コマンドラインオプションも書いてある。

  1. PDFTOHTML conversion programから辿ってpdftohtml | Free Development software downloads at SourceForge.netからPDFTOHTMLのwindowsバイナリをダウンロード、展開。
  1. XpdfからXpdfのwindowsバイナリとLanguage Support PackagesのJapaneseをダウンロードする。
  1. PDFTOHTMLを展開したディレクトリにXpdfを展開して出てきたファイル全部を入れる。
  1. そのディレクトリにjapaneseというサブディレクトリを作って、ランゲージパックのxpdf-japanese.tar.gzを展開して出てきたファイルを全部入れる。
  1. PDFTOHTMLとXpdfの全ファイルが入っているディレクトリにxpdfrcという名前のファイルを作り、以下の内容を書き入れる。
#----- begin Japanese support package (2011-sep-02)
cidToUnicode	Adobe-Japan1	japanese/Adobe-Japan1.cidToUnicode
unicodeMap	ISO-2022-JP	japanese/ISO-2022-JP.unicodeMap
unicodeMap	EUC-JP		japanese/EUC-JP.unicodeMap
unicodeMap	Shift-JIS	japanese/Shift-JIS.unicodeMap
cMapDir		Adobe-Japan1	japanese/CMap
toUnicodeDir			japanese/CMap
#fontFileCC	Adobe-Japan1	/usr/..../kochi-mincho.ttf
#----- end Japanese support package
  1. Ghostscript 9.04 and GSview 5.0 J (Official Site)からGhostscriptのwinバイナリをダウンロードしてインストールし、パスを通す。インストーラーのオプション「Use Windows TrueType fonts for Chinese, Japanese and Korean」をチェック。

で、実行。

>pdftohtml -c -enc UTF-8 r5rs-ja.pdf

で二つほどフォントがないよ、と言われるけど、なんとか無事にちゃんと日本語のhtmlファイル群が生成された。

なんかFirefoxでみると、段組みのまん中の幅が狭くて、多少重なった感じに表示される。
でも、IEで見ると、きれいなもの。
この違いはなんだろうか?

[tombloo][study] tomblooで学習:絶対復習

絶対復習というサイトがある。
登録した覚えたいことを、忘却曲線に沿ったみたいな感じで、リマインドしてくれるサービスを提供してくれている。
以前は、tomblooのポスト先にあったような気がする。
絶対復習+tomblooの組合せが最強すぎる件について - 教えてお星様という紹介記事がある。
でも、その後、サービスが停止して、ポスト先から外れたということなのかな。


で、その後、絶対復習のサーバ移行&復活 - I am Cruby!ということになったらしい。


そこで、ポスト先に存在する最新のリビジョンかと思われる、xpi/chrome/content/library/20_model.js at 9b6b4c821e2da87aaeb5bba819428a8c072978dd from to/tombloo - GitHubから、絶対復習の部分を切り出して、url部分を書き換えてみたら、普通にポストできたので、パッチをここに貼っておくことに。


tomblooで学習。15秒後に復習するために。 - うぇぶとらばぁすと組み合わせると割りといい感じかも、と我田引水。

[devel][racket] Racketのクラスの基礎っぽいことのメモ(2) 継承とか

その前に大事なことを書き忘れた。
Racketのオブジェクトシステムには、javaC++のような明示的なコンストラクタメソッドがない。
クラスのフィールドの宣言などは、オブジェクト生成時に、上から順番に評価されるので、そのことが実質的なコンストラクタの働きをする、ということになる、ということらしい。
そう言えば、Gaucheのオブジェクトシステムも、明示的なコンストラクタがなかったような。
Lisp系ってこういう風なのかな。


で、本題。
メソッドに関して、いわゆるオーバーライドとaugment(拡張、付加)という概念が登場する。

継承

フィールドの継承

まずは、シンプルに。

(define exclass2%
  (class* object% ()
    (super-new)
    (init-field [pblcfield1 10] [pblcfield2 20])))

(define exclass2-1%
  (class* exclass2% ()
    (super-new)
    (inherit-field pblcfield1)
    (define/public (getsf1)
      ;直接アクセス
      pblcfield1)
    (define/public (getsf2)
      ;間接的にはアクセスできる
      (get-field pblcfield2 this))))

(send (new exclass2-1%) getsf1)
;;;>10
(send (new exclass2-1%) getsf2)
;;;>20

サブクラス内で、(inherit-field フィールド名)を使って、使用したいパブリックなフィールドを指定する。
すると、そのサブクラス内で、ダイレクトにそのフィールドにアクセスすることができる。
ここでは、pblcfield1。


一方、この指定をしていないパブリックフィールドも、(get-field フィールド名 this)を使えば、間接的にアクセスできる。
ダイレクトアクセスができないだけで、当然継承はされてるので。
ここでは、pblcfield2
thisはいわゆるthis。


プライベートフィールドにはダイレクトアクセスはできない。
自前のアクセサを定義してあれば、別だけど。


javaのprotectedに当たる仕組みはないっぽい。

メソッドの継承

(define exclass3%
  (class* object% ()
    (super-new)
    (init-field [pblcfield1 "pubfield1"] [pblcfield2 "pubfiled2"])
    (define/public (smethod1)
      (string-append  pblcfield1 " - " pblcfield2))
    (define/public (smethod2)
      (string-append  pblcfield2 " - " pblcfield1))))

(define exclass3-1%
  (class* exclass3% ()
    (super-new)
    (inherit smethod1)
    (define/public (method1)
      ;直接
      (smethod1))
    (define/public (method2 marg2)
      ;間接
      (string-append marg2 (send this smethod2)))))

(send (new exclass3-1%) method1)
;;;>"pubfield1 - pubfiled2"

(send (new exclass3-1%) method2 "marg2 - ")
;;;>"marg2 - pubfiled2 - pubfield1"

(inherit メソッド名)で継承したいメソッドを指定する。
すると、ダイレクトにそのメソッド、ここではsmethod1にアクセスできる。


一方、指定していないメソッドも、外部での呼び出しと同じく(
send this メソッド名)で呼び出すことができる。


オーバーライド

define/publicで宣言されたメソッドをオーバーライドすることができる。
そしてそれには、そのオーバーライドを行うメソッドをdefine/overrideで宣言する。
ここではsmethod1。


そしてそのオーバーライドを行うメソッドの中で、スーパークラスのメソッドを呼び出して利用することができる。
(super メソッド名)という形になる。
ここでは、smethod2。

(define exclass3-2%
  (class* exclass3% ()
    (super-new)
    (define/override (smethod1 marg1)
      ;全く上書き
      marg1)
    (define/override (smethod2)
      ;スーパークラスのメソッドを利用
      (string-append "override - " (super smethod2)))))

(send (new exclass3-2%) smethod1 1)
;;;>1
;;;>"override - pubfiled2 - pubfield1"
(send (new exclass3-2%) smethod2)

smethod1は数値を返すメソッドに全く上書き。
smethod2は、スーパークラスのsmethod2の出力を利用している。


当然、このオーバーライドしているサブクラスのメソッドを、そのサブクラスでオーバーライドすることができる。
この連鎖を止めるには、define/override-finalでメソッドを宣言する。
あるいは、最初からオーバーライド禁止でdefine/public-finalで宣言する。

拡張(augmentation)

augmentationをどう訳していいのか分からないので、ここでは拡張とした。
増強とか付加の方がいいかもしれない。
要は、サブクラスのメソッドを、スーパークラスで呼び出す。
superを使ったオーバーライドと逆の形。

スーパークラスのメソッドに、サブクラスのメソッドを添加するイメージ。
emacs lispで言うとスーパークラスのメソッドにhookを用意する感じ。



この仕組みを使うには、スーパークラスのメソッドをdefine/pubmentで宣言し、添加を行うサブクラスのメソッドをdefine/augmentで宣言する。

(define exclass4%
  (class* object% ()
    (super-new)
    (define/pubment (smethod1)
      (string-append "SuperClass" (inner "" smethod1)))))

(send (new exclass4%) smethod1)
;;;>"SuperClass"

(define exclass4-1%
  (class* exclass4% ()
    (super-new)
    (define/augment (smethod1)
      (string-append " - SubClass" (inner "" smethod1)))))

(send (new exclass4-1%) smethod1)
;;;"SuperClass - SubClass"

スーパークラスの中で(inner デフォルト値 サブクラスのメソッド名)という形で、サブクラスのメソッドを呼び出す。
デフォルト値は、サブクラスで添加メソッドが宣言されない時に使われる。
(void)という形をよく見た。


ここでは、サブクラスのメソッドの出力を、スーパークラスのメソッドの中で文字列連結の形で利用してる。


そして、さらなるサブクラスでの付加も可能なので、この添加メソッドの中でもinnerを使用している。


ファクトリメソッドなんかを作る時のvirtualとかabstractの代わりって感じか。


この添加連鎖を止めるには、単にinnerを使わない、だけ。

(define exclass4-4%
  (class* exclass4-1% ()
    (super-new)
    (define/augment (smethod1)
      (string-append " - use no inner"))))

(send (new exclass4-4%) smethod1)
;;;>"SuperClass - SubClass - use no inner"

(define exclass4-5%
  (class* exclass4-4% ()
    (super-new)
    (define/augment (smethod1)
      (string-append " - how about me?"))))

;効いてない
(send (new exclass4-5%) smethod1)
;;;>"SuperClass - SubClass - use no inner"

別にエラーにもならないけど、何も効いてない。

オーバーライドメソッドにaugmentする。

この辺からややこしさが増す。
define/publicなメソッドをオーバーライドするんだけど、同時に、サブクラスで、augmentして欲しい、そんなあなたにoverment

(define exclass3-3%
  (class* exclass3-2% ()
    (super-new)
    (define/overment (smethod1 marg1)
      (string-append  "super:" marg1
                      (inner "default" smethod1 (string-append  "marg1:" marg1 ))))))

(send (new exclass3-3%) smethod1 "sarg3 - ")
;;;>"super:sarg3 - default"

(define exclass3-4%
  (class* exclass3-3% ()
    (super-new)
    (define/augment-final (smethod1 marg1)
      (string-append " - augment - " marg1))))

(send (new exclass3-4%) smethod1 "sendarg4")
;;;>"super:sendarg4 - augment - marg1:sendarg4"

オーバーライドの例で使ったクラスexclass3-2% を継承し、exclass3-3% を宣言する。
ここで、define/overmentを使う。
つまり、overrideするし、自分のサブクラスからaugmentもして欲しい。
だから当然、innerも使う。


クラスexclass3-2% に対するオーバーライドとしては、単純にオーバーライドするだけで、superは使ってない。
ただ、次に宣言するexclass3-4% に対してスーパークラスであることを示すために"super:"という文字列を出力している。


クラスexclass3-4% がaugmentを行う。
ここでは、define/augment-finalを使っている。
ここでストップのサイン。


出力は、単純に、exclass3-4% による添加が行われた形になっている。

添加をオーバーライドする

おんなじ継承の階層に兄弟クラスをわざわざ作るんじゃなくて、継承させて、添加部分だけを書き換えたい、そんなときだろうか、このdefine/augride

(define exclass4-2%
  (class* exclass4-1% ()
    (super-new)
    (define/augride (smethod1)
      (string-append " - augride"))))

(send (new exclass4-2%) smethod1)
;;;>"SuperClass - SubClass - augride"


(define exclass4-3%
  (class* exclass4-2% ()
    (super-new)
    (define/override-final (smethod1)
      (string-append " - override-final"))))


;拡張部分がオーバーライドされている。
(send (new exclass4-3%) smethod1)
;;;>"SuperClass - SubClass - override-final"

拡張の最初の例でサブクラスとして使ったexclass4-1% を継承してexclass4-2% を宣言する。
ここで、exclass4-1% に対して添加、拡張、augmentを行うけど、overrideも許可するので、augrideを使う。


出力は通常のaugment通り、 "- augride"が添加されたものになっている。


次に、これを継承してexclass4-3% を宣言する。
ここではdefine/override-finalを使ってオーバーライドしている。
これは前述のとおり、これ以上のオーバーライドを禁止するもの。


出力は、直接のスーパークラスであるexclass4-2% が行ったaugment、添加部分だけがオーバーライドされて、" - override-final"だけが、付加されたものになっている。
つまり、メソッド全体がオーバーライドされるわけではない、ということを表している。


とりあえず、こんなもの。
あと、名前の中と外とか、genericがどうのこうのとか、mixin、traitとか、contractがなんやらとかあるみたいけど、どうしようか、という感じ。

[devel][rakcet] Racketのクラスの基礎っぽいことのメモ(1)

「あ…ありのまま今起こった事を話すぜ!
『俺はGaucheの最新版をcygwinにインストールする作業をしていたと思ったら、いつの間にかRacketのクラスを調べていた』。
な…何を言っているのかわからねーと思うが、
俺も」
という訳で、Racket(旧名PLT Scheme)のオブジェクト指向部分、クラスの作り方をちょっと調べたのでメモ。


参考にしたのは、Racketから、


今のところ分かった特徴としては、

  • 最上位クラスはobject%
  • 多分単一継承
  • javaのようにインターフェイスがある
  • mixinの構文があるみたい
  • アクセスコントロール的なものがなんかちょっと多い
  • でもprotectedやパッケージスコープみたいなものはないような?

などなど。

まずは基本型

(define exclass0%
  (class* object% ()
    ;スーパークラスの初期化
    (super-new)
    (init [arg1 1] [arg2 2])
    (field [pblcfield1 arg1] [pblcfield2 arg2])))

クラスを定義して、シンボルにバインドしている。
クラス名は規約により"%"で終わる。

(class* スーパークラス名 (インターフェイス名)
  (super-new スーパークラス生成)
  (init 初期化変数:オブジェクト生成時に渡す、初期化のための引数)
  (field パブリックなフィールド、つまりインスタンス変数の宣言)
  )

class*じゃなくて、classというのもある。
この場合は、実装するインターフェイス宣言部分が無い。
でも、いくつかのソースではインターフェイスを使ってなくてもあえてclass*を使ってあった。
だから、こっちで。


スーパークラスの生成は必ず行う。
処理は上から、書いた順に行われる。


パブリックなフィールドというのは、パブリックにアクセスが出来るデフォルトのアクセサが使えるフィールド、ということ。

オブジェクト生成

以下、実行結果は;;;>で示す

(define exobj0 (new exclass0%))
;フィールド値取得
(get-field pblcfield1 exobj0)
;;;>1
;フィールド値変更
(set-field! pblcfield1 exobj0 2)
(get-field pblcfield1 exobj0)
;;;>2

デフォルトのゲッターとセッター。

オブジェクトの生成と初期化

名前付き引数
(define exobjn (new exclass0% [arg2 20] [arg1 10]))
(get-field pblcfield1 exobjn)
;;;>10
(get-field pblcfield2 exobjn)
;;;>20

newを使ってオブジェクトを生成する。

位置による引数
(define exobjm (make-object exclass0% 30 40))
(get-field pblcfield1 exobjm)
;;;>30
(get-field pblcfield2 exobjm)
;;;>40

make-objectを使う。

位置と名前
(define exobji (instantiate exclass0% [50] [arg2 60]))
(get-field pblcfield1 exobji)
;;;>50
(get-field pblcfield2 exobji)
;;;>60

instantiateを使う。

ちなみにこれらの頭にsuper-を付けたものをスーパークラスの生成に使う。

フィールドと初期値

初期化変数を介さずにフィールドを宣言、初期化する。

(define exclass01%
  (class* object% ()
    ;スーパークラスの初期化
    (super-new)
    ;フィールドの宣言
    (init-field  pblcfield1 pblcfield2)))


(define exobj01-1 (make-object exclass01% 10 20))
(get-field pblcfield1 exobj01-2)
;;;>10
(get-field pblcfield2 exobj01-2)
;;;>20

init-filedを使うと、フィールドと、それがオブジェクト生成時に直接引数を受け取ることを同時に宣言できる。


デフォルト値を付けて宣言することもできる。

(define exclass02%
  (class* object% ()
    (super-new)
    (init-field  [pblcfield1 30] [pblcfield2 40])))


(define exobj02 (new exclass02%))
(get-field pblcfield1 exobj02)
;;;>30
(get-field pblcfield2 exobj02)
;;;>40

プライベートなフィールドとメソッド

(define exclass1%
  (class* object% ()
    (super-new)
    (define prvtfield1 1)
    (define/public (getprvt1)
      prvtfield1)))

(define ex1obj (new exclass1%))
(send ex1obj getprvt1)
;;;>1

defineとかdefine-valueで宣言したフィールドはプライベートになる。
これは、デフォルトのアクセサは使えず、javaと同じように、直接アクセスできるのは、そのクラスからのみとなる。


しかし、自前でアクセサを用意すれば、当然それを使ってアクセスは出来る。


define/publicがメソッドの宣言。
どこからでも使えるパブリックなアクセスが可能。


メソッドを呼び出すのは、(send 対象オブジェクト メソッド名)。

プライベートフィールドの初期化

defineに直値を与える他に、初期化変数を使って、オブジェクト生成時に値を受け取ることもできる。

(define exclass1-2%
  (class* object% ()
    (super-new)
    (init [arg1 10])
    (define prvtfield1 arg1)
    (define/public (getprvt1)
      prvtfield1)))

(send (new exclass1-2%) getprvt1)
;;;>10
(send (make-object exclass1-2% 20) getprvt1)
;;;>20

プライベートメソッド

define/privateを使って宣言する。
java同様、そのクラスの中からしか使えない。

(define exclass1-3%
  (class* object% ()
    (super-new)
    (init [arg1 10])
    (define prvtfield1 arg1)
    (define/public (getprvt1)
      (privmethod1)
      prvtfield1)
    (define/private (privmethod1)
      (set! prvtfield1 (+ prvtfield1 10)))))

(send (new exclass1-3%) getprvt1)
;;;>20
(send (make-object exclass1-3% 20) getprvt1)
;;;>30

プライベートなメソッドを、パブリックなメソッドから呼び出している。


次回は継承

[devel][python][gae] flask-babelで国際化のメモ

pythonで、gettextメッセージカタログによる国際化のためのパッケージBabelをflaskから簡易に利用するためのライブラリflask-babel。

これを使って、既存のサイトをi18nした時の手順メモ。

  • リファレンス Flask-Babel ― Flask Babel 1.0 documentation
  • flask-babel 0.8
  • flask、jinja2、werkzeugなどはそれぞれ最新版でないと動かない
  • プロジェクトルートにbabel、pytz、flaskextとspeaklater.py
  • flaskextには__init__.pyの空ファイルも入れておく
  • プロジェクトルートにmysettings.cfgの空ファイル


wsgiオブジェクトを作る各モジュールに、

from flaskext.babel import Babel

app = Flask(__name__)
app.config.from_pyfile('mysettings.cfg')
babel = Babel(app)

@babel.localeselector
def get_locale():
    return request.accept_languages.best_match(['ja', 'ja_JP', 'en'])


babel.cfgはこんな感じ

[jinja2: **/templates/**.html]
encoding = utf-8
extensions=jinja2.ext.autoescape,jinja2.ext.with_

jinjaのテンプレートしか国際化しないので。

これをプロジェクトルートに。


これまでのjinjaテンプレートに変換用のIDを{{ _("ID") }}を使って書き足していく。

<p>
{{ _("Welcome to My Site.") }}ようこそ私のサイトへ
</p>

基本的には、表示したい英文そのものIDとして使っちゃえばいい感じ。

だけど、ID部分に>とか<、つまりタグやらが入ってるとうまくいかない。

ダブルクォート"も無いほうが、面倒が少ないかもしれない。

ワード構成文字とピリオド、カンマ辺りくらいが無難?

そして、あんまり長すぎてもよくないみたい。

その場合はキーワードに絞っていかにもIDっぽいものに。

次にそれを抽出

pybabel extract -F babel.cfg  -o messages.pot .


これを元に、各言語用のメッセージカタログを作成

以下のコマンドで、プロジェクトルートのtranslations以下に、messages.poという名前で作成される。

pybabel init -i messages.pot -d translations -l ja
pybabel init -i messages.pot -d translations -l en

ここでは日本語と英語。

出来上がったmessages.poの該当箇所に、翻訳文を書いていく。

msgidが先のID、msgstrが翻訳文。

上述したテンプレートの書き方だと、カットアンドペーストの作業となる。

文章が長すぎてキーワードに絞ったところも、enのmessages.poに本文を翻訳文として書いておく。
それ以外はそのままでいい。

抽出したけどIDが良くないというケースがある。

その場合、poファイルの先頭辺りと、該当箇所に、#, fuzzyとかそんなマークが付く。

こういうのが出たら、テンプレートを書き直し、各messages.poを書き直し、fuzzyマークを削除し、

pybabel update -i messages.pot -d translations

再抽出したほうが正確かも。この辺、よくわからない。

とにかく出来上がったら

pybabel compile -d translations

で、コンパイルする。fuzzyが全部調整されてればskipなしで成功してmessages.moというファイルが出来る。


そのまんまgaeにデプロイして、ブラウザの言語をenにしたりjaにしたりして確認。


参考

[tombloo][study] tomblooで学習。15秒後に復習するために。

ちょっとした小ネタ。

15秒で訓練なしにできる記憶力を倍増させる方法 読書猿Classic: between / beyond readersによると、記憶学習は、記銘作業後、15秒空けて、モダリティーを換えて復習すると、定着しやすいらしい。

一方、僕は最近は、オンラインの英語辞書として、英和辞典・和英辞典 - Weblio辞書を使ってる。

発音の音声や、テクニカルタームの辞書なんかも同時に検索表示されたり、登録すると、マイ単語帳という学習用の単語登録機能なんかが使えて便利。

で、要は、weblioで覚えたい単語を、先の方式に従って、手軽に、15秒後に復習するためのtomblooのパッチを作ってみた。

weblioの単語表示ページ(studyの意味 - 英和辞典 Weblio辞書)で、コンテキストメニューTomblooのところの「studyWeblio15」を選択。

さっさとページを閉じて、次の作業にかかる。いや、ぼうっとしてたほうがいいのかな?

とにかく、そうすると15秒後にダイアログがポップアップする。

その入力ボックスに先程学習した英単語を打ち込む。

合ってれば、そのまま終わり。

間違ってれば、その英単語のページが再び読み込まれる。


っていうだけのもの。


[devel][cygwin][gauche] ビルドエラー

とりあえずメモ
cygwinGauche-0.9をtarボールからビルド。

エラー。

Creating library file: .libs/libgc.dll.a
.libs/win32_threads.o:win32_threads.c:(.text+0x5fe): undefined reference to `_GC_get_max_thread_index'
collect2: ld returned 1 exit status
Makefile:711: recipe for target `libgc.la' failed
make[2]: *** [libgc.la] Error 1

なんでそんなことを?
0.9.2をビルドしようとしたら失敗したので、出来てるとこから積み上げようと思った。

cygwinを一から入れなおすか、mingw版を使うか。