2011-11-29

ちょっとひどすぎだろこれ?

橋下知事が高校生をフルボッコwwwwwww
上記のサイトにあった動画を見た。ひどすぎというのは知事ではなくて、高校生の方。
討論になってない。というか嘆願にすらなってない。

というだけでは自分も同類なので、まずは自分がどちら側か。もちろん知事側。
理由、僕は大学受験の際に不景気のあおりで傾きかけていた親の事業のため、母親から「お前だけは国公立に行ってくれ」と言われたので。
この高校生たちに言いたいこと。中学のときに勉強しなかったの?それとも別の理由で私学に行ったの?学力が優秀なら奨学金制度もあると思うけど、それは活用しないの?etc.

と、これだけだと面白くないので、高校生側からなんとか議論に持っていけないかとも考えてみた。
大阪の受験事情を知らないので、僕が高校受験をした際の愛知の事情で。
愛知県は当時A日程、B日程と分かれていて、もちろん両方受けることができる。ただ、進学校を狙って両方とも自分のレベルより少し高い高校を受けた際に、両方とも落ちるということはままある。この辺僕は割りと問題だなぁと思っていて、どうしても滑り止めとして私学を受ける必要があった。(もちろん中学浪人という選択肢もあるはあるが)
僕ならそこを切り口にして、
  • 将来的に○○を専攻したいと思い、その分野に力を入れている公立の進学校を狙ったが、不甲斐なくも両方落ちた
  • 母子家庭で母親の収入だけでは厳しいのを知っていたが、進学校の私立に自分もバイトをして学費を稼ぐからと無理をいって入学
  • そうは言ってもそれだけでは厳しいし、バイトばかりして学業がおろそかになるのも本末転倒なので、補助金も学費の足しにしていた
  • 奨学金は大学の入学費等に当てるため貯金している
という路線で補助金の必要な環境にいることをアピールして、例えば学業の優秀な人には補助金を出して教育に力を入れるよう促すかね。
でも、単に補助金の減額だった上記のようなのは考慮に入ってるかもしれない。全額カットだと議論に余地ありかもしれない。問題は、そこまで考えている高校生には見えなかったのと、話の内容から箸にも棒にも引っかからない成績だったので私学に行ったように見えたので、話に信憑性がでないことか。

2011-11-28

頓珍漢なコメントをしてしまった

えぇ、正直浮かれてました。

事の発端はこちらのブログ
R7RS実装のポイント(改) - .mjtの日記復帰計画
なぜ浮かれたか、Sagittariusの名前が載ってたから。
っで、キーワードのことについて触れてたので、頑張ればポータブルに書ける旨をコメントしたのだが、3回くらい記事を読み返しておかしいことに気づいた。
(コメントを消す機能はないみたいなので、頓珍漢なコメントはインターネットに残り続ける・・・orz)
多分、R6RS処理系全体でポータブルなR7RSのライブラリを書くということなんだと思う。(国語苦手だったんです)
もしそうなら、こんな超マイナー処理系まで考慮に入れていただいて大変ありがたいです。moshを散々disってすいません。でも、moshには負けません(何の勝負?)

こんなとこ読んでないとは思うけど、一応言い訳・・・

2011-11-27

トヨタ「ハチロク」

こんな記事を見つけた
トヨタ「ハチロク」復活へ…来春に200万円台
200万円台といわれると、僕のRX-8(日本にある。売られる前に引き取らねば!)と一緒だわね。まぁ、前半か後半かで大分違うが。(僕のは240万台だったかな?そこから20万値引きがあったけど、諸費用が結構かかった記憶。ブログのどこかに書いたか?)
正直、トヨタがそう好きではないというのを差し引いても、あまり魅力を感じないなぁと思ってしまった。水平対抗なエンジンがいいっていうなら、スバルのインプレッサを買えばいいわけだし、イニシャルDを読んでない20代の若者はハチロクって言われても「何それ?」だろう。
スポーツカー好きな僕としてはメーカーがスポーツカーを作るというのは非常に好ましい状況なのだが、これはどの層をターゲットにしてるのかわからないなぁ。(RX-8のときは4ドアスポーツカーで、多分30代の家族持ちでスポーツカーにもう一度乗りたいという人だったのだろうと思う)
正直今のご時世で2ドアスポーツに200万以上払う人がいるだろうか?マツダのロードスターみたいな「車好きに!」みたいなコンセプトならまだしも、そうは見えないしなぁ。

この辺の意見を見ると、賛否両論だなぁ。まぁ、元が2chなので微妙ではあるが。
下の方みたら、ベースで250万になるとかのレスがある。本当なら正直RX-8より魅力が低いのに価格が上という糞仕様になるなぁ。(多少RX-8贔屓過ぎるか?ロータリーエンジン可愛いよロータリーエンジン)

日本のIT企業とオランダのIT企業の比較

slashdot.jpにこんなのがあった。
日本人プログラマーについての記事が Hacker News で話題になった
元ネタはこっち(英語)
Force Multipliers and Japanese Programmers

要約すると、日本企業は新しいフレームワークを使うことを極端に嫌がるため、生産性を落としているというものだ。
僕が日本のIT企業で働いた経験は(多く見積もっても)4年半なのであまり本質を捉え切れてないかもしれないが、大まかにそうだなぁと思うところが多々あった。スラッシュドットのコメント蘭は特に的を射ていた感がある。
それにプラスしてではないが、自分が感じたオランダ企業との比較をちょっと書いてみようと思う。一つしか知らないのであまり参考にはならないが。

納期を極端に重要視する
日本で働いていた際にどう考えても無理だろうという納期があったが、いわゆるデスマでなんとかした経験がある。その際にプロジェクトマネージャーに「どう考えても間に合わない再スケジュールしてくれ」と頼んだのだが、答えは当然「無理!」だった。
逆にオランダではその辺は割りと柔軟でこちらからあらかじめアラートを挙げると、優先順位の付け直しをしてクライアントとスケジュール調整をしてくれる。

自社製のフレームワークに極端にこだわる
まぁ、これは上記のブログでも言及されていたが、日本では割と元請けのフレームワークの使用を強制される。そのフレームワークが「実際に生産性を向上させるもの」ならいいのだが、4年半(開発者としては2年半)の間にそのような優れたものを見たことがない。おおよそ、「素直にhibernate使えよ」とか(当時なら)「素直にstruts使えよ」というようなものが主だった。個人的にこれらのフレームワークが好きではないのだが(特にspring)、確かに車輪の再開発をする必要がないのでビジネスロジックに集中できる。また、一度これらのフレームワークを習得してしまえば別のプロジェクトでも使えるので習得期間という初期コストを抑えられる。でも、○○社謹製△△フレームワークなんての物の習得がプロジェクト毎に入るんだよね。大抵上記のフレームワークの劣化版かつAPI互換性なしで。まぁ、その期間なにもしなくても金が入るから偽装派遣屋さんには美味しいかもしれないけど。

ユニットテストの概念がない、その為リファクタリングが非常に困難
この辺は今はよく知らないけど、僕が働いていたときはテストといえばテストケースの仕様書があって、人間が手でデータを揃えて都度エビデンスの作成。仕様変更もしくは不具合修正があればやり直し。これが結合テストですらなく単体テストレベルだったから涙が出そうだった。
(じゃあ今テスト駆動でやってるかといえばそうでもないのだが・・・)

PG->SE->PM以外のキャリアパスがない
個人的にはこれは結構問題だと思ってて、それぞれ全然違うものなのにあたかも順当なキャリアパスのように扱っている。例えば日本の求人を見ると、「PG->SEへと着実なスキルアップ」なんて殺し文句をそれこそほぼすべてのSIerの求人でみる。SEというポジションが最早なんなのか分からなくなったけど、SEの先にPMがあるなら、PG->PMになるはずだ。PMってプロジェクトマネージャの略なのでスケジュール管理とクライアントとのミーティングがメインタスクになる。
そうなりたいならいいけど、プログラマからそこに行く道って、大工が保険の営業になるくらい違うと思うのだが、どうしてそれがデフォルトなんだろう?(理由は次の問題で)

PMが最も単価の高い高級職
上も問題の答えだと思う。企業は単価の高い人間を売りたい(IT企業の多くが2次請け=人売りだと仮定)ので、単価の安いPGよりも単価の高いSE、PMを元請けに売りたいわけだ。
でも、これってすごく間違っていて、技術の高いプログラマが育たない、もしくは育っても開発に携わらないということになる。
これはモチベーションの問題だが、PGの単価が安いってことは、がんばっても給料安いのでやる気もでんわね。

思い出せただけでこれだけか。そもそも、文学部出身がPGになるってので間違ってる気がするけど。如何にIT業界(SIerか?)の求める人材がコミュニケーションスキルに偏ってるか分かるところか。

2011-11-24

疎な配列(Sparse Array)

あんまりこれについて書かれてる記事がなかったので書いてみる。
(MathematicaにマニュアルがGoogleでトップにヒットするんだもん)

事の発端
RE2のソースを読んでて、SparseArrayなる入れ物があるのを発見。Sparse Arrayとは何ぞやと思い調べてみた。

分かったこと
タイトル通り、訳としては「疎な配列」。意味は配列自体は巨大なんだけど中身はすっからかんな配列。(実装が腐ってるとそうなる)
ハッシュマップと何が違うの?もともとは行列を扱うのに適したものだったらしい。なのですべての要素に初期値がある。(ハッシュマップにはない)
後、検索、挿入、削除などのアクセスが定数時間(O(1)ってこと?)。イテレーションにかかる時間がO(n)でnは要素数、配列のサイズではない。
普通の配列を使うより高速かつハッシュマップと違ってリサイズの心配がない。(動的な配列ではないた。、実装によると思うが)


何がハッシュマップに比べてよさげか
あくまで配列なので、ハッシュの計算をする必要がない。(RE2のSparseArrayはそうなってる)
RE2の実装ではイテレータはインデックスと値のpairを返す。(多分そうやってO(n)のイテレーションを実現してるのだろう、for(int i = 0; i < size; i++)とは書けないということだね)
リハッシュの心配がないので、メモリの見積もりが聞く。


何が単なる配列よりよさげか
総アクセス時間が要素数に対しての線形になる。(配列のサイズじゃない)

自前で実装するほどのメリットが今のところ見当たらない。結局メモリの節約になるわけでもないし。
あ、まてよ、RE1もRE2もコンパイルされた正規表現のインストラクションの数だけ配列つくってるなぁ。10000以上になってきたらさすがに総アクセス時間がパフォーマンスに影響を与えそうだ。
とりあえず、配列アクセス用のマクロ書いて、パフォーマンスチューニングの段階になったら考えるか。(こういうときC++だとtemplateが使えると便利だよなぁ・・・)

2011-11-23

Inlinable marking

On Sagittarius Scheme, as I wrote before (in Japanese) it has mechanism to inline non exported small procedure and seems constant variable implicitly. Well, it sounds really good, it does optimise like GCC's static functions or static const variables.
However, if it marks wrong way, there is problems. I have introduced define-constant syntax and implicit inliner for non exported constant value since version 0.2.2. The latter one had the problem. The compiler marks some variable which should not be inlinable as inlinable. Let me show my embarrassing staff:
(library (test)
   (export test)
   (import (rnrs))

  (define *inner-value* #f)
  (define *inner-value2* #f)

  (define (test)
    (and (begin (set! *inner-value* #t))
         (begin (set! *inner-value2* '())))
    (display *inner-value*)(display *inner-value2*)(newline))
)
In this case, (I actually did not check if it does mark wrongly or not) *inner-value2* will be marked as inlinable, so the compiler inline it as #f. This is the problem. As you can see, it has to be '().
Inlinable marking is written as conservative as possible. Well, actually it wasn't ...

I was too lazy to open an issue for this on Google code, so I just fixed it.

2011-11-22

俺もアメリカに行くよ

mixiのマイミクが書いた日記の標題をそのままパクリ。
そのままです、アメリカに行きます。3泊4日で。今回はLAです。

期間は11月30日から12月3日まで。何が偶然かと言えば、マイミクは誕生日をアメリカで過ごしたが、どうやら僕もそうなりそうだ。節目の年(と多くの人が考える年齢になる日)をアメリカで過ごすのは何かの暗示だろうか。
まぁ、いろいろ事がうまく(なのか拙くなのか正直自分でも分からん・・・)進むといろんな意味で節目になるだろうなぁとは思っているのだが。

ところで、誰かLAでお勧めがあったら教えて。正直右も左も分からん。
といっても、あんまり身動きが取れる時間がないので手早くいけるお勧めの場所、レストランなどがあるといいなぁ。

2011-11-20

ロードマップを考えてみた

今後のリリースでSagittarius Schemeがどのようになるのかというのを考えてみた。
たいした物ではないし、0.3.0までしか考えてない。
version 0.2.3
  • 組み込み文字セット(完)
  • 正規表現ライブラリの書き直し(in Progress)
    • cl-ppcreの移植
version 0.2.4
  • リーダーマクロの導入
    • 【動機】正規表現を#/regex/と書きたい!
version 0.3.0
  • Tiny CLOSをベースにした組み込みCLOSの導入
    • 【動機】総称関数がほしくなる場面が多々ある
    • 【動機】現状、レコードと公開していない構造体が混在しているのですっきりさせたい
  • 上記をベースにしたレコードの実装
  • (可能なら)VCでの文字列をC++11仕様のU"string"に変更
    • 文字列リテラルをutf-32(ucs4)に統一
    • VCでのコンパイルはCではなくC++になるかもしれない
思ったとおりたいしたものではなかった。もちろんバグフィックスは随時だし、簡単にできそうかつ効果的だなぁと思ったものは実装していくと思う。
なので0.3.0が0.2.4の直ぐ後に来るとは限らないわけだが。(ただCLOSを組み込みにするとなると、結構な修正が入るので、無暗に修正範囲を広げることはしたくないので、多分0.2.4の後は0.3.0になると思うが。もしくはリーダーマクロを0.3.1に回すかもしれないが)
リーダーマクロは実装の目安がある程度あって、試してみたいなぁというのがある。これも内部的に結構いじくることにはなるので、(主にリーダー周りだが)どこで入れようかは実際迷い中。

独自実装を入れすぎだろか?
まぁ、Mostly R6RSと謳っているので問題ないか。ユーザー数1(僕)だし。

2011-11-16

正規表現ライブラリを書き直そう

組み込みの文字セットが完了したので、いよいよ本丸に取り掛かろう。
現在SagittariusではJavaから移植した正規表現を使っている。別にこれで問題はないと言えばないのだが、気になるのはその中で独自のASTを持っていること。
せっかくSchemeなんだしS式でASTを構築したほうがいいんじゃね?とちょっと思えてきた。
なぜそう思ったか?
世の中にはPCREとSREという正規表現のタイプがあるらしい。まぁ、もっとあるだろうが。っで、PCREは超有名なPerlの正規表現。SREはS式で書かれた正規表現らしい。Perl形式の正規表現をSREに置き換えて、ってやれば、PCREもSREも使えて一粒で2度おいしい感じがする。
と、こういうことをやっているのが、irregexというAlex Shinn氏が書いてるScheme用の正規表現ライブラリなわけだ。とりあえず、それを足がかりに文字列->SREなものを作って、ごにょごにょするか、もう少し資料をあさってみるか。(鬼車のソースを眺めてみるのもありか)

2011-11-15

Scheme使いのためのClojure入門

なんてタイトルをつけてみた。別にたいしたことをするわけでもなく、単に文法上の比較というかなんというか。
とりあえず、Clojureを触ってみた感想ではある。
;; 定義
(define hello
 (lambda (name) (string-append "hello, " name)))
;; or
(define (hello2 name)
 (string-append "hello, " name))
;; 定義
(def hello (fn [name] (str "hello, " name)))
;; or
(defn hello2 [name] (str "hello, " name))
特に何も書く必要はないだろうというくらいよく似ている。[]は引数だけど、ベクターのリードマクロでもある。
うわさによるとdefnは構文ではなくマクロだそうだ。 あと、defnはデフォルトでSchemeでいうcase-lambda仕様になっている。
;; 名前付let
(define (factorial n)
  (let loop ((cnt n)
            (acc 1))
    (if (zero? cnt)
        acc
        (loop (- cnt 1) (* acc cnt)))))
;; 名前付let
;; なんてものはないのでloopとrecurを使う
(defn factorial [n]
  (loop [cnt n acc 1]
    (if (zero? cnt)
      acc
      (recur (dec cnt) (* acc cnt)))))
loop構文は多分letのバインド方式だと思う。Clojureではletは括弧が一つでよくて、順に変数名、初期値、以下続くという感じになる。Schemeに慣れているとちょっと混乱しそうになる。
とりあえずこれくらいにしてしまう。本家サイトにドキュメントあるので、興味があればどうぞ。

それはおかしいだろ

マジで言ってるなら人間性を疑うレベルだが。
https://twitter.com/#!/YANA1945/status/136027550081220608
今日の面接。「もし給料が支払われなかったらどうする?」私が必ず訊く質問だ。目をキラキラさせて「構いません!」と叫ぶ人は合格。少しでも戸惑う奴。そんな奴とはプライベートでも口を聞きたくない!さっさと立ち去れ!
「論外ですね」が僕の答えになるだろうなぁ。もしくは何も言わずに立ち去るか。
叫んだ人は奴隷根性丸出しと批判してもいいかもしれない。
業績不振で遅延支払いになるとかだったらまぁ、「理由しだいでは理解します」になるかもしれない。実際、今の会社は今年のベースアップはなしと言われたし、理由もまぁしょうがないかというものだった。
支払われないということは、雇用契約の反故を通り越して「死ね」と言われているのとほぼ同義だと思うので、奴隷なら雇用者の都合で死ねという理念が無ければこの質問は出ないはずだ。

もともとは、
Island Life - 釣りくさいけど
で見つけたものなのだが(べ、別にShiroさんの隠れファンなんかじゃないんだからね!)、豪快に1本釣りされたのかもしれない。
でも、このエントリの追記にツイートした人は面接代行業者とあったので、割とマジなんだろう。整合性も確かにある。
っが、お前同じこと言われたら目をキラキラさせて「構いません!」と叫ぶんだろうな?と問い詰めてやりたい。他のツイートもなんだかキ○ガイじみてるものだったし、まぁ、根性論で走る人なんだろう。
可能な限りお近づきになりたくないタイプの人種だ。

2011-11-14

赤黒木(続)

結局LLRBではなく純正赤黒木を作ることにした。というかJavaのTreeMapの実装をそのまま移植したともいう。
テストができてないが、とりあえずいいだろう。

一つ前の記事で、メモリ効率と書いたが、よく考えればそんなものどうでもよくて、重要な点は順序があることだった。実装してて気づいた。馬鹿か俺は(カカシ風)
この赤黒木はSchemeのAPIにもするつもりではあるが、元々は組み込みの文字セットを実装するためのものである。なので、ハッシュテーブルのようにオーダーがなくなるようなものではなく、データの挿入時にオーダーが保たれるものじゃないと困るわけだ。(範囲等の関係で)

正直赤黒木の中身がどうなっているのかいまいち理解してないが、(2-3-4木を二分木で表現したものということくらいしか・・・)、単に使うだけなら問題あるまい。問題が出たら直せばいいわけだし。
木の回転とバランスが命だということは実装(コピー)してて気づいたが・・・

2011-11-12

赤黒木

(後々の正規表現ライブラリ改善のため)組み込みの文字セットを入れようと考えているのだが、ハッシュテーブルをセットとしてもつより、平衡二分木を持った方がメモリ効率的にいいかなぁと思い、赤黒木を調べ中。(長い)

調べてみると、実装が難儀とあって、LLRBなるものを発見。Javaで200行程度で実装できるらしい。とりあえずこいつを実装して、後から実装を変更するのもありか。
となると、他の二分木も実装(AVL木とか)も試してみたくなるよなぁと思うのが人間で、そうするとインターフェースだけ定義して実装は別にしたい。何を持つべきだろう?
正直、どこまでやるかということになるが、一応Schemeからも実装できるようにしたいなぁと思うと以下のようになるだろうか?
typedef struct tree_map_rec
{
  int type; /* CかSchemeか*/
  union {
    struct {
      int (*insert)(struct tree_map_rec *tree, node_t *node);
      /* so on */
    } c_procs;
    struct {
      /* scheme procs on C object*/
    } scheme_procs;
  } impl;
} tree_map;
問題になりそうなのはnode_tの定義か?まぁ、とりあえずintptr_tの別名にして、実装毎に適当に定義してキャストすればOKだろうか?
あとは、実装ごとにイテレータをどう用意するかとかその辺を煮詰めないとなぁ。この辺C++だともう少し簡単に書けそうだよなぁ。ABIの問題さえなければ・・・

2011-11-11

1年前のネタを拾った

ボーっとどう書く的なネタを探していたら、こんなの発見。

Twitter / ばーるのようなもの: comp.lang.scheme で簡単なリスト操作 ...
comp.lang.scheme で簡単なリスト操作のお題が出ておるな。
っでやってみた。
(import (rnrs) (rnrs mutable-pairs))
(define (acons k v r) (cons (cons k v) r))
(define (process-labeled-list lst)
  (let loop ((lst lst)
      (ans '()))
    (if (null? lst)
 (map cdr (list-sort (lambda (p1 p2) (< (car p1) (car p2)))
       ans))
 (cond ((assv (caar lst) ans)
        => (lambda (slot)
      (set-cdr! slot (append (cdr slot) (cdar lst)))
      (loop (cdr lst) ans)))
       (else
        (loop (cdr lst) (acons (caar lst)
          (cdar lst)
          ans)))))))

(process-labeled-list '((0 a b) (1 c d) (2 e f) (3 g h) (1 i j)
   (2 k l) (4 m n) (2 o p) (4 q r) (5 s t)))
set-cdr!を使うのは卑怯だろうか?
副作用ありだとあんまり関数型っぽくはない気もするが。

他の処理系でも動かすために、aconsを再定義。Sagittariusならなくても動く。というか、import文すら無くてもこれくらいなら動く。

Version 0.2.2リリース

1日寝かせたら不具合を発見したのでそれを直してのリリース。

今回のリリースではコンパイラがさらに定数畳み込みを行うようになりました。また、定数畳み込みを補助する構文としてdefine-constantが正式にサポートされました。
またビルドの際に必要なライブラリがプラットフォームにインストールされていなかった場合、自動的にダウンロードするように改善されました。 ただし、MSVC環境以外ではテストがあまり行われていません。

修正された不具合
  • get-bytevector-n!でcountパラメータがバイトベクターのサイズだった再に&assertionが投げられる不具合が修正されました。
  • Windows版のmake-transcoderがEOLスタイルをlfとして作成する不具合が修正されました。
  • ライブラリのrenameインポートの際に、renameされたものだけをインポートする不具合が修正されました。
  • let*-valuesの右辺値に左辺値が含まれている際にコンパイラがエラーを報告する不具合が修正されました。
  • delete-fileの挙動がR6RSのものと異なっていた不具合が修正されました。
  • ライブラリ内インライン化の際にコンパイラが誤ってインライン可能フラグをつけていた不具合が修正されました。
  •  カスタムポートでclose引数を指定しても呼ばれていなかった不具合が修正されました。
変更された機能
  • パターンマッチライブラリ(match)がAndrew Wright氏のものからAlex Shinn氏のものに変更されました。
  • current-directoryがパラメータ化されました。(current-directory "somewhere")で(set-current-directory "somewhere")と同様の働きをします。これによって(srfi :39)にあるparameterizeとの親和性があがりました。
  • ソケットライブラリ(sagittarius socket)からエクスポートされていた定数が、define-constantで定義されたものと同様の振る舞いをするように変更されました。
新たに追加された機能
  • Zlib圧縮ライブラリ(rfc zlib)が新たに追加されました。
  • プログラム引数処理ライブラリ(srfi :37)が新たにサポートされました。
  • ハッシュテーブルユーティリティ(util hashtables)が新たに追加されました。


個人的に割りといい感じになってきた感がある。正規表現でクラスのサポートをするために文字セットを組み込みにしないと。

2011-11-10

定数畳み込み

コンパイラの最適化をもう一歩進めてみた。
実は以前から構文としてはdefine-constantをサポートしてはいたんだけど、何もしない単なるサポートにしかなっていなかった。
っで、せっかくライブラリのインライン化とかやったので定数も畳み込んでしまおうと思い立ってやってみた。

基本方針は以下の通り。
  • 定数のみ。
  • exportで定義されていない。
  • コンパイラの最適化で定数になるものは含める。例えばこんなの
    (define a (car '(a b c))) ;; コンパイラは'aをaに定義する。
  • define-constantで定義されたものはライブラリ外でも参照する
とりあえず、なんとなく動くようになったっぽい。以下のコードでは定数が畳み込まれていることが確認できた。
(define-constant a (car '(a b c))) ;; carはコンパイル時に計算される(可能なら)

(define (test)
  (print a))
(disasm test)
;; size: 5
;; 0: CONST_PUSH a <-- シンボルaがそのまま渡されている
;; 2: GREF_TAIL_CALL(1) #<identifier print#user(0x5fd1e0)> ;; print
;; 4: RET

(library (inner)
    (export const-value)
    ;; define-constant は(sagittarius)ライブラリにて提供
    (import (sagittarius))
  (define-constant const-value 10)
)

(library (test)
    (export test2)
    (import (rnrs)
     (inner))

  (define a (+ 1 2 3)) ;; a はexportされていない

  (define (test2)
    (display a)
    (display const-value)
    (newline))
)

(import (test))
(disasm test2) 
;; size: 13
;; 0: FRAME 4
;; 2: CONSTI_PUSH(6) <-- 計算された後の定数になっている
;; 3: GREF_CALL(1) #<identifier display#|(test)|(0x73d018)> ;; display
;; 5: FRAME 4
;; 7: CONSTI_PUSH(10) <-- GREF const-valueではない
;; 8: GREF_CALL(1) #<identifier display#|(test)|(0x73efa8)> ;; display
;; 10: GREF_TAIL_CALL(0) #<identifier newline#|(test)|(0x73ef30)> ;; newline
;; 12: RET
ま、まずまずでしょう。Gambitのベンチマークにはなんら影響が出ないところが多少以上に悲しいが。(あれらはR6RSのライブラリを使ってないから、最適化がかからん)
もう少し寝かせてから0.2.2をリリースしよう。

2011-11-09

割と大きめな岐路

このサイズの岐路は3度目なのだが、2度あることはじゃないけど、3度目がきたわけだ。
(まだ、不確かな要素が多いので、歯に衣を着せた物言いだったり)

正直迷ってはいたりするのだが、さてどうしたものか。別に今の位置にそう固執しているわけではないのだが、割と気に入っていたりはするので、迷うわけだ。
う~ん、どうしたものだろう。

2011-11-02

ドキュメント

オープンオフィス(以下OOo) をやめて、RacketのScribbleに乗り換え中。
乗換えと言っても、Racketに付属しているものをそのまま使うのではなく、ドキュメント生成スクリプトも同時に書いている。なので、コンセプトだけを使うといった感じ。
Chibi Schemeに触発された感はあるが。

その際にあんまりうまいこと解決方法が見つからなかったのが以下のセクションを拾って目次に変換する処理。
用件としては、以下のようになっているリストをulとliで作成されたsxmlに変換すること。
((section
  (@ (tag "tag1") (number "1"))
  "Section 1")
 (subsection 
  (@ (tag "tag1.1") (number "1.1"))
  "Subsection 1.1")
 (subsection 
  (@ (tag "tag1.2") (number "1.2"))
  "Subsection 1.2")
 (section
  (@ (tag "tag2") (number "2"))
  "Section 2")
 (subsection 
  (@ (tag "tag2.1") (number "2.1"))
  "Subsection 2.1")
 (subsubsection 
  (@ (tag "tag2.1.1") (number "2.1.1"))
  "Subsection 2.1.1")
 (sub*section 
  (@ (tag "tag2.1.1.1") (number "2.1.1.1"))
  "Subsection 2.1.1.1")
 (section
  (@ (tag "tag3") (number "3"))
  "Section 3"))
期待される出力
(div (@ (id "G137") (class "table-of-contents"))
     (ul (@ (class "section"))
  (li (@ (class "section"))
      (a (@ (href "#tag1"))
  (span (@ (class "section-number")) "1")
  "Section 1")
      (ul (@ (class "sub-section"))
   (li (@ (class "sub-section"))
       (a (@ (href "#tag1.1"))
   (span (@ (class "section-number")) "1.1")
   "Section 1.1"))
   (li (@ (class "sub-section"))
       (a (@ (href "#tag1.2"))
   (span (@ (class "section-number")) "1.2")
   "Section 1.2"))))
  (li (@ (class "section"))
      (a (@ (href "#tag2"))
  (span (@ (class "section-number")) "2")
  "Section 2")
      (ul (@ (class "sub-section"))
   (li (@ (class "sub-section"))
       (a (@ (href "#tag2.1"))
   (span (@ (class "section-number")) "2.1")
   "Section 2.1")
       (ul (@ (class "sub-sub-section"))
    (li (@ (class "sub-sub-section"))
        (a (@ (href "#tag2.1.1"))
    (span (@ (class "section-number"))
          "2.1.1")
    "Section 2.1.1")
        (ul (@ (class "sub-sub-sub-section"))
     (li (@ (class "sub-sub-sub-section"))
         (a (@ (href "#tag2.1.1.1"))
     (span (@ (class "section-number"))
           "2.1.1.1")
     "Section 2.1.1.1"))))))))
  (li (@ (class "section"))
      (a (@ (href "#tag3"))
  (span (@ (class "section-number")) "3")
  "Section 3"))))
単にulとliで構成されたリストにちょっとしたhtmlのメタ情報が入ったものといった感じ。これが結構てこずった。
最終的にはこんな風になったけど、もうちょっといい感じにならないだろうか?
;; sxml toolsをふんだんに使ってます。
(define *section-classes*
  '((section       . "section")
    (subsection    . "sub-section")
    (subsubsection . "sub-sub-section")
    (sub*section   . "sub-sub-sub-section")))

(define (content-list-handler element)
  (define (process contents)
    (define (li-gen content class)
      (let* ((attrs (sxml:attr-list-node content))
      (tag   (cond ((assq 'tag attrs) => cadr)))
      (section (cond ((assq 'number attrs) => cadr)
       (else
        (assertion-violation 'li-gen
        "section is not defined" content)))))
 `((li (@ (class ,class))
       (a (@ (href ,(format "#~a" tag)))
   (span (@ (class "section-number")) ,section)
   ,@(map phase2/dispath (sxml:content content)))))))
    (define (ul-gen class)
      `(ul (@ (class ,class))))
    (define (rec contents generator top)
      (let loop ((contents contents)
   (r top))
 (if (null? contents)
     r
     (let ((content (car contents)))
       (let-values (((class depth) (generator content)))
  (let loop ((i 0)
      (r r))
    (if (= i depth)
        (cond ((and (zero? i) ;; top
      (eq? (car r) 'ul))
        (append! r (li-gen content class)))
       (else
        (let ((tail (car (list-tail r (- (length r) 1)))))
          (cond ((eq? (car tail) 'ul)
          (append! tail (li-gen content class))
          r)
         (else
          (let ((ul (ul-gen class)))
     (append! ul (li-gen content class))
     (if (eq? (car tail) 'li)
         (append! tail (list ul))
         (append! r (list ul)))
     r))))))
        (loop (+ i 1)
       (let((rr (car (list-tail r (- (length r) 1)))))
         (if (eq? (car rr) 'li)
      rr
      (car (list-tail rr (- (length rr) 1))))))))
  (loop (cdr contents) r))))))

    (define (section-generator element)
      (define len (length *section-classes*))
      (define sections (map car *section-classes*))
      (cond ((assq (car element) *section-classes*)
      => (lambda (slot)
    (let ((name (car slot))
   (class (cdr slot)))
      (values class (- len (length (memq name sections)))))))
     (else
      (assertion-violation 'section-generator
      "unknown tag" element))))
    ;; assume first one is section
    (rec contents section-generator (ul-gen "section")))

  (let* ((contents (*table-of-contents*))
  (attr (sxml:attr-list-node element))
  (id   (cond ((and attr (assq 'id attr)) => cadr)
       (else (symbol->string (gensym))))))
    `(div (@ (id ,id)
      (class "table-of-contents"))
   ,(process contents))
    )
  )
リストの作成を破壊的に行っているので、なんとなく反則技を使っている気分。いい点は、*section-classes*に追加のサブセクションを足せば簡単にネストできることか。4つ以上サブセクションが要るドキュメントなんて読みたくないが・・・