Gaucheの最近のブログ記事



JavaScriptでカリー化


私の第一言語であるJavaScriptでカリー化を試してみる。


JavaScriptはお師匠のJavascriptシェルで実行すると楽ちん。



例題はWikipediaのカリー化を参考にしよう。



関数 f がhttp://upload.wikimedia.org/math/9/3/6/936d3616ae1788839acf2cbb7228fad2.pngの形のとき、f をカリー化したものを g とすると、g はhttp://upload.wikimedia.org/math/8/6/7/8678d9a38b70c18ff730a4326baf87b9.pngの形を取る。非カリー化(uncurrying)とは、これの逆の変換である。


カリー化とは直感的には「引数を幾つか固定すると、残った引数の関数が得られる」ということである。たとえば、除算の関数http://upload.wikimedia.org/math/8/b/0/8b012fa4da01406236b0b0a5cb959a03.pngをカリー化したものを cdiv とし、inv = cdiv(1) とすると、inv は新しい関数となり、http://upload.wikimedia.org/math/d/2/0/d201da20452ac22a913f0debbcdd4dc4.png 、つまり引数の逆数を返す関数になる。


http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AA%E3%83%BC%E5%8C%96

実際に書いてみた。

例題を実直にdiv関数を書くとこんな感じ。



var div = function(x,y){
return x / y;
};
alert(div(2, 1));//2

2つ目の例を落とし込むとこんな感じ。



var inv = function(x){
return function(y){
return x / y;
};
};

var cdiv = inv(10);//inv(10)のfunctionを変数cdivにbindする

alert(cdiv(1));//10
alert(cdiv(2));//5

var cdiv = inv(2);//inv(2)のfunctionを変数cdivにbindする
alert(cdiv(1));//2
alert(cdiv(2));//1

alert(inv(10)(2));//5
alert(inv(10)(5));//2


書いて分かったけど、高階関数の一種なのね。なるほど。


乗法してみた

もう少し書いてみる。次は乗法。



var multiplication_curry = function(x){
return function(y){
return x * y;
};
};

//実行例1
var first = multiplication_curry(1);
var second = multiplication_curry(2);
var third = multiplication_curry(3);
alert(first(second((third(4)))));//24
//first(second((third(4))))
//first(second((3 * 4)))
//first(second((12)))
//first(2 * 12)
//first(24)
//1 * 24
//24

//実行例2: 実行例1とは当然等価。
alert(multiplication_curry(1)(multiplication_curry(2)(multiplication_curry(3)(4))));//24
//multiplication_curry(1)(multiplication_curry(2)(3 * 4))
//multiplication_curry(1)(multiplication_curry(2)(12))
//multiplication_curry(1)(2 * 12))
//multiplication_curry(1)(24))
//1 * 24
//24

展開式も書いてみた。


JavaScriptでこの書き方好きだけど、他人のコードをリバースエンジニアリングするのは勘弁。



Pythonでカリー化


乗法を第2言語のPythonで書いてみる。



multiplication_curry = lambda x: lambda y: x * y

print(multiplication_curry(1)(multiplication_curry(2)(multiplication_curry(3)(4))))#24

lamda式を使う。return文がないので綺麗に書けた。


Gaucheでカリー化


ついでにGaucheでもカリー化。



(define (multiplication_curry x)
(lambda (y) (* x y)))

((multiplication_curry 1)
((multiplication_curry 2)
((multiplication_curry 3)
4)))
;;24

大体理解した。



別件の疑問


JavaScriptの関数定義の際、変数に無名関数を束縛する書き方と関数を定義する書き方どっちが主流なんだろう??


変数に無名関数を束縛する書き方例


var div = function(x,y){
return x / y;
};


関数の定義


function div(x,y){
return x / y;
}


個人的には前者の変数に無名関数を束縛する書き方なのだけれど...どっちが良いのだろうか...??




まとめ



  1. カリー化を実戦で使うところってどこだ?

  2. やっぱりプログラミング言語はファーストクラスオブジェクトじゃないと♪



参考


id:m-hiyamaさんのブログを読んでて興味を持ちました。


檜山正幸のキマイラ飼育記


例題はWikipediaからの引用です。


Wikipedia カリー化


実行とテストにはお師匠のJavascriptシェルを利用しました。


Javascriptシェル




TDDを求めるエンジニアが多いので、gaucheでのユニットテスト例。



;;テスト対象
(define (proc1 a b c)
(if (and (<= a b)(<= a c))
(+ (proc2 b)(proc2 c))
(proc1 b c a)))

(define (proc2 x)
(* x x))

#|
以下ユニットテスト例。
|#
;;テストモジュールを読み込む
(use gauche.test)

;;テストをスタート
(test-start "proc1 test")

;;テスト群の名前付け。
(test-section "test group 1")

;;テスト項目
(test* "proc1 13" 13 (proc1 1 2 3))
(test* "proc1 25" 25 (proc1 2 4 3))
(test* "proc1 41" 41 (proc1 5 4 3))
(test* "proc1 2" 2 (proc1 1 1 1))

;;テストの終了
(test-end)

実行結果



Testing proc1 test ...
<test group 1>-----------------------------------------------------------------
test proc1 13, expects 13 ==> ok
test proc1 25, expects 25 ==> ok
test proc1 41, expects 41 ==> ok
test proc1 2, expects 2 ==> ok
passed.

参考



Gaucheについてまとめた記事


Gaucheの有用情報まとめ




昨日自分が書いた記事。


Re:Gauche0.8.14とKahua1.0.7.3だとKahuaの./configureでこける。


原因探索(?)


どうやらVirtualBoxが犯人みたいです。


というのは職場のサーバにKahua入れたらうまく入り、動作も確認できました。


職場サーバの環境


  • Fedora10

  • Gauche0.8.14

  • Kahua1.0.7.3



なんだかなぁ。



ちなみに今日はプログラミングGaucehを読まずにSICPを読みます。




追記:原因はvirtualboxみたい?


詳しくはこちら。


Re:Gauche0.8.14とKahua1.0.7.3だとKahuaの./configureでこける。



Gauche0.8.14とKahua1.0.7.3だと、Kahuaの./configure時にこける。


3時間くらいハマった。


環境


Fedora10(Mac上のVirtualbox)


=>virtualboxが原因?と思ったけどどうやら違うみたい。



原因はどうやら、gauche/threads.scmがGaucheのインストール時に配置されないのが原因みたい。


/usr/local/share/gauche/0.8.14/libの中を確認しても確かにthreads.scmは確認なかった。


gaucheでthreadsが有効になってないのかな?と思い、gosh -Vを実行したら有効になってる罠。



ログ(Kahua ./configure時)



checking check Gauche version and thread type... gosh: "error": Compile Error: cannot find file "gauche/threads.scm" in *load-path* ("/usr/local/share/gauche/site/lib" "/usr/local/share/gauche/0.8.14/lib")
"./check.scm":7:(use gauche.threads)

configure: error: You must install Gauche 0.8.13 or later which was built with
--enable-threads=pthreads configure option.

[root@localhost scheme]# gosh -V
Gauche scheme interpreter, version 0.8.14 [utf-8,pthreads]


対応


対応方法分からなかったので、以前問題なかったGauche0.8.13とKahuaの組み合わせに変更。結果問題なし。


ここでmakeの仕組みを知ってれば解決出来たろうけど、経験不足でした。




順調に14章読み終えた。format関数のフォーマット形式に慣れてないからもう少し見直す。



ファイル入出力は他言語のsourceにあたるものがポートであると解釈。


ゆくゆく、共通ライブラリ化しようと思う。



ちなみに今日はGoogle Maps APIを触ってるから、プログラミングGaucheをそんなに読み進めれそうもない。


































小節
第1部 予備知識1章 LispとScheme
2章 Gaucheの特徴
3章 Gaucheの設計思想や誕生の背景
第2部 Gaucheの基礎練習4章 Gaucheの開発スタイル
5章 プログラムの書式
6章 リスト
7章 手続き
8章 真偽値と条件判断
9章 状態の管理
10章 テストと例外処理
11章 評価モデル
第3部 実用的なプログラミング12章 数値
13章 文字と文字列の処理
14章 入出力
15章 テキストの構築
16章 さまざまなデータ構造
17章 総称関数とオブジェクト
18章 構文の拡張
19章 継続
20章 モジュールシステム
21章 デバッグ
22章 データベース
23章 日付と時間
第4部 Webアプリケーションへの応用24章 GaucheでCGIスクリプトを書いてみる
25章 スケジュール管理アプリケーション
26章 継続渡しによるWebアプリケーション
27章 Kahuaアプリケーションを書こう
付録AGaucheインストール
付録BEmacsの設定
付録CKahuaインストール
付録DGaucheとR6RS



































小節
第1部 予備知識1章 LispとScheme
2章 Gaucheの特徴
3章 Gaucheの設計思想や誕生の背景
第2部 Gaucheの基礎練習4章 Gaucheの開発スタイル
5章 プログラムの書式
6章 リスト
7章 手続き
8章 真偽値と条件判断
9章 状態の管理
10章 テストと例外処理
11章 評価モデル
第3部 実用的なプログラミング12章 数値
13章 文字と文字列の処理
14章 入出力
15章 テキストの構築
16章 さまざまなデータ構造
17章 総称関数とオブジェクト
18章 構文の拡張
19章 継続
20章 モジュールシステム
21章 デバッグ
22章 データベース
23章 日付と時間
第4部 Webアプリケーションへの応用24章 GaucheでCGIスクリプトを書いてみる
25章 スケジュール管理アプリケーション
26章 継続渡しによるWebアプリケーション
27章 Kahuaアプリケーションを書こう
付録AGaucheインストール
付録BEmacsの設定
付録CKahuaインストール
付録DGaucheとR6RS



12章を読み終えた。


12章 数値


正確数、不正確数は初めて聴いた用語。


あと、四則演算の「法」も知らなかった。


細かい関数は覚えきれないので、何ができるのかをひとまずさらう。


13章 文字と文字列の処理


最後の方にある正規表現処理が苦手。



第20章 モジュールシステム


Gaucheのモジュール例が載ってる。


この辺結構興味あって、既存のソースコード(srfi-0.scmとか、www/cgi.scmとか)に目を通してみた。


まだ、基本文法の知識不足で読めてないけど、モジュールに必要な構文は理解。



疑問に思った点

SRFIライブラリの内、useを使って読み込む必要があるライブラリ(srfi-13など)と組み込みのライブラリ(srfi-0など)はどのような理由で分けられているのか不明。


なぜ?歴史的なものであろうか...??


関連事項見つけた。



Gauche (0.8.14)


0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 16, 17, 18, 19, 22, 23, 25, 26, 27, 28, 29, 30, 31, 34, 35, 36, 37, 38, 39, 40, 42, 43, 45, 55, 61, 62, 87


http://srfi.schemers.org/srfi-implementers.html

ひとまずGauche0.8.14は上記をサポートしているそうです。


追記:GaucheのSRFIライブラリサポート予定見つけた。


http://practical-scheme.net/wiliki/wiliki.cgi?Gauche%3Asrfi



SRFIってなによ?

そもそもSRFI自体がなんなのか知らないから読む。


Scheme Requests for Implementation


SRFIの細かいのはあとで読み解く。いまはGaucheに慣れるのが優先。



モジュール作成に必要な文法


  • define-module

  • export

  • provide


とか。




Gaucheについて調べてたら、ブラウザのタブ占有数がえらい事になってきたので、一回まとめる。



Gauche ユーザリファレンス


ShiroKawa氏が管理されているGaucheユーザリファレンス。


http://practical-scheme.net/gauche/man/gauche-refj.html


モジュールに関しても載っているので、モジュールソースコード読む前に目を通すのが吉。



GaucheによるWEBフレームワークKahua


http://khead.kahua.org/


リファレンスが充実していてありがたい。



Chaton (「しゃとん」)


今は亡きLingerのGauche部屋を引き継ぐ。


Chaton



Gauche部屋

Chaton Gauche


SourceforgeにBSDLicenseで公開されている。


Chaton Code


追:ちなみにjava-jaはLingerからIRCに乗り換えました。



practical-scheme.net


SchemeやGaucheについての情報交換されてる場。


http://practical-scheme.net/wiliki/wiliki.cgi


というか、このwiki自体Gauche実装ですね。わかります。



wiliki

http://sourceforge.net/projects/wiliki/



wilikiに蓄積されたGaucheのページ


この情報は熱い!!


http://practical-scheme.net/wiliki/wiliki.cgi?Gauche


こっそり追加...


http://practical-scheme.net/wiliki/wiliki.cgi?rokujyouhitoma



mixiのGaucheコミュニティ


mixiのGaucheコミュニティは300人を超えてます。


http://mixi.jp/view_community.pl?id=197784



その他


R5RS

http://www.schemers.org/Documents/Standards/R5RS/HTML/


というわけで...


僕のブラウザのタブが10個くらい減ってすっきりしました。



代わりにダイアリーの情報が散漫になったのでまとめ直すかもしれません...。


こちらは雑多なメモ。はてなダイアリーにまとめたらあげる。

(use dbi)
(use gauche.sequence)

(define *db-name* "dbi:mysql:db=mysea;host=localhost")
(define *db-username* "root")
(define *db-password* "root")
(define *mysql-con*
(dbi-connect *db-name* :username *db-username* :password *db-password*))
(define (test)
(for-each print (dbi-do *mysql-con* "SELECT * FROM t_category"))
(dbi-close *mysql-con*))


dbiを使ってのmysql接続は、Gauche-dbd-mysql-0.2.2.tgzをインストールしてないとだめ。Gaucheの再インストールは必要ない。

gauche-package install -S root Gauche-dbd-mysql-0.2.2.tgz


で入れられるから楽チン。

参考:http://www.kahua.org/show/dev/DBI/dbd.mysql

あと別の参考だがGaucheのユーザリファレンスは参考になる。
http://practical-scheme.net/gauche/man/gauche-refj.html#Top

という感じに当面はGaucheに関するメモ書きを連ねる。



kahuaインストール


アプリケーションサーバKahuaのインストールでSchemeに触れる。


環境

Fedora9


設定手順


Kahuaのダウンロードからmake installまで。


$ wget http://www.kahua.org/download/kahua/Kahua-1.0.7.3.tgz
$ tar xzf Kahua-1.0.7.3.tgz

$ cd Kahua-1.0.7.3
$ ./configure --prefix=/usr/local/kahua --with-site-bundle=$HOME/work/site
$ make
$ make check
# make install

参考:


Kahua Project



プログラミングGauche


Gauche-dbd-mysqlのインストール。


GaucheからMySQLに接続するため。


$ wget http://www.kahua.org/download/dbi/Gauche-dbd-mysql-0.2.2.tgz
$ gauche-package install --install-as=root Gauche-dbd-mysql-0.2.2.tgz

確認


$ gauche-package list -a
Gauche-dbd-mysql 0.2.2
$ gosh
gosh> (use dbd.mysql)
#<undef>

ちなみにundefが帰ってくればOKだそうな。


ロードできない場合はエラーになるので#<undef>が帰ってくればOK*


参考:


dbd.mysql


2008-01-08 りむーばぶる3


Emacsの設定


Gaucheを快適にするため。

ほぼパクリ。~/.emacsに設定する。



;; Gaucheのデフォルトエンコード
(modify-coding-system-alist 'process "gosh" '(utf-8 . utf-8))

;; goshインタプリンタのパスに合わせる。-iは対話モードを意味する。
(setq scheme-program-name "gosh -i")

;; schemeモードとrun-schemeモードにcmuscheme.elを使用します。
(autoload 'scheme-mode "cmuscheme" "Major mode for Scheme." t)
(autoload 'run-scheme "cmuscheme" "Run an inferior Scheme process." t)

;; ウィンドウを2つに分け、一方でgoshインタプリタを実行するコマンドを定義する。
(defun scheme-other-window ()
"Run scheme on other window"
(interactive)
(switch-to-buffer-other-window
(get-buffer-create "*scheme*"))
(run-scheme scheme-program-name))

;; そのコマンドをCtrl-csで呼び出す。
(define-key global-map "\C-cs" 'scheme-other-window)

;; 直前/直簿の括弧に対応する括弧を点滅する
(show-paren-mode)

;; 以下はインデントの定義
(put 'and-let* 'scheme-indent-function 1)
(put 'begin0 'scheme-indent-function 0)
(put 'call-with-client-socket 'scheme-indent-function 1)
(put 'call-with-input-conversion 'scheme-indent-function 1)
(put 'call-with-input-file 'scheme-indent-function 1)
(put 'call-with-input-process 'scheme-indent-function 1)
(put 'call-with-input-string 'scheme-indent-function 1)
(put 'call-with-iterator 'scheme-indent-function 1)
(put 'call-with-output-conversion 'scheme-indent-function 1)
(put 'call-with-output-file 'scheme-indent-function 1)
(put 'call-with-output-string 'scheme-indent-function 0)
(put 'call-with-temporary-file 'scheme-indent-function 1)
(put 'call-with-values 'scheme-indent-function 1)
(put 'dolist 'scheme-indent-function 1)
(put 'dotimes 'scheme-indent-function 1)
(put 'if-match 'scheme-indent-function 2)
(put 'let*-values 'scheme-indent-function 1)
(put 'let-args 'scheme-indent-function 2)
(put 'let-keywords* 'scheme-indent-function 2)
(put 'let-match 'scheme-indent-function 2)
(put 'let-optionals* 'scheme-indent-function 2)
(put 'let-syntax 'scheme-indent-function 1)
(put 'let-values 'scheme-indent-function 1)
(put 'let/cc 'scheme-indent-function 1)
(put 'let1 'scheme-indent-function 2)
(put 'letrec-syntax 'scheme-indent-function 1)
(put 'make 'scheme-indent-function 1)
(put 'multiple-value-bind 'scheme-indent-function 2)
(put 'match 'scheme-indent-function 1)
(put 'parameterize 'scheme-indent-function 1)
(put 'parse-options 'scheme-indent-function 1)
(put 'receive 'scheme-indent-function 2)
(put 'rxmatch-case 'scheme-indent-function 1)
(put 'rxmatch-cond 'scheme-indent-function 0)
(put 'rxmatch-if 'scheme-indent-function 2)
(put 'rxmatch-let 'scheme-indent-function 2)
(put 'syntax-rules 'scheme-indent-function 1)
(put 'unless 'scheme-indent-function 1)
(put 'until 'scheme-indent-function 1)
(put 'when 'scheme-indent-function 1)
(put 'while 'scheme-indent-function 1)
(put 'with-builder 'scheme-indent-function 1)
(put 'with-error-handler 'scheme-indent-function 0)
(put 'with-error-to-port 'scheme-indent-function 1)
(put 'with-input-convrsion 'scheme-indent-function 1)
(put 'with-input-from-port 'scheme-indent-function 1)
(put 'with-input-from-process 'scheme-indent-function 1)
(put 'with-input-from-string 'scheme-indent-function 1)
(put 'with-iterator 'scheme-indent-function 1)
(put 'with-module 'scheme-indent-function 1)
(put 'with-output-conversion 'scheme-indent-function 1)
(put 'with-output-to-port 'scheme-indent-function 1)
(put 'with-output-to-process 'scheme-indent-function 1)
(put 'with-output-to-string 'scheme-indent-function 1)
(put 'with-port-locking 'scheme-indent-function 1)
(put 'with-string-io 'scheme-indent-function 1)
(put 'with-time-counter 'scheme-indent-function 1)
(put 'with-signal-handlers 'scheme-indent-function 1)
(put 'with-locking-mutex 'scheme-indent-function 1)
(put 'guard 'scheme-indent-function 1)

;; gont-lockを有効化
(global-font-lock-mode t)

あわせて読みたい

  • あわせて読みたいブログパーツ

Lingr java-ja

ウェブページ

Powered by Movable Type 4.1