`(Hello ,world)

ツッコミ、添削大歓迎です。いろいろ教えてください。

2008-03-30

Amazon.comでのSICPの評価

| 00:49

Amazon.comでのSICPのページを見たら、Peter Norvig 先生がベストレビューだった。本人かどうかわからないけどpaul grahamもレビューを書いている。他にも有名人がいるかと見てみたけど、LokiAndrei Alexandrescuくらいしかわからなかった。

それにしても本当に星5個と1個ではっきりわかれてるな。1個の人は「退屈」とか『不親切」とかのコメントが多い。理解できないと評価もよくなりようがないよね。

Gauche-gd で図形言語

| 12:28

ImageMagickのインストールにつまづいてしまったので、gdを試してみた。無事にインストールできて、SICPの図形言語ができました。

f:id:mokehehe:20080330122615p:image

#!/usr/local/bin/gosh

(use graphics.gd)

(load "./pict-lang.scm")

;; gd interface

(define *im* #f)

(define (screen w h . rest)
  (let-optionals* rest ((r 255)
                        (g 255)
                        (b 255))
                  (set! *im* (gd-image-create w h))
                  (gd-image-color-transparent *im* (color r g b))
                  (gd-image-interlace *im* 1)))

(define (outimg)
  (current-gd-image-format (if (memq 'png *gd-features*) 'png 'gif))
  (write *im*))

(define (color r g b)
  (gd-image-color-allocate *im* r g b))

(define (line col x0 y0 x1 y1)
  (gd-image-line *im* x0 y0 x1 y1 col))


;; test painter

(define wave
  (let ((p01 (make-vect 0.42 1.00)) (p02 (make-vect 0.58 1.00))
        (p03 (make-vect 0.00 0.80)) (p04 (make-vect 0.35 0.80))
        (p05 (make-vect 0.65 0.80)) (p06 (make-vect 0.00 0.60))
        (p07 (make-vect 0.30 0.60)) (p08 (make-vect 0.40 0.60))
        (p09 (make-vect 0.60 0.60)) (p10 (make-vect 0.70 0.60))
        (p11 (make-vect 0.20 0.55)) (p12 (make-vect 0.30 0.55))
        (p13 (make-vect 0.35 0.50)) (p14 (make-vect 0.65 0.50))
        (p15 (make-vect 0.20 0.45)) (p16 (make-vect 1.00 0.40))
        (p17 (make-vect 0.50 0.20)) (p18 (make-vect 1.00 0.20))
        (p19 (make-vect 0.25 0.00)) (p20 (make-vect 0.40 0.00))
        (p21 (make-vect 0.60 0.00)) (p22 (make-vect 0.75 0.00)))
    (segments->painter
      (list (make-segment p01 p04)
            (make-segment p04 p08)
            (make-segment p08 p07)
            (make-segment p07 p11)
            (make-segment p11 p03)
            (make-segment p06 p15)
            (make-segment p15 p12)
            (make-segment p12 p13)
            (make-segment p13 p19)
            (make-segment p20 p17)
            (make-segment p17 p21)
            (make-segment p22 p14)
            (make-segment p14 p18)
            (make-segment p16 p10)
            (make-segment p10 p09)
            (make-segment p09 p05)
            (make-segment p05 p02)))))

(define wave2 (beside wave (flip-vert wave)))
(define wave4 (below wave2 wave2))

(define (rotate4 painter)
  (let ((half (beside painter (rotate90 painter))))
    (below half (rotate180 half))))

(define (divide-x painter n)
  (if (> n 0)
      (let ((sub (divide-x painter (- n 1))))
        (below (beside (rotate270 sub) (rotate180 painter)) (beside painter (rotate90 sub))))
    painter))

(define test-painter
;  (square-limit wave 4)
;  (rotate4 (flip-vert (flip-horiz (corner-split wave 4))))
  (divide-x wave 5)
  )

(define-constant WIDTH  256)
(define-constant HEIGHT 256)

(define (draw-line v0 v1)
  (let ((x0 (floor->exact (xcor-vect v0)))
        (y0 (floor->exact (- HEIGHT (ycor-vect v0))))
        (x1 (floor->exact (xcor-vect v1)))
        (y1 (floor->exact (- HEIGHT (ycor-vect v1)))))
    (line (color 0 0 0) x0 y0 x1 y1)))

;; Entry point
(define (main args)
  (screen WIDTH HEIGHT)
  (let ((frame (make-frame
                (make-vect 0 0) (make-vect WIDTH 0) (make-vect 0 HEIGHT))))
    (test-painter frame))
  (outimg)
  0)

ImageMagick

09:42

SICPの図形言語がやりたくて、なにか画像処理のパッケージを使いたい。ImageMagickというのがいろいろできそうでよさげ。Gauche-bindingもある。

でやってみようとしたんだけど、インストールに失敗する。

$ ./auto
checking build system type... i686-pc-cygwin
checking host system type... i686-pc-cygwin
checking target system type... i686-pc-cygwin
checking for gosh... /usr/local/bin/gosh
checking for gauche-config... /usr/local/bin/gauche-config
checking for gauche-package... /usr/local/bin/gauche-package
checking for gauche-install... /usr/local/bin/gauche-install
checking for gauche-cesconv... /usr/local/bin/gauche-cesconv
checking for a BSD-compatible install... /usr/bin/install -c
configure: creating ./config.status
config.status: creating Makefile
config.status: executing im_head_n_tail commands
config.status: generating im_head.c and im_tail.c
gcc -g -O2 -I/usr/local/lib/gauche/0.8.12/include -fomit-frame-pointer -march=i686 -DUSE_I686_PREFETCH -fpic   -c -o im_head.o im_head.c
im_head.c:1: warning: -fpic ignored for target (all code is position independent)
gcc -g -O2 -I/usr/local/lib/gauche/0.8.12/include -fomit-frame-pointer -march=i686 -DUSE_I686_PREFETCH -fpic   -c -o im.o im.c
im.c:1: warning: -fpic ignored for target (all code is position independent)
im.c:121: error: initializer element is not constant
im.c:121: error: (near initialization for `Scm_ImageInfoClass.cpa')
im.c:173: error: initializer element is not constant
im.c:173: error: (near initialization for `Scm_ExceptionInfoClass.cpa')
im.c: In function `Scm_ExceptionInfoClass_reason_SET':
im.c:211: warning: assignment discards qualifiers from pointer target type
im.c: In function `Scm_ExceptionInfoClass_description_SET':
im.c:224: warning: assignment discards qualifiers from pointer target type
im.c: At top level:
im.c:282: error: initializer element is not constant
im.c:282: error: (near initialization for `Scm_ImageClass.cpa')
make: *** [im.o] Error 1

わからん。とりあえずCから使えるかテストする。

Cから使う

ImageMagick - MagickCore, Low-level C API

  • MagickCore-config がない→無視
gcc core.c -lmagick
  • リンクエラー
$ gcc core.c -lmagick
core.c:(.text+0x70): undefined reference to `_MagickCoreGenesis'
core.c:(.text+0x1d2): undefined reference to `_MagickCoreTerminus'
collect2: ld returned 1 exit status
Gaucheバインディングのインストールに失敗した行を見てみる
im.c:121: error: initializer element is not constant
im.c:121: error: (near initialization for `Scm_ImageInfoClass.cpa')
im.c:121: SCM_DEFINE_BUILTIN_CLASS(Scm_ImageInfoClass, NULL, NULL, NULL, NULL, SCM_CLASS_DEFAULT_CPL);
  • SCM_CLASS_DEFAULT_CPL の定義で、
SCM_EXTERN ScmClass *Scm_DefaultCPL[];
  • のSCM_EXTERN が、Cygwin だと
#  define SCM_EXTERN extern __declspec(dllimport)
  • となって、これが定数にはならないからだめぽい。
  • でもそれだとCygwinで拡張ライブラリが使えないことになっちゃうぞ?
  • 宣言時には CPA に NULL を与えておいて、実行時に値をセットするよう書き換え
// 宣言時
//SCM_DEFINE_BUILTIN_CLASS(Scm_ImageInfoClass, NULL, NULL, NULL, NULL, SCM_CLASS_DEFAULT_CPL);
SCM_DEFINE_BUILTIN_CLASS(Scm_ImageInfoClass, NULL, NULL, NULL, NULL, NULL);

// 初期化関数内
	Scm_ImageInfoClass.cpa = SCM_CLASS_DEFAULT_CPL;
  • リンクエラー
gcc  -Wl,--export-all-symbols -Wl,--enable-auto-import -shared -o  im.so im_head.o im.o im_tail.o im-lib.o -L/usr/local/lib/gauche/0.8.12/i686-pc-cygwin  -lgauche -lm  -lpthread  -lMagick
im.o: In function `im_im_write_image_to_uvector':
/cygdrive/c/temp/gauche-imagemagick-1.9/im.c:629: undefined reference to `_Scm_U8VectorClass'
/cygdrive/c/temp/gauche-imagemagick-1.9/im.c:629: undefined reference to `__imp__Scm_MakeUVectorFull'
im.o: In function `im_im_uvector_discard':
/cygdrive/c/temp/gauche-imagemagick-1.9/im.c:641: undefined reference to `_Scm_U8VectorClass'
collect2: ld returned 1 exit status
トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080330

2008-03-23

池袋ジュンク堂

23:09

久しぶりに下界に降りて、本屋と電気屋巡り。池袋のジュンク堂に行ったら、エスカレータでコンピュータ書籍売り場についたすぐの平積みコーナーに「プログラミングGauche」に始まって「入門Common-Lisp」に「On Lisp」、「ふつける」「入門Haskell」、海外のHaskell本2冊「Programming in Haskell」「The Haskell School of Expression」、Erlang本2冊「プログラミング言語Erlang入門」「プログラミングErlang」、さらには「SICP」まで。他にも多数、関数言語本がおもむろに置いてあった。かなりブーム来てるってことだな。おそろしす。

その中で「プログラミング言語の新潮流」という本を買ってきた。中身はラムダ計算、LispScheme、FP、Prolog、など。初版が1988年で相当古い本だけど、ラムダ計算についていろいろ書いてあったのでつい買ってしまった。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080323

2008-03-22

SICP第2章

| 07:00

2章を読み進めてるけど、あまり面白くない。1章は出てくる例がどれもビルディングブロックとして組みあがっていくのを強く感じてとてもわくわくしたんだけど、2章はSchemeの文法というか基本的な話が多くてそれほど面白くない。クロージャがデータ構造としても使えるってので面白い話が出てくるのではないかと期待しますが…。

Gambit-Cを使ってみる

23:15

  • cygwinでインストールできた。
  • インタラクティブモード gsi で、括弧の対応にカーソルがあってくれる!どうやってんの?
  • なんか動作が超速い(体感)。すげえ。
コンパイル
(define (twice x) (cons x x))
___DEF_SLBL(0,___L0_twice)
   ___IF_NARGS_EQ(1,___NOTHING)
   ___WRONG_NARGS(0,1,0,0)
___DEF_GLBL(___L_twice)
   ___IF(___EQP(___GLO(4,___G_cons),___PRM(4,___G_cons)))
   ___GOTO(___L3_twice)
   ___END_IF
   ___SET_R2(___R1)
   ___POLL(1)
___DEF_SLBL(1,___L1_twice)
   ___JUMPGLOSAFE(___SET_NARGS(2),4,___G_cons)
___DEF_GLBL(___L3_twice)
   ___SET_R1(___CONS(___R1,___R1))
   ___CHECK_HEAP(2,4096)
___DEF_SLBL(2,___L2_twice)
   ___JUMPPRM(___NOTHING,___R0)
___END_P_SW
___END_P_COD
    • とかいうおぞましいコードに。これCなのか?まあでも実際コンパイルできる。
  • 2008-03-22
    • けつのヌル文字をコピーしてないよ

Gambit-C

13:02

451 名前:デフォルトの名無しさん[sage] 投稿日:2008/03/21(金) 00:26:36

Nintendo DSDS Gambit-C 入れてる

453 名前:デフォルトの名無しさん[sage] 投稿日:2008/03/21(金) 00:37:48

>451

まじか!

ttps://webmail.iro.umontreal.ca/pipermail/gambit-list/2006-October/000870.html

今からDS買ってくる!

Lisp Scheme Part20

Gambit consists of two main programs: gsi, the Gambit Scheme interpreter, and gsc, the Gambit Scheme compiler.

Gambit-C is a version of the Gambit programming system in which the compiler generates portable C code.

Gambit

あとでテストする(DSじゃなくて)

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080322

2008-03-20

SICP読み直し中

10:33

以前読んだときはSchemeにもLispにも詳しくないくせに本とは違う環境、xyzzy Lispで動かしてたんで結構辛くて途中で投げ出してしまった。

今回新たにGaucheを使いながら読み直し始めて、多少Lispにも慣れたせいかいまのところスラスラ読み進めてる。1章読み終わった。抽象化を使うとプログラムはこんなに読みやすく書けるのか!と感動しつつ。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080320

2008-03-15

PAIP読書会

23:14

参加しました。

先日のgauche.nightに参加して、あれはただ聞くだけだったので今後は読書会など自分の手や頭を動かす活動に参加していきたいと思い、ちょうどいいところにParadigms of AI Programmingの読書会が開かれるというのを見たので、参加させてもらいました。本を持ってなかったので急いで注文してそれが今日の午前中にAmazonから送られてきたので、予習も何もないまま電車に乗って分厚い本をさらいながら向かいました。

会場への到着が少し遅れてしまいまだ入れるか不安だったのですが、優しく招き入れてくださって無事に参加させていただきました。リーディングは2章の頭から、内容は自由文法規則から文章を生成するLispのプログラムを作るというもので輪読で日本語に訳しながら進めていったのですが、一人で英語の文章を読んでいるときはわからない単語があってもてきとーに読み流してしまうんですが、みんなの前なのでそういうわけにもいかずかなり苦労しました。英語に躓いてしまい皆さんの足を引っ張ってしまって申し訳なかったです。予習をしないと私には厳しいですな…。

まだ2章なので内容自体はそれほど難しいものではありませんが、それでもなかなかハッとさせられるサンプルでした。自由文法によるランダムな文の生成を、はじめは置き換えルールをそのままプログラムに落とし込む形で実装してみて、これだと変更や拡張するのが難しいということでデータ駆動に変えてそれも単純な置き換えルールだけで作り上げていくのにはかなり感心しました。

輪読で手一杯で、途中のExerciseなどに手が出せなかったので、これも宿題にしようと思います。次回は3.2章の途中の、マクロからです。

なんだかんだで5時間はあっという間に過ぎてしまい読書会は終了、このまま帰るのもなんだねってことで近くの食堂に入りあれこれだべりタイム。id:g000001さんが相変わらずかっ飛ばしていて、すごかったです。処理系マニアというか、あらゆる処理系や歴史について非常に詳しく、それぞれの違いについてや年代などをすべて記憶しているところがハンパじゃなかったです。

Lispに詳しくない自分としては、Lispの関数の名前とか引数がなぜこの形になってるんだろう?と疑問に思うことがあって、それがそういう歴史を知ることによって腑に落ちることがよくあるので、非常に理解の助けになりました。

話に上がってた内容はいろいろあるんですが、「Common Lispのコミュニティ欲しいよね」「Shiroさんのようなカリスマ的人物が欲しい」「なぜCommon Lispが盛り上がらないのか」「80年代にやりつくしてしまったからではないか」「昔のLispハッカーはもう超越してしまって、言語は別に何でもいい領域に達してしまった」というあたりがずしーんと重い感じでした。

読書会と飲み会にid:drybulbさんも参加されており、なかなかcadrグループは集まりがよいというか、今もっとも活発なLispコミュニティなのではないかと思います。それもこれもid:g000001さんのパワフルさに支えられていると思うので、ここはひとつ先頭走って盛り上げていっていただけたら、と思います。

f:id:mokehehe:20080315231406j:image

記念写真。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080315

2008-03-13

マクロ2

08:42

単純だがパワフルなマクロ機能は1960年代中頃にMacLispに導入された。

Lispの進化

dat落ちしたスレLisp Scheme Part18から

115 :デフォルトの名無しさん:2007/08/26(日) 08:18:04 
andやorって 
関数で定義したほうがapply出来たりして柔軟性が増すと思うんですが、 
R5RSだと7.3でsyntax-rulesで定義がされてます。 
関数で定義するとなんか問題が発生したりするんでしょうか。 

116 :デフォルトの名無しさん:2007/08/26(日) 08:29:19 
関数にしちゃうと、必ず全引数評価しちゃうから困る。 
(and (pair? foo) (car foo)) 
みたいなのができない。 

117 :デフォルトの名無しさん:2007/08/26(日) 08:34:05 
どう違うかぐらい自分で確かめなさい 

118 :デフォルトの名無しさん:2007/08/26(日) 09:10:38 
>>115 
そこまでやるなら if や define も関数にしたら如何?w 

119 :デフォルトの名無しさん:2007/08/26(日) 09:26:33 
andにしろifにしろ 
陽にlambdaを渡すようにすれば関数でもいいわけだよな 
果てしなく面倒くさいが 

120 :デフォルトの名無しさん:2007/08/26(日) 09:48:25 
Haskell みたいにデフォルトで遅延評価にしちゃえば、関数で問題ないんだけどね。 

>>119 
その場合、各引数を lambda で包んでその関数に渡すようなマクロが欲しくなるかもw 

121 :デフォルトの名無しさん:2007/08/26(日) 13:16:00 
スペシャルフォームじゃだめなん? 

123 :デフォルトの名無しさん:2007/08/29(水) 14:14:20 
デフォルトで遅延評価にしちゃえばマクロは用なしになるのかな? 
現在のマクロは 
Schemeだと名前呼び+レキシカルスコープの関数 
CLだと名前呼び+ダイナミックスコープの関数と等価? 

124 :デフォルトの名無しさん:2007/08/29(水) 15:00:15 
r6rsキタ 

125 :デフォルトの名無しさん:2007/08/29(水) 16:25:14 
へー、批准されたんだ… 

126 :デフォルトの名無しさん:2007/08/29(水) 17:04:59 
scheme構文もCLマクロもファーストクラスじゃないから関数と等価ではないかな 
R6+RSで構文オブジェクトもファーストクラスにならないかな 

ところでR6RSどこにキタの? 

127 :デフォルトの名無しさん:2007/08/29(水) 17:33:57 
単純に、関数で setq って書けないよね。 
引数を評価しないでシンボルのまま扱う手段が必要で、遅延評価だけじゃ足りない。 

128 :デフォルトの名無しさん:2007/08/29(水) 20:33:34 
LISP 1.5にはマクロは無く、代わりにFSUBR/FEXPRという引数を評価しない関数があった。 
評価すべき部分(例えば setq の第2引数みたいなの)は明示的に eval を呼ぶわけだが、 
スコープの関係とかぐちゃぐちゃになって使いにくかったらしい。 

129 :デフォルトの名無しさん:2007/08/31(金) 04:16:32 
>>126 
ttp://lists.r6rs.org/pipermail/r6rs-discuss/2007-August/003272.html 
ttp://www.r6rs.org/ratification/results.html 

YESの人たちとNOの人たちのコメントの差が物悲しい(量・質共に)。 

preliminary resultsが出た時は承認ラインが全投票人数の60%と 
なぜか思い込んでたもんで、僅差(67/112)で届かないと思って 
ホッとしてたりもしたんだけど、まぁ有効投票数ですよね、普通。

マクロ

07:03

LispはS式でできていてマクロを使えばコンパイラ製作者と同等な力を手に入れる、とかいう記述を On Lisp とかで見て、マクロはすごいものでこれがあるからLispは他の言語にはないパワフルさがあるもんだと思ってたんだけど、

どうしてもマクロでなければできないことというのは 実はあまり無い。

Scheme:マクロの危険

というのを読んで結構ビックリした。テストで while を作ってみる:

(defun my-while (pred body)
  (if (funcall pred)
      (progn
        (funcall body)
        (my-while pred body))))

(setq i 0)
(my-while (lambda () (< i 10))
          (lambda ()
            (print i)
            (incf i)))

lambda がメンドウだけど一応できるといえばできるのか~。

さきほどのページの文章のすぐ後ろに

処理の抽象化の多くは(lambdaの氾濫を気にしなければ) 高階関数で可能だし、オブジェクト指向の機構についてのいろいろな処理は メタオブジェクトが使えれば大抵なんとかなる。

Scheme:マクロの危険

と書いてある orz。ちゃんと読めよ。

自分が気になるのは、いつごろ Lispマクロが導入されたか、ということです。S式で記述されたプログラムを eval 作ればコンピュータで計算できるじゃん、てのが Lisp の始まりだと思うんですが(推測で)、マクロを導入しようと思いつくってのはまた別の次元だと思うのです。もともと関数で何でもできるっていうのが Lisp だというのがありますし。

1962年初版のThe Lisp 1.5 Programmer's Manual\note{Lisp1.5}も, 参考のためにLispで書かれたevalの定義を載せている.

no title

実装側のニーズから出てきた、とかなんでしょうか。このあたりのことをなにか id:g000001 さんはご存知ないかな、と期待して…。

g000001g0000012008/03/13 08:10マクロがLISPに初めて登場した時期ということであれば、実はこのグループのキーワード「マクロ」の項目に最初のメモを紹介していますw 初出は1963年のようです。
動機は、スペシャルフォームを置き換える試みetcの様子です。
メタプログラミングというのもLISPの大きな特徴だと思うので、マクロは重宝されていたんではないでしょうか。

mokehehemokehehe2008/03/13 08:41ありがとうございます!積年の悩みが氷解しました!

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080313

2008-03-12

表示…意味…論?

07:01

no title gauche.night で黒田さんが話していたR6RSの問題。unwind-protect のことなど。私には余り理解できませんが、鋭い切り口に感心します。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080312

2008-03-11

Paradigms of AI Programming

22:06

Peter Norvig氏ということもあり、id:drybulbさんに薦められたのもあって、「Paradigms of AI Programming」を読みたいと思う。これから本を注文します。

読書会があるようなので、参加したいなぁ。しかも黒田さん絶賛とな!

  • naoya_t氏も参加しているようで
Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp

Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp

次回は3/15(土)の予定

http://blog.livedoor.jp/naoya_t/archives/50854643.html

うぉー今から本を注文しても間に合わん!

価格: ¥ 9,291 (税込)

高ぇ!

しかし思い切ってPAIPと、さらに The Little Schemer に To Mock a Mockingbird まで注文。

g000001g0000012008/03/12 00:25自分も今回参加してみようかと思い、本がないので見学してても良いですかと問い合わせたら、まあ、折角なのでOK、とのことでした。
友達の引っ越しの手伝いが15日に被らなければ、自分も参加します! 見学ですけどw

mokehehemokehehe2008/03/12 06:41お、g000001さんも参加されるんですか。
誰に問い合わせればいいんでしょうか。

g000001g0000012008/03/12 16:13自分はlingrのGauche部屋で訊いてみましたが、MLに参加したりmixiでも良さげです。
http://practical-scheme.net/wiliki/wiliki.cgi?ParadigmsOfArtificialIntelligenceProgramming
もうそろそろML等に3回目のアナウンスがあるんじゃないかなと思います。

mokehehemokehehe2008/03/12 22:59ありがとうございます!聞いてみます。

naoya_tnaoya_t2008/03/14 23:22こんにちは。ご指名頂きましたnaoya_tです。
今週のも参加するつもりでしたが、残念ながら出られなくなりました><

g000001g0000012008/03/15 01:34自分もMLに参加しているんですが、返事がないですね(^^;
多分参加しても大丈夫だと思うんですが。。。
もしかしたら参加直前に3回目のアナウンスだったかもしれないので、アナウンスを張っておきます。場所や時間は1回目から変わらないみたいです。
日時: 2008年3月15日(土) 13:00~
18:00
場所: 株式会社タイムインターメディア2F大会議室
東京都新宿区坂町26-27 インテリジェントプラザビ
ル 2F *3
参加費: 無料
参加条件: 特にありませんが、上記の本とCommon Lisp処
理系をインストールした
ノートパソコンを持参することをお薦めします。
その他: 持ち込みネタ(PAIP本に関わる発表とかデモと
か)大歓迎です。
予定通りならChapter 2 A Simple Lisp Program か
ら読み始め

お話をお伺いできると思っていたのに残念です。> naoya_tさん
自分も今回様子をみて、ついて行けそうなら次回から続けたいと思います^^

mokehehemokehehe2008/03/15 08:56naoya_t さん出られないんですか、残念です。先日の gauche.gong の発表の、PIC上でScheme実装するってことにウヒー!と思いました (^^;;
g000001 さん、今日の午前中にAmazonから本が送られてくるはずなのでそれを待って、間に合うようだったら会場に行ってみようかと思います。誰からも返答がないので行っていいのか不安ですが (^^;; 断られたら帰って不貞寝します。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080311

2008-03-09

shiroさん語録

23:10

<higepon> 自分の全盛期がいつ来るか分からないのが怖い.全盛期を最大限に活用するにはどうすれば良い?

<shiro> 逆にもし,明日か,1ヵ月後か,1年後に全盛期が来るとするなら,そのためにできることは?

Route 477(2008-03-09)

こ、これはすごい…。質問に対して自分の経験からの答えを与えるんでなく、示唆する問いを返して相手に考えさせるという。人格者というか、仙人の域に達してるな。感動した。

gauche.nightは楽しかったけど

18:59

どうやっても見物人という立場であることはまぬがれない。今後は読書会とか、自分が参加するイベントに参加していきたい。

g000001g0000012008/03/09 21:09昨日はありがとうございました!
確かに見物人だけじゃものたりない、と思わせるような方々と交流できて刺激になりますよね。
mokeheheさんの発表も是非見てみたいです!

mokehehemokehehe2008/03/09 23:08こちらこそありがとうございました!先に帰ってしまってすいません。
g000001さんの知識の豊富さにたじたじです (>_<)

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080309

2008-03-08

gauche.night

01:11

cadrグループの方や他にたくさんの人に会えてよかったです。

  • 黒田さんの、R6RSは実用として使えるという方向に走ってるけど、Algorithmic Language Schemeじゃなくていいの?というツッコミ。
    • 実用にするには unwind-protect が必要だけど、完全な継続とは相性が悪い。どうすんの?
  • hogelogさんのプレゼンがうますぎてワロタ。
  • koguroさんのglint + Flymake + oshiete-shiro-san (gauche-ARToolKit)がツボった。

  • 青海駅降りてから TOKYO CULTURE CULTURE がどこにあるかわからなくて10分くらい迷った。ZEPP TOKYO 内ということを知らなかった。
  • 舞台が高くて見上げる形で2、3時間いたので、首が痛い
  • Haskell 好きとしては、あまり発言しなかったけど nobsun がいい味を出していた

Gaucheで正規表現

11:19

Gaucheには正規表現のリテラルが使えるのか~

gosh> #/abc/
#/abc/
gosh> #/(a.*b)/
#<subr />

#<subr />と出るのが気になりますね…。

実際に使用してみる:

(let ((match (rxmatch #/(a.*b)/ "abracadabra")))
  (if (match)
      (match 1)))
  • rxmatchで正規表現のマッチを行える。rxmatch を省いて正規表現を先頭に持ってきても化。
  • 返ってきた正規表現マッチオブジェクトに数値で (...) でくくった部分の取り出し、'before や 'after で前後の取出しができる。(regmatch)

正規表現のマッチを let で受け取って #f じゃなかったら、というのがメンドイのでアナフォリックマクロを使ってみる:

(define-macro (aif pred then-val . else-val)
              `(let ((it ,pred))
                 (if it
                     ,then-val
                   ,@else-val)))

(aif (rxmatch #/(a.*b)/ "abracadabra")
     (it 1))
  • Scheme でのオプション引数とデフォルト引数の仕方がわからない…。Comon Lisp でいうところの、
(defmacro aif (pred then-val &optional (else-val nil))
  • のようにしたいんだけど、わからないので残りのリストをすべて受け取ってしまっている。
  • Scheme で if の else節を書かなかった場合 #<undef> が返ってくる。同様に aif でも else が与えられなかった場合 #<undef> を返したいが、オプション引数が書けたとしても #<undef> が入力できない
(define-macro (aif pred then-val &optional (else-val #<undef>))  ;<= #<undef> がリテラルじゃないのでできない
  • #<undef> ってなに?偽になるの?
gosh> (if #f 123)
#<undef>
gosh> (if (if #f 123) 456)
456

lequeleque2008/03/14 08:31Scheme だとオプショナル引き数は rest 引き数で受け取ってあとで分解するというのが常道ですね。
SRFI-89 みたいにそれ用の構文を作ってしまう人もいます。
http://srfi.schemers.org/srfi-89/srfi-89.html
Gauche だと let-optionals* や let-keywords を使うのがイディオムですかね。
> #<undef>
#<undef> は「何だかよくわからない未定義の値」です。
R6RS の初期段階で「the unspecified value」という「未規定であると規定された値」という少し自己矛盾的なものもあったのですが、それ故か最終的にはなくなってしまいました。規格上は #<undef> という値は存在しなくて、 Gauche では便宜上 #<undef> と表現される値が返ってくるだけです。また、 #f でもないので真値になります。
戻り値として #<undef> 的な値が欲しい場合は (if #f #f) とするのがポータブルだと思います。

mokehehemokehehe2008/03/14 22:27Scheme では常道なんですね。同じ Lisp 系だから大して違わないだろうと思ってたんですが、Common Lisp との違いに結構戸惑ってます。
#<undef> はリテラルとして直接入力できないんですね。不思議です。

lequeleque2008/03/14 23:15Gauche だと一応 (undefined) で #<undef> を返すこともできます。ただし、 #<undef> にあたる値は規格では建て前上存在しないことになっているので、リテラルの存在する処理系はないんじゃないかと思います。

mokehehemokehehe2008/03/15 09:04建て前上存在しない…if には必ず else をつけて、どっちかの場合は when か unless を使うってことですかね。
むーそれだったら (if ...) でelseがなかったら #f を返すとか、未定義を返すなら
(if #<undef> ...) は偽になるとかのほうが自然に感じます。

lequeleque2008/03/15 11:56規格では #<undef> にあたる値が返る部分は、「戻り値は規定されていない」というふうになっています。未規定値というのは、規格上、実際に何であるか「未規定」な値です。何であるべきか規定されていないというか。だから文字列が出てもハトが出てもかまわないわけですし、「何だかよくわからないけれど未定義の値」を返してもかまわないのです。なので、「未規定値が返る」と仕様にある部分はどんな値が返るかは処理系によって異なります。
else のない if のような場合は、何らかの値が返るかもしれませんが、未規定なのでその値を使って何かをしようとするとプログラムがポータブルではなくなってしまいます。
ちなみに when や unless も if に展開されるので未規定値が返ることがあります。

mokehehemokehehe2008/03/16 06:22Cでいう不定値が返るようなことでしょうか。納得しました。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080308

2008-03-07

サーバーサイドでschemeを動かす

23:12

あしたはGauche.night、Kahuaの話も出るんだろうか。サーバサイドでLisp or Schemeを動かせる環境がほしいなぁ。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080307

2008-03-05

eclでの最適化2

08:58

Use of Declarations to Improve Efficiencyの続き。ecl のソースを proclaim で grep してみる。該当箇所:cmpenv.lsp(168)

(defun proclaim (decl)
  (case (car decl)((~ FUNCTION)
     (proclaim-var (car decl) (cdr decl)))

(defun proclaim-var (type vl)
  (setq type (type-filter type))
  (dolist (var vl)
    (if (symbolp var)
	(let ((type1 (get-sysprop var 'CMP-TYPE))
	      (v (sch-global var)))
	  (setq type1 (if type1 (type-and type1 type) type))
	  (when v (setq type1 (type-and type1 (var-type v))))
	  (unless type1
	    (warn
	     "Inconsistent type declaration was found for the variable ~s."
	     var)
	    (setq type1 T))
	  (put-sysprop var 'CMP-TYPE type1)
	  (when v (setf (var-type v) type1)))
	(warn "The variable name ~s is not a symbol." var))))

これじゃないのかな?たしかに symbolp じゃないから warning は出るわな。関数の型宣言はこれじゃない予感。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080305

2008-03-04

Arc sucks

08:43

Arcを動かしてみようかと重い腰を上げて、Windows版のMzSchemeをインストーラで入れてArc2を落として、

mzscheme -m -f as.scm

としたが

compile: bad syntax; function application is not allowed, because no #%app syntax transformer is bound in: (quote nil)

というエラーが出てしまい動かない。ググると 利用できるブログ数を超えています - はてなブログ で、

ていうかArcのInstallationページに、バージョン352入れろと書いてある。

利用できるブログ数を超えています - はてなブログ

とのこと。いっきにやる気が萎えた…。

MzSchemeもいれたばっかだし古いバージョンも簡単に落とせるので、入れなおして動かしてみた。テストはおいおい…。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080304

2008-03-02

Use of Declarations to Improve Efficiency

22:55

404 Not Found ECLのマニュアルに最適化について、tak関数を使って書いてあった。

   (eval-when (compile)
   (proclaim '(function tak (fixnum fixnum fixnum) fixnum))

   (defun tak (x y z)
   (declare (fixnum x y z))
   (if (not (< y x))
   z
   (tak (tak (1- x) y z)
   (tak (1- y) z x)
   (tak (1- z) x y))))

ぬぬ、なんか括弧が足りない…。適当に括弧をつけても、Cへの変換結果がintに最適化されない…。

  • なんかwarningが出てる
> (compile-file "tarai4.l" :system-p t :c-file "tarai4.c")
;;; Compiling tarai4.l.;;; Warning: The variable name (FIXNUM FIXNUM FIXNUM) is
not a symbol.
  • 404 Not Found 8.2 Significant Type Specifiers」を見ても、これでよさそうなもんだけど。
  • コンパイル時に Safety が 3 だから?と思い、(proclaim '(optimize (safety 0))) を追加したが変わらず
  • ひょっとして最新じゃないから?と思い ecl-0.9j-p1 にしたけど変わらず

ECLでクロージャをコンパイル

19:45

どうなるのかテスト

(defun make-adder (n)
  (lambda (x)
    (+ x n)))

(print (mapcar (make-adder 10)
             '(1 2 3 4)))

(quit 0)

結果:

#include <ecl/ecl-cmp.h>
#include "D:/usr/prog/script/lisp/ecl-0.9i/test/map.h"
/*	function definition for MAKE-ADDER                            */
static cl_object L2make_adder(cl_object V1)
{ VT2 VLEX2 CLSR2
cl_object value0;
	{
		env0 = Cnil;
		CLV0=env0=CONS(V1,env0);                  /*  N                                     */
		value0=cl_make_cclosure_va((void*)LC1NIL,env0,Cblock); NVALUES=1;
		return value0;
	}
}
/*	closure CLOSURE                                               */
static cl_object LC1NIL(cl_narg narg, cl_object env0, cl_object V1, ...)
{ VT3 VLEX3 CLSR3
cl_object value0;
	/* Scanning closure data ... */
	CLV0=env0;                                /*  N                                                   */
	{ /* ... closure scanning finished */
		if(narg!=1) FEwrong_num_arguments_anonym();
		{
			value0=number_plus(V1,CAR(CLV0)); NVALUES=1;
			return value0;
		}
	}}
	
#include "D:/usr/prog/script/lisp/ecl-0.9i/test/map.data"
#ifdef __cplusplus
extern "C"
#endif
void init_MAP(cl_object flag)
{ VT1 CLSR1
cl_object value0;
	cl_object *VVtemp;
	if (!FIXNUMP(flag)){
		Cblock=flag;
#ifndef ECL_DYNAMIC_VV
		flag->cblock.data = VV;
#endif
		flag->cblock.data_size = VM;
		flag->cblock.temp_data_size = VMtemp;
		flag->cblock.data_text = compiler_data_text;
		flag->cblock.data_text_size = compiler_data_text_size;
		return;}
#ifdef ECL_DYNAMIC_VV
	VV = Cblock->cblock.data;
#endif
	VVtemp = Cblock->cblock.temp_data;
	cl_def_c_function(VV[0],(void*)L2make_adder,1);
	T0= L2make_adder(MAKE_FIXNUM(10))         /*  MAKE-ADDER      */;
	T1= cl_mapcar(2,T0,VVtemp[0])             /*  MAPCAR          */;
	print(T1,Cnil);
	(void)si_quit(1,MAKE_FIXNUM(0))           /*  QUIT            */;
}
  • nを環境に積んで、環境からクロージャを作成
  • 作成したクロージャを mapcar に渡す

ECL

12:25

Cのソースにも変換できて実行ファイルも作れるというECL (Embeddable Common-Lisp) を試してみた。

cygwin で make して、実行ファイルができたはいいが起動しても何も起こらない。原因不明。わからないのでVisualC++でビルドしてみる。こっちも問題なく実行ファイルができた。そして起動させてECL – Embeddable Common-Lispどおりにサンプルが動かせた。

ためしにたらいまわしをしてみる:

tarai.l
(defun tarai (x y z)
  (if (<= x y)
      y
    (tarai (tarai (- x 1) y z)
           (tarai (- y 1) z x)
           (tarai (- z 1) x y))))

(print (tarai 20 10 5))

コンパイル

(compile-file "tarai.l" :system-p t :c-file "tarai.c" :h-file "tarai.h")

生成された中間ファイル:tarai.c

#include <ecl/ecl-cmp.h>
#include "D:/usr/prog/script/lisp/ecl-0.9i/test/tarai.h"
/*	function definition for TARAI                                 */
static cl_object L1tarai(cl_object V1, cl_object V2, cl_object V3)
{ VT2 VLEX2 CLSR2
cl_object value0;
	{
	TTL:
		if(!(number_compare(V1,V2)<=0)){
			goto L5;}
		value0=V2; NVALUES=1;
		return value0;
	L5:;
		{cl_object V4;
			V4= L1tarai(number_minus(V1,MAKE_FIXNUM(1)),V2,V3) /*  TARAI       */;
			{cl_object V5;
				V5= L1tarai(number_minus(V2,MAKE_FIXNUM(1)),V3,V1) /*  TARAI       */;
				V3= L1tarai(number_minus(V3,MAKE_FIXNUM(1)),V1,V2) /*  TARAI       */;
				V2= V5;
				V1= V4;}}
		goto TTL;
	}
}
	
#include "D:/usr/prog/script/lisp/ecl-0.9i/test/tarai.data"
#ifdef __cplusplus
extern "C"
#endif
void init_TARAI(cl_object flag)
{ VT1 CLSR1
cl_object value0;
	cl_object *VVtemp;
	if (!FIXNUMP(flag)){
		Cblock=flag;
#ifndef ECL_DYNAMIC_VV
		flag->cblock.data = VV;
#endif
		flag->cblock.data_size = VM;
		flag->cblock.temp_data_size = VMtemp;
		flag->cblock.data_text = compiler_data_text;
		flag->cblock.data_text_size = compiler_data_text_size;
		return;}
#ifdef ECL_DYNAMIC_VV
	VV = Cblock->cblock.data;
#endif
	VVtemp = Cblock->cblock.temp_data;
	cl_def_c_function(VV[0],(void*)L1tarai,3);
	T0= L1tarai(MAKE_FIXNUM(20),MAKE_FIXNUM(10),MAKE_FIXNUM(5)) /*  TARAI */;
	print(T0,Cnil);
	(void)si_quit(1,MAKE_FIXNUM(0))           /*  QUIT            */;
}
  • おお、末尾最適化されてるし、関数呼び出しはCの関数の直接呼出しになってる

tarai.h

#ifdef __cplusplus
extern "C" {
#endif
static cl_object L1tarai(cl_object , cl_object , cl_object );
#define VT2
#define VLEX2
#define CLSR2
#define VT1 cl_object T0;
#define VLEX1
#define CLSR1
static cl_object Cblock;
#define VM1 1
#define VM2 0
#define VM 1
#define VMtemp 0
#ifdef ECL_DYNAMIC_VV
static cl_object *VV;
#else
static cl_object VV[VM];
#endif
#ifdef __cplusplus
}
#endif

実行ファイル作成:

(c:build-program "a.out" :lisp-files '("tarai.o"))

実行してみる:

$ time ./a.exe

20
real    2m54.588s
user    0m0.010s
sys     0m0.000s

結構かかる。数値の比較とか数値の減算とかが関数呼び出しになってて時間がかかってる。

tarai2.l

Optimization of GCL/KCLにしたがって、型宣言を入れてみる:

(defun tarai (x y z)
  (declare (fixnum x y z))  ;<= 型宣言を追加
  (if (<= x y)
      y
    (tarai (tarai (- x 1) y z)
           (tarai (- y 1) z x)
           (tarai (- z 1) x y))))

(print (tarai 20 10 5))

生成されたCソース:tarai2.c

#include <ecl/ecl-cmp.h>
#include "D:/usr/prog/script/lisp/ecl-0.9i/test/tarai2.h"
/*	function definition for TARAI                                 */
static cl_object L1tarai(cl_object V1, cl_object V2, cl_object V3)
{ VT2 VLEX2 CLSR2
cl_object value0;
	{
		cl_fixnum V4;
		cl_fixnum V5;
		cl_fixnum V6;
		V4= object_to_fixnum(V1);
		V5= object_to_fixnum(V2);
		V6= object_to_fixnum(V3);
	TTL:
		if(!((V4)<=(V5))){
			goto L5;}
		value0=MAKE_FIXNUM(V5); NVALUES=1;
		return value0;
	L5:;
		{cl_fixnum V7;
			V7= object_to_fixnum(L1tarai(MAKE_FIXNUM((V4)-(1)),MAKE_FIXNUM(V5),MAKE_FIXNUM(V6)) /*  TARAI */);
			{cl_fixnum V8;
				V8= object_to_fixnum(L1tarai(MAKE_FIXNUM((V5)-(1)),MAKE_FIXNUM(V6),MAKE_FIXNUM(V4)) /*  TARAI */);
				V6= object_to_fixnum(L1tarai(MAKE_FIXNUM((V6)-(1)),MAKE_FIXNUM(V4),MAKE_FIXNUM(V5)) /*  TARAI */);
				V5= V8;
				V4= V7;}}
		goto TTL;
	}
}
	
#include "D:/usr/prog/script/lisp/ecl-0.9i/test/tarai2.data"
#ifdef __cplusplus
extern "C"
#endif
void init_TARAI2(cl_object flag)
{ VT1 CLSR1
cl_object value0;
	cl_object *VVtemp;
	if (!FIXNUMP(flag)){
		Cblock=flag;
#ifndef ECL_DYNAMIC_VV
		flag->cblock.data = VV;
#endif
		flag->cblock.data_size = VM;
		flag->cblock.temp_data_size = VMtemp;
		flag->cblock.data_text = compiler_data_text;
		flag->cblock.data_text_size = compiler_data_text_size;
		return;}
#ifdef ECL_DYNAMIC_VV
	VV = Cblock->cblock.data;
#endif
	VVtemp = Cblock->cblock.temp_data;
	cl_def_c_function(VV[0],(void*)L1tarai,3);
	T0= L1tarai(MAKE_FIXNUM(20),MAKE_FIXNUM(10),MAKE_FIXNUM(5)) /*  TARAI */;
	print(T0,Cnil);
	(void)si_quit(1,MAKE_FIXNUM(0))           /*  QUIT            */;
}
  • object_to_fixnum() で数値を取り出したあとは、普通の整数演算になってる
  • 実行結果:
$ time ./a2.exe

20
real    3m30.728s
user    0m0.010s
sys     0m0.020s
  • むしろこっちのほうが遅い。Windows 恐るべし…。
Cで作ったバージョン:
#include <stdio.h>

int tarai(int x, int y, int z)
{
	if (x <= y)
		return y;
	else
		return tarai(
			tarai(x-1, y, z),
			tarai(y-1, z, x),
			tarai(z-1, x, y));
}

int main()
{
	printf("%d\n", tarai(20, 10, 5));
	return 0;
}

実行結果:

$ time ./tarai.exe
20

real    0m30.247s
user    0m0.010s
sys     0m0.010s
  • 6~7倍速い
tarai3.l: 式の途中に the fixnum で型を指定
(defun tarai (x y z)
  (declare (fixnum x y z))
  (if (<= x y)
      (the fixnum y)
    (the fixnum
         (tarai (tarai (the fixnum (- x 1)) y z)
                (tarai (the fixnum (- y 1)) z x)
                (tarai (the fixnum (- z 1)) x y)))))

(print (tarai 20 10 5))
(quit 0)

出力結果:tarai2.c と変わらず。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080302

2008-03-01

ダイナミックスコープ

10:39

no title

これを読んでも、ダイナミックスコープの利点がわからない…。

xyzzyでscheme-modeを使う

10:07

Gaucheを使うときに今までは、ファイル上でエディットして保存してシェル上から実行してテスト、またはgoshでインタラクティブモードを立ち上げて手入力してた。手入力は括弧によるインデントをしてくれないし上を押してもヒストリが出ずにカーソルが移動してしまい、その後エンターを押すとカーソルが入力されたと判定されるらしくエラーが出てしまって、使い勝手がよくなかった。

そこで重い腰を上げてxyzzyscheme-modeを入れた。どうもこういうのを導入するとき、調べるのが億劫でなかなか踏み切れないんだけど、やってみたらドキュメントどおりで超簡単だった。M-x make-scheme-scratch でバッファが作れて、xyzzy上でソースを入力、実行できる。うぉ~超便利!さらに2005-09-29にあるように、結果を別バッファに出すようにすればさらに便利。同じようにやればRubyHaskellの開発環境もこんな感じにできるね。開発スピードが劇的に変わる気がする。あぁ、ハッカーは偉大だな…。

これでGaucheでライフゲームを作ってみた - koguroの日記

のようなインタラクティブ開発もできるね。この動画のようにテスト入力は出力バッファのほうで行いたいんだけど、それはできない。ちょっと変えればできそうだな。

  • no title
    • *Scheme run* のバッファを scheme-mode にすればできる
    • 以下のようにすればできた
; Gauche - directly
(setf *scheme-process-open-hook*
      #'(lambda (buffer)
          (if (buffer-process)
              (buffer-process)
            (progn
              (save-window-excursion
                (with-output-to-temp-buffer ("*Scheme run*"))
                (scheme-mode))   ; <= ここに追加
              (make-process
               (format
                nil "~A"
                (map-slash-to-backslash "gosh -i")))))))
(setf *scheme-process-read-filter*
      #'(lambda (proc text)
          (let ((curwin (selected-window)))
            (pop-to-buffer "*Scheme run*" 10)
;            (goto-char (point-max))
            (insert text)
            (process-buffer proc)
            (set-window curwin)
            (refresh-screen))))

コード補間がすごいなぁ。俺もやってみたい。

トラックバック - http://cadr.g.hatena.ne.jp/mokehehe/20080301