Island Life

2013/12/20

ピアノレッスン113回目

  • Kapustin: Concerto Etude Op40-1
    • 中間部のアドリブっぽいところ、速くすると単調になってしまうので "do something"。
  • Ravel: Ondine
    • 高音域でメロディと伴奏が重なるところで、伴奏にメロディが 埋もれがちになるので注意。

Tag: Piano

2013/12/14

ピアノレッスン112回目

また忙しくてひと月ぶりくらいになった。

  • Kapustin: Concerto Etude Op40-1
  • Ravel: Ondine

すこしづつ進歩はしてる模様。

Tag: Piano

2013/12/13

sqrtが遅かった話

https://twitter.com/tk_riple/status/411433966952923136

最初は環境がネストしてるからだと思ってフラットにしたんだけど変わらなかったので、多分Gaucheだとsqrtが遅いんだな。プロファイラ見てみると%sqrtの呼び出したがsqrtの呼び出しの倍くらいになってる。実装は知らない。

ヘロン三角形

gosh> (time (find-heron 100))
;(time (find-heron 100))
; real   1.011
; user   0.967
; sys    0.032
((100 100 56) (100 99 89) ...

norm> (time (find-heron 100))
((100 100 56) (100 99 89) ...
total 0.897 second
GC    0.0 second
#<undef>
norm> 

ああ、そうか。

sqrt は正確な正の平方数が与えられたら、正確な結果を返す (cf. Exact sqrt) のだけど、その計算を

  1. exact-integer-sqrt で正確な正の引数nに対し n = q*q + m (0 <= m < q) なる正確数q, mを計算
  2. mが0ならqが答え
  3. そうでなければnは正確数の平方数ではないので浮動小数点数にしてCのsqrtに投げる

としていた。これだと引数が有理数の平方数でない場合、 exact-integer-sqrt で一回平方根に近い正確値を計算し、 さらに3.でもう一度sqrtを計算するという二度手間をやってたことになる。

二度手間を避けるようにしたらこれこのとおり。

変更前

shiro@scherzo:~/src/Gauche/src$ ./gosh -ftest ../heron.scm
;(time (find-heron 100))
; real   0.722
; user   0.720
; sys    0.000

変更後

shiro@scherzo:~/src/Gauche/src$ ./gosh -ftest ../heron.scm
;(time (find-heron 100))
; real   0.617
; user   0.620
; sys    0.000

Tags: Programming, Gauche

2013/12/08

コンポジションに便利なpropagatedスロット

Metaobject Protocol(MOP) Advent Calendar 2013参加エントリ (12/9分)

GUI作っている時などによく出会うケースだけど、複数の関連するオブジェクトをまとめて ひとつのオブジェクトとして扱いたいことがある。例えばラベル、テキストボックス、 アイコンイメージを並べたものをひとつのウィジェットとして扱いたい、とか。

これはまあ普通にコンテナとなるクラスのサブクラスを作って 部品を配置し、必要な処理について委譲するメソッドを書いてやればいいんだけど、 GUIなんかだと「子ウィジェットのこのプロパティ(スロット)を合成した部品の プロパティとして見せたい」ってのが多い。上の例のウィジェットで テキストボックスのtextスロットを合成ウィジェットのtextスロットとして 参照させたい、等。

テキストボックス自体をスロットとして見せることで、(~ widget 'text-box 'text) というふうに多段で参照させる手もあるけど、必要以上に中身を見せている感じがして いまいち。(アクセスコントロールがデフォルトで備わっていないCLOSで 中身が見えるのを気にするのも妙な話ではあるけれど、 上のような多段アクセス法を公式なAPIにしてしまうと、後で実装を変えたくなった時に 面倒だったり、途中のオブジェクトへの参照を予想外のところで保持されて困ったりする。)

そんな時にpropagatedスロット。これは自分が内包しているオブジェクトのスロットを あたかも自分のスロットであるかのように見せるスロットオプションだ。 Gaucheでは gauche.mop.propagate モジュールで提供されている。 もともとSTkにあった機能を真似したものだ。 最低限の部分だけ示すとこんな感じ:

(use gauche.mop.propagate)

(define-class <text-box> ()
  ((text :init-keyword :text)))

(define-class <composited-widget> ()
  ((text-box :init-form (make <text-box>))
   (text     :allocation :propagated
             :propagate-to 'text-box
             :init-keyword :text))
  :metaclass <propagate-meta>)

<composited-widget>text スロットへの読み書きは、 text-box に保持された text スロットへの読み書きになる。 通常の方法で初期化もできるので、当初<text-box>を使っていたコードを 変えずにその部品だけ<composited-widget>にすげ替えることが できたりして便利。

gosh> (define cw (make <composited-widget> :text "abc"))
cw
gosh> (~ cw 'text)
"abc"
gosh> (~ cw 'text-box 'text) ; 確かに子ウィジェットに伝わってるか確認
"abc"
gosh> (set! (~ cw 'text) "def")
#<undef>
gosh> (~ cw 'text-box 'text) ; 確かに子ウィジェットに伝わってるか確認
"def"

さて、この機能もMOPで実現されている。 これまでの例と同じく、compute-get-n-set をオーバライドする。 allocation スロットオプションが :propagated なら 自前で作ったアクセサ手続きを返し、そうでなければnext-methodを呼んで デフォルトの振る舞いに任せる。 (matchの二番目の節は、子スロットの名前と違う名前を親スロットで定義したい場合の処理)。

(define-method compute-get-n-set ((class <propagate-meta>) slot)
  (let ([name  (slot-definition-name slot)]
        [alloc (slot-definition-allocation slot)])
    (if (eq? alloc :propagated)
      (match (or (slot-definition-option slot :propagate #f)
                 (slot-definition-option slot :propagate-to #f))
        [(? symbol? prop)
         `(,(^o (slot-ref (slot-ref-using-class class o prop) name))
           ,(^(o v) (slot-set! (slot-ref-using-class class o prop) name v))
           ,(^o (slot-bound? (slot-ref-using-class class o prop) name))
           #t)]
        [((? symbol? object-slot) (? symbol? real-slot))
         `(,(^o (slot-ref (slot-ref-using-class class o object-slot)
                          real-slot))
           ,(^(o v) (slot-set! (slot-ref-using-class class o object-slot)
                               real-slot v))
           ,(^o (slot-bound? (slot-ref-using-class class o object-slot)
                             real-slot))
           #t)]
        [other
         (errorf "bad :propagated slot option value ~s for slot ~s of class ~s"
                 other name class)])
      (next-method))))

compute-get-n-set が返しているのは4要素のリストで、各要素の意味は

  1. スロットを読む時に呼ばれる手続き
  2. スロットに書く時に呼ばれる手続き
  3. スロットが値を持っているかどうかをチェックする時に呼ばれる手続き
  4. このスロットが初期化引数で初期化されるかどうかのフラグ

となっている。詳しくはrefj:compute-get-n-set参照。

Tags: Programming, Gauche, MOP

2013/12/07

潜水母艦伊400

第二次大戦中に建造され、戦後に米軍によって沈められた巨大潜水艦伊400が ハワイ沖で見つかったというニュースが流れていた。

同型艦の伊401が数年前に見つかっていて、 ナショナルジオグラフィックが特集番組を組んだことがある。 いま検索してみたらwebで見られるようになってた。

パイロット役でちらっとだけ出演してる。14分過ぎくらい。(撮影は本物の潜水艦で行った。うんと小さいやつだけど。)

(追記2013/12/09 10:57:24 UTC):「潜水母艦」ってどっかの報道で目にした気がしたんだけど、 どうも「潜水艦をデプロイする艦船」という意味らしい。航空母艦が飛行機飛ばすんだから そりゃそうか。伊400系は「航空機をデプロイできる潜水艦」だけどそれを指す 用語は無いのかな。

★ ★ ★

しかし自分のように自慢ビリティがモチベーションになってる技術者にとっては、 軍用技術はやってられないな。自慢できないし、せっかく作っても壊される。 伊400系だって戦争を生き抜いたのに技術の漏洩を恐れて沈められたというんだからたまらん。

別に自分の名を残したいとかそういうわけじゃなくて、自分の技術のミームが 広がって、それが別の技術を産み出して加速度的に世の中がおもしろくなってゆくっていうのが いいんだよね。

囲い込んじゃうと、積み上げるのではなく、似たようなことをあちこちでやる羽目になって、 人類全体として効率が悪い。

軍用用途が技術を進めてきた、って歴史はあるけれど、 それって単に他の全てに優先してリソースが割かれたからで、 同じだけリソースを回せる条件ならオープンでやった方が進歩は速いんじゃないかな。

Tag: 芝居

More entries ...