gemma
- Mixi http://mixi.jp/show_friend.pl?id=1325229
- 1983年生まれ、大学生。
- Fedora Core 5を使ってます。
- Dvorak配列使いです。算術記号のキーが、ホームポジションの近くになり、便利です。Schemeで良く使う"-"はEnterキーの隣になるので、小指で楽に打てます。Emacsのキーバインディングがごちゃごちゃになりますが、慣れれば気になりません。
- 昔にC言語で書いたゲーム。今見ると、恥ずかしい。http://racanhack.sourceforge.jp/cgi-bin/wiki.cgi
Webプログラミングに継続を採り入れると、より美しいコードが書けるんじゃないかと、興味を持っています。
- Kahua
- The Influence of Browsers on Evaluators or, Continuations to ...
- Web Programming with Continuations
- 境界を越える: 継続とWeb開発、そしてJavaプログラミング
- https://www-06.ibm.com/jp/developerworks/java/060412/j_j-cb03216.shtml
- (抜粋)
- プログラマーにとってはステートフル・モデルでありながら、ユーザーにとってはステートレスとなるWeb開発が可能なことを知ると、皆さんはショックを受けるかも知れません。しかし実際には、Paul Grahamが『Hackers and Painters』(参考文献)の中で、既に1995年のViaWebにおいて、この基礎となっている手法を紹介したことを述べています。この手法では、『継続(continuation)』というプログラミング制御構造を使うのです。
- この基本的な考え方は、「プログラミング・フレームワークが、アプリケーションの状態をリクエストの前にロードし、また各リクエストの後に保存するようにする」ということです。この「継続」を、まずRubyプログラミング言語で見て行くことにします。
最近、Smalltalkでも継続を扱えることを知りました。
- Smalltalkでの継続の扱い
- Seaside is a framework for developing sophisticated web applications in Smalltalk.
Seasideの、
- Callback-based request handling.
- Why should you have to come up with a unique name for every link and form input on your page, only to extract them from the URL and request fields later? Seaside automates this process by letting you associate blocks, not names, with inputs and links, so you can think about objects and methods instead of ids and strings.
がまさに求めているものなのかもしれない。
memo: Scheme:リスト処理
(defun longer (x y) (labels ((compare (x y) (and (consp x) (or (null y) (compare (cdr x) (cdr y)))))) (if (and (listp x) (listp y)) (compare x y) (> (length x) (length y)))))
memo: Smalltalkでも制約指向プログラミングがある。 http://www.sra.co.jp/people/aoki/SmalltalkTextbookJ/textbook33.html
memo: スーパークリエイタの研究はさすがに画期的。 http://www.ipa.go.jp/NBP/14nendo/14mito/creator.html
memo: http://www.cincomsmalltalk.com/userblogs/avi/blogView?showComments=true&entry=3240140310
memo: SISC Second Interpreter of Scheme Code http://sisc.sourceforge.net/
memo: あとで読みたい。 Scheme:オブジェクト指向表現
- Squeakを試してみた。これは・・・素晴らしい! - 2006/07/13 12:41:11 PDT
- Gauche ユーザリファレンスのtypo
- 数独の解答プログラム
- AA折れ線グラフ二度
- AA折れ線グラフ
- Fedora Core 5での、Gauche-glのインストール。
- C言語の関数をGaucheから呼び出そう。
Gauche ユーザリファレンスのtypo
- Function: find pred clist
[SRFI-1] clist の各要素に対して左から右に pred を適用し、 pred が真を返す最初の要素を返します。
この説明には、満たす要素がなければ偽を返す。ことが書いていない。 find-tail、list-indexも同様。
Function: find-tail pred clist
[SRFI-1] clist の各要素に対して左から右に pred を適用し、pred が真を返す場合、その car がその要素であるペアを返します。
Function: list-index pred clist1 clist2 …
[SRFI-1] pred を満足する最も左の要素のインデックスを返します。
- Function: array-length array dim
[SRFI-25+] array-startは配列arrayのdim番目の次元のインデックスの下限を返します。 array-endは上限+1を、そして
array-startは両者の差を返します。
これは、array-lengthのはず。
- Function: map! f clist1 clist2 …
[SRFI-1] 手続き f は clist1 の各要素と clist2 の対応する要素に適用され、
結果な
ひとつのリストに集められます。clist1 のセルは結果のリストを構築するのに再利用されます。
- Function: fold kons knil clist1 clist2 …
[SRFI-1] 基本リスト反復演算子です。単一のリスト clist1 = (e1 e2 … en) を与えられたときには、以下を返します。
初期値 knil である「種」あるいは畳み込み状態と
よばれもの
です
- Generic application: regmatch 'after &optional index
マッチオブジェクトは直接整数のインデックスもしくは...
.
.
.
(define match (#/(?<integer>\d+)\.(?<fraction>(\d+)/ "pi=3.14..."))
↑<fraction>の後ろの、強調したところのカッコは要らないはず。正しくは↓だと思う。
(define match (#/(?<integer>\d+)\.(?<fraction>\d+)/ "pi=3.14..."))
- Generic Function: dbm-db-exists? class name
nameで指定されたclass暮らすのデータベースが存在する場合は#tを返します。
Typo ではなくて、要望。
- Macro: let-args args (bind-spec … [. rest]) body …
このマクロはparse-optionsのラッパーで、
...
束縛リストは、最後のcarにシンボルを持つ不完全なリストであっても良く、その場合はコマンドライン引数の残りのリストがその変数にと束縛されます。
↑この機能は良く使われそうな気がするので、具体例を書いておいてほしかった。
数独の解答プログラム
(2006/06/18 00:07:10 PDT)
ambの勉強
http://www.shido.info/lisp/scheme_amb.html
のために書いたものです。
0 5 0 0 0 0 0 4 0 0 0 0 1 0 0 3 2 0 0 0 9 0 6 2 0 0 5 3 0 0 8 0 0 0 0 4 8 4 0 0 0 1 0 5 0 0 0 6 0 0 0 8 0 1 0 9 0 0 0 4 0 0 0 0 0 0 0 2 0 0 0 0 0 6 0 3 1 8 0 0 0
問題をこのように入力したものを、ファイルに保存して、例えばそのファイル名をprobremとすると、
$ ./suudoku.scm probrem ........................ solved. counts of answer=1 1 5 2 9 8 3 6 4 7 6 7 8 1 4 5 3 2 9 4 3 9 7 6 2 1 8 5 3 1 5 8 9 6 2 7 4 8 4 7 2 3 1 9 5 6 9 2 6 4 5 7 8 3 1 2 9 3 6 7 4 5 1 8 7 8 1 5 2 9 4 6 3 5 6 4 3 1 8 7 9 2 ....answer is not any further
と出力されます。内部でバックトラックが動くたびに"."が表示されます。
#!/usr/bin/env gosh (use srfi-1) (use srfi-43) (use util.combinations) (use util.list) (use gauche.array) (define-constant dim 9) (define-constant 1-9-list (iota dim 1)) (define-constant 0-8-list (iota dim)) (define-constant all-list (cartesian-product `(,0-8-list ,0-8-list))) (define (array-ref-multi G l) (map (lambda (x) (array-ref G (car x) (cadr x))) l)) (define (row-list row) (cartesian-product `((,row) ,0-8-list))) (define (col-list col) (cartesian-product `(,0-8-list (,col)))) (define (region-list row col) (let* ((a0 (* (quotient row 3) 3)) (a1 (+ a0 1)) (a2 (+ a0 2)) (b0 (* (quotient col 3) 3)) (b1 (+ b0 1)) (b2 (+ b0 2))) (cartesian-product `((,a0 ,a1 ,a2) (,b0 ,b1 ,b2))))) (define (get-usable-number-list G row col) (define (get-row-used-number-list G row) (remove! zero? (array-ref-multi G (row-list row)))) (define (get-col-used-number-list G col) (remove! zero? (array-ref-multi G (col-list col)))) (define (get-region-used-number-list G row col) (remove! zero? (array-ref-multi G (region-list row col)))) (define (get-used-number-list G row col) (lset-union = (get-row-used-number-list G row) (get-col-used-number-list G col) (get-region-used-number-list G row col))) (lset-difference = 1-9-list (get-used-number-list G row col))) (define (read-data inp) (apply (cut array (shape 0 dim 0 dim) <...>) (apply append! (map (cut map x->integer <>) (map (cut string-split <> #\space) (port->string-list inp)))))) (define (my-array-print G) (for-each (lambda (x) (apply print (intersperse #\space (array-ref-multi G (row-list x))))) 0-8-list)) (define (single? l) (and (pair? l) (null? (cdr l)))) (define (fixed-num-finder A row col) (define (unique-in-list? a l) (single? (filter (cut eq? a <>) l))) (any (lambda (x) (find (cut unique-in-list? <> x) (array-ref A row col))) (map (lambda (x) (apply append x)) (list (array-ref-multi A (row-list row)) (array-ref-multi A (col-list col)) (array-ref-multi A (region-list row col)))))) (define (usable-number-list-array G) (let1 usable-number-list (map (lambda (x) (let ((row (car x)) (col (cadr x))) (if (zero? (array-ref G row col)) (get-usable-number-list G row col) '()))) all-list) (apply (cut array (shape 0 dim 0 dim) <...>) usable-number-list))) (define (fixed-num-list G) (let1 A (usable-number-list-array G) (filter-map (lambda (x) (let ((row (car x)) (col (cadr x))) (let1 p (fixed-num-finder A row col) (if (eq? p #f) #f (list row col p))))) all-list))) (define (solvable? G) (let1 A (usable-number-list-array G) (null? (filter-map (lambda (x) (let ((row (car x)) (col (cadr x))) (and (= (array-ref G row col) 0) (null? (array-ref A row col))))) all-list)))) (define (back-track-candidates G) (define (array-index pred a) (let1 i (vector-index pred (array->vector a)) (if (eq? i #f) #f (list (quotient i dim) (modulo i dim))))) (let1 A (usable-number-list-array G) (let length-loop ((len 2)) (if (> len dim) (print "wtf?") (let1 x (array-index (lambda (x) (= (length x) len)) A) (if (not (eq? x #f)) (let ((row (car x)) (col (cadr x))) (map (lambda (p) (list row col p)) (array-ref A row col))) (length-loop (+ len 1)))))))) (define (solve G) (define (solve-fork G x) (format #t ".") (flush) (let1 G0 (apply (cut array (shape 0 dim 0 dim) <...>) (array->list G)) (array-set! G0 (car x) (cadr x) (caddr x)) (solve G0))) (cond ((null? (filter zero? (array-ref-multi G all-list))) (if (answer-checker G) (begin (inc! answer-count) (newline) (format #t "solved. counts of answer=~s\n" answer-count) (my-array-print G) (choose)) (choose))) ((not (solvable? G)) (choose)) (else (let1 l (fixed-num-list G) (if (null? l) (solve-fork G (apply choose (back-track-candidates G))) (begin (for-each (lambda (x) (array-set! G (car x) (cadr x) (caddr x))) l) (solve G))))))) (define (answer-checker G) (define (checker G row col) (and (equal? 1-9-list (sort (array-ref-multi G (row-list row)))) (equal? 1-9-list (sort (array-ref-multi G (col-list col)))) (equal? 1-9-list (sort (array-ref-multi G (region-list row col)))))) (null? (filter-map (lambda (x) (not (checker G (car x) (cadr x)))) all-list))) (define answer-count 0) (define fail #f) (define (choose . ls) (if (null? ls) (fail) (let ((fail0 fail)) (call/cc (lambda (cc) (set! fail (lambda () (set! fail fail0) (cc (apply choose (cdr ls))))) (cc (car ls))))))) (define (main args) (if (call/cc (lambda (cc) (set! fail (lambda () (cc #f))) (cc #t))) (solve (call-with-input-file (cadr args) read-data)) (print "answer is not any further")))
- 9x9行列の枡目に0-8で番号付けしてるのを、いずれ書き直したいと思う。
- おっと、入力が問題として成立しているかをはじめにチェックするのを忘れている。"総当りしてから"解けないと答えるはめになっている。
- ああ、なんてことだ。share-array関数という便利なものがあったんじゃないか。2006/06/28 12:26:57 PDT
- my-array-printは、array->listしてslicesしてfor-eachでプリントしたほうがよかったなぁ。
- いや、やはり、こういうコードにすればよかった。
(define (array-print mat) (for-each (lambda (r) (let1 row-r (share-array mat (shape (array-start mat 1) (array-end mat 1)) (lambda (k) (values r k))) (print (array->list row-r)))) (iota (array-length mat 0) (array-start mat 0))) (newline))
AA折れ線グラフ二度
Schemeに慣れてきて、以前のコードを今ならもっときれいに書けるはずと、改良してみた。2006/06/10 18:35:16 PDT
(define (graph input) (define (input->plist in) (let1 y 0 (port-map (lambda (c) (case c ((#\R) (inc! y) (cons (- y 1) #\/)) ((#\F) (dec! y) (cons y #\\)) ((#\C) (cons y #\_)))) (lambda () (read-char in))))) (define (draw-row y plist) (for-each (lambda (x) (if (= (car x) y) (display (cdr x)) (display #\space))) plist)) (let ((plist (call-with-input-string input input->plist))) (receive (min-y max-y) (apply min&max (map car plist)) (let loop ((y max-y)) (if (< y min-y) 'AA-graph (begin (draw-row y plist) (display #\newline) (loop (- y 1)))))))) (graph "RCRFCRFFCCRFFRRCRRCCFRFRFF")
AA折れ線グラフ
(define (graph input) (define (input->plist input) (let1 input-p (open-input-string input) (let loop ((plist '()) (y 0)) (let1 c (read-char input-p) (if (eof-object? c) (reverse! plist) (let1 obj '() (case c ((#\R) (set! obj (cons y #\/)) (inc! y)) ((#\F) (set! obj (cons (- y 1) #\\)) (dec! y)) ((#\C) (set! obj (cons y #\_)))) (loop (cons obj plist) y))))))) (define (draw-row y plist) (for-each (lambda (obj) (if (= (car obj) y) (display (cdr obj)) (display #\space))) plist)) (let ((plist (input->plist input))) (receive (min-y max-y) (apply min&max (map car plist)) (let loop ((y max-y)) (if (< y min-y) 'AA-graph (begin (draw-row y plist) (display #\newline) (loop (- y 1))))))))
gosh> (graph "RCRFCRFFCCRFFRRCRRCCFRFRFF") __ / \/\/\ _/\_/\ _/ \ / \__/\ / \/ AA-graph
- まだfold関数の使いかたがわからん・・・ 他の方の解答に比べて、set!が多いあたり、修行が足らない。2006/04/25 22:28:52 PDT
- 今では、fold, unfoldも、使えるようになった。2006/06/10 18:43:05 PDT
Fedora Core 5での、Gauche-glのインストール。
- インストール方法。
- $ yum install freeglut-devel
- Gauche-gl の configure.in 69行目を書き換える。
AC_CHECK_HEADERS(GLUT/glut.h, [
をAC_CHECK_HEADERS(GL/glut.h, [
に。 - $ autoconf
- $ ./configure & make & make install
- 説明
いつもどおり、tar.gzを展開して、Gauche-glのconfigureを実行すると、 GLUT/glut.hが見つからないと言われる。
$ ./configure checking GL/glx.h usability... yes checking GL/glx.h presence... yes checking for GL/glx.h... yes checking GLUT/glut.h usability... no checking GLUT/glut.h presence... no checking for GLUT/glut.h... no
それもそのはず、freeglut-develパッケージをまだインストールしていない。
#yum install freeglut-devel
よし、これでGLUT/glut.hを見つけてくれるはずだ。と思ったら、また失敗、見つからないと言われる。
glut.hが、GL/glut.hにインストールされてしまっているので、GLUT/glut.hは存在しないのだ。 そこで、Gauche-glのconfigure.inを書き換える。69行目、
AC_CHECK_HEADERS(GLUT/glut.h, [
を
AC_CHECK_HEADERS(GL/glut.h, [
に。
変更をconfigureスクリプトに反映するために、
$ autoconf
を実行。
$ ./configure checking GL/glx.h usability... yes checking GL/glx.h presence... yes checking for GL/glx.h... yes checking GL/glut.h usability... yes checking GL/glut.h presence... yes checking for GL/glut.h... yes
正常。この後めでたく、make, make install で、インストール完了。
C言語の関数をGaucheから呼び出そう。
SDL_Surfaceを回転するC言語の関数を、Gaucheから呼び出したくなった。 spigotとgenstubのソースコードが参考になった。
$ gauche-package generate hoge $ cd hoge/ hogelib.stub, hoge.c, hoge.h, hoge.scm を書いて、 $ ./DIST gen $ ./configure $ make # make install
配布したくなったら
$ ./DIST tgz
C言語の関数を呼び出す方法を調べるにあたって、参考にしたページ Gauche:FFI Gauche:MeCab