yasu
こんにちは。やすといいます。
Schemeを勉強中ですが、まだメリットが良く分かりません。このままだと、再帰のお勉強はするけど、実際には使わないということになりかねません。(^^; まずは、使ってみます!
2002/06/05
(2003/06/02 21:54:33 PDT)下の方法でオブジェクトが作成できません。make <~> は分離ができないのでしょうか?
(define def '(<Dog> :name "pochi" :age 3))
(apply make def)
=>*** ERROR: no applicable method for #<generic make (1)>
with arguments (<Dog> :name "pochi" :age 3)
(define def '(:name "pochi" :age 3))
(apply make <Dog> def)
=>OK
P.S. Gauche0.7リリースおめでとうございます
- Shiro: (apply make <Dog> def)という場合の<Dog>は単なる変数で、
makeに渡される実態はdefine-classで作られた「クラスそのもの」である
オブジェクトです。一方、エラーになる方ではシンボル'<Dog>が渡されています。
シンボル'<Dog>には何ら特別の意味はありません。Schemeでは情報の担い手は
常にオブジェクトそのものであって、便宜上それが変数に束縛されている
だけなのです (関数もそうですね)。
以下を試してみてください。
(define var <Dog>) ;; クラスそのものをvarに束縛
(make var :name "pochi" :age 3) ;; 動作するはず
(define def (list <Dog> :name "pochi" :age 3))
(apply make def) ;; これも動作するはず
- yasu: 「クラスそのものをvarに束縛」、理解しました。ファイルからインスタンスを作れました。makeが「<Dog>」というシンボルを理解してオブジェクトを生成する訳ではないんですね。都合よく理解してました(^^;
[dog.txt]
(<Dog> :name "pochi" :age 3)
gosh> (define l (with-input-from-file "dog.txt"
(lambda ()
(car (port->sexp-list (current-input-port))))))
gosh> (define (make-dog l)
(let ((c (eval (car l) (interaction-environment)))
(p (cdr l)))
(apply make c p)))
gosh> (make-dog l)
[メモ]
CGI(escm)プログラミングにおいて、sys-getenvは使えなかった。cgi-parse-parametersを使うこと。
(ただし、(sys-getenv "HTTP_ACCEPT_LANGUAGE")は使えた)
NG
(display (sys-getenv "HTTP_COOKIE"))
OK
(display (cgi-parse-parameters :query-string "" :merge-cookies #t) )
(2002/12/21 19:14:36 PST)
Shiro (2002/12/23 06:01:35 PST): あれれ。
cgi-parse-parametersも中では結局sys-getenvを呼んでいるんですが、
なんででしょ。どんな不都合が出ましたか。
[メモ]
CGIプログラミングにおいて、random-integerを使うと同一値が発生する。当然、インタラクティブセッションでは乱数が発生する。CGIにおいてはmt-random-integerを使うこと。
NG
(random-integer 10000)
OK
(define m (make <mersenne-twister> :seed (sys-time)))
(mt-random-integer m 100000)
Shiro: あれ、(random-source-randomize! default-random-source)すれば
いいはず…と思って確かめてみたら、それでも同一シーケンスになりますね。
mt-random-set-seed!にバグがある模様。→Gauche:Bugs
(2002/12/21 16:45:01 PST)
- ううっ、はじめてお役に立てたかも。みなさんと同じく、「パッチを送ります」と言えるようになりたい。。早速、対応していただき、ありがとうございます。
- ところで、lisp的デバックノウハウとかデバック定石集についての資料を探しています。実は、私はjavaみたいな手とり足とりのエラーメッセージがないとデバックが難しいです。そう言えば、昔2chで「traceを使え」ってのがありましたが、Gaucheではサポートされてないし。初学者が、スタックトレースに取り組むときの取っ掛かりがほしいです。(^^;
(2002/12/21 19:14:36 PST)
早くも2002年を振り返ってみます。今年、やっとSchemeでCGIプログラミングができるようになりました。いろいろなアドバイスをしていただき、感謝です。
そこで、いっぱし気取りで語ります。小さなプログラムなので、速度に不満はないです。でもCGIプログラミングをやっていると、リクエスト毎にSlibのデータベースを読みにいくようなコーディングは気持ち悪いです。やっぱり、Tomcatみたく、マルチスレッドで動いて、コネクションプールも用意したいです。
来年は、Schemeのマルチスレッドと関数プログラミングの深い部分にタッチしたいです。来年もよろしく、お願いします。_o_
2002/12/12 05:36:35 PST
- Shiro (2002/12/12 10:38:13 PST): 簡単な方法としては、persistentなSchemeサーバを
立ち上げておいて、CGIは単なるブリッジプログラムでSchemeサーバにつなぐだけ、
ということができますね。DBはサーバーのメモリに置いとけるので高速です。
ただ、サーバにしてしまうと、常に立ち上げておかねばならないという管理上の
負担も発生するので善し悪しですね。以前同様の方法で社内のミーティング
スケジュール管理システムを作っていました。小さなパッチくらいなら
落とさずにコードフラグメントをロードさせれば済みますが、多少規模の
大きな変更になるとやっぱり書き直して再立ち上げ、という手順が必要で、
かなり頻繁にアクセスされるシステムだったので再立ち上げにもいろいろ
面倒なことがありました。で、結局version 2では全てCGIスクリプトに
してしまいました。ただ、ほとんど最近のデータしか参照されないという
性質があったため、DBを最近のデータと過去のデータに分けて、
CGIでは基本的に最近のデータのみを読みに行くようにしていました。
[Q]下のコードを使ってfoo.cgiを実行したいのですが、foo.cgiがescmの場合にエラーが発生します。何が問題なのでしょうか。(2002/10/29)
=> *** ERROR: Read error at "(stdin)":line 8: extra close parenthesis Stack Trace:
(html:form :method "POST" :name "form1" action "foo.cgi"
(html:input :type "hidden" :name "command" :value "doThat")
(html:a :href "#" :onClick "document.form1.submit();return false" "実行"))
[同じ事をhtmlで書くと]
<FORM method=post name="form1" action="foo.cgi">
<INPUT type=hidden name="command" value="doThat">
<A HREF='#' onClick="document.form1.submit();return false">実行</A>
</FORM>
[Q] CGIプログラムで使えるグラフ作成のライブラリってあるでしょうか? (2002/10/06)
- skimu: GGC の ggc.skimu.frame-buffer がモトネタになるかもしれません。ビットマップに適当にお絵書きして ppm にすることができます。 netpbm や cjpeg が使えれば gif や jpg にもなります。 それ以外では gnuplot を呼び出して tiff を吐かせるか。。。
- yasu: GGCってそんなことができるんですね。と思って触ってみたら、動かし方がわかりませんでした。ううっ。まずは、SVGでグラムを作ってみました。ご指摘、どうもありがとう。
[Q] 環境変数へのアクセス方法はありますか? (2002/09/25)
CGIを使っていると、$ENV{'HTTP_ACCEPT_LANGUAGE'}というような環境変数を使いたくなります。Gaucheではどのような方法があるでしょうか?
- Shiro: sys-getenvという手続きがあります。
- ありがとうございました。使えました。ところで、ページが大きくなると少し不安定な動きがあるんですが、みなさんの環境でもそうでしょうか?(ブラウザのせいかな?)yasu(2002/09/30)
Gaucheでデータベースを使ってみる (2002/09/20)
犬飼さんの「入門Scheme(公開版)」を参考にして、データベースを使ってみました。
(Slib編)
(use slib)
(require 'database-utilities)
(define zrdb (create-database "zosho.db" 'alist-table))
;; デスクリプタを定義
((((zrdb 'create-table) '*nengo-table-desc* '*columns*) 'row:insert*)
'((1 #t 年号 symbol? symbol)
(2 #t 始め #f uint) ;変更前 (2 #t 始め #f uint)
(3 #t 終り #f uint))) ;変更前 (3 #f 終り #f uint)))
;; テーブルの定義
(((zrdb 'create-table) '年号テーブル '*nengo-table-desc*))
;; テーブルのクローズ
((zrdb 'close-database))
;; テーブルのオープン
(define zrdb (open-database! "zosho.db"))
;; 追加
((((zrdb 'open-table) '年号テーブル #t) 'row:insert*)
'((元治 1864 1865)
(慶応 1865 1868)
(明治 1868 1912)
(大正 1912 1926)))
((zrdb 'write-database) "zosho.db")
;; 追加
((((zrdb 'open-table) '年号テーブル '年号デスク) 'row:update)
'(文久 1861 1864))
;; ブラウズ
(require 'database-browse)
(browse zrdb)
((((zrdb 'open-table) '年号テーブル #f) 'for-each-row)
(lambda (row)(write row)(newline)))
;; => 表示される
;;ここをコメントアウトしました ((zrdb 'close-database))
;; 検索
(define z-open ((zrdb 'open-table) '年号テーブル #f))
((z-open 'get* '年号))
;; => (文久 大正 明治 慶応 元治)
((z-open 'row:retrieve*) '明治)
;;=> ((明治 1868 1912))
;; 「1912」年に「始め」のrowを見つける
((z-open 'row:retrieve*) #f '1912)
;; => *** ERROR: too many keys: (#f 1912)
これって、Slibの仕様変更かな?
Shiro: あれれれ。私のところ(Gauche 0.6.2+slib 2d4)だと上の「検索」
のところでエラーになってしまいました。
slibのコードは高階関数を使いまくりで抽象化しているので、何をやっているのか
追うのがしんどいですな。ぼちぼち見てみます。(2002/09/20 02:10:16 PDT)
- それは、その上でクローズしていたからでした。修正しました。yasu
- Shiro: ああ、私もslibのDBの仕様を理解していませんでした。
コードを追っててようやくそれ(クローズ)に気づきました。
で、最後のエラーですが、ディスクリプタ定義のところでキーを年号にしか
設定していないからじゃないでしょうか。次のようにしたら動きました。
((((zrdb 'create-table) '*nengo-table-desc* '*columns*) 'row:insert*)
'((1 #t 年号 symbol? symbol)
(2 #t 始め #f uint)
(3 #t 終り #f uint)))
((z-open 'row:retrieve*) #f #f 1912)
;; => ((明治 1868 1912))
Gaucheを使ってオブジェクト指向してみる
(define-class point ()
((x :init-value 1 :init-keyword :xx :accessor xxx)
(y :init-value 2 :init-keyword :yy :accessor yyy))
)
(define-method move ((p point) dx dy)
(inc! (slot-ref p 'x) dx)
(inc! (slot-ref p 'y) dy))
(define-method write-object ((p point) port)
(format port "[point ~a ~a]"
(slot-ref p 'x)
(slot-ref p 'y)))
(define i (make point)) ;; Point i = new Point() <java>
(define j (make point :xx 10 :yy 20)) ;; Point j = new Point(10,20) <java>
(xxx j) => 10 ;; j.xxx()
(yyy j) => 20 ;; j.yyy()
(slot-ref i 'x) => 1
(slot-ref i 'y) => 2
(move i 100 200)
=> *** ERROR: no setter defined for procedure #<subr slot-ref>
(inc! (slot-ref i 'x) 1)
=> *** ERROR: no setter defined for procedure #<subr slot-ref>
- なんでかな?(2002/09/04)
- 参照透過性とオブジェクト指向の素敵な関係ってのを理解したいです(あれば)。
- Shiro: あれ??? Gaucheのバージョンはいくつですか。 (setter slot-ref)
を実行して #<subr slot-set!> が返って来ませんか? (2002/09/04 00:28:05 PDT)
- Version 0.5 であったので、0.6.2にバージョンアップしたら解決しました。助かりました!(2002/09/04) --yasu
- Shiro: Gaucheのオブジェクトシステム (CLOS由来) はばりばりにmutable
なので、参照透過性とはちと相性が悪いです。
- なるほど相性は悪いんですかー。そーですよね、オブジェクト指向はget,setを使わずには多くのことができなそうですものね。「関数プログラミング」R.Bird,P.Wadler著で勉強中なのですが、参照透過性の取り扱いが理解できてません。例えば、「住所録プログラム」で住所が変わった場合、どうするんだろう?等です。参照透過性を使うプログラムでは、オブジェクト指向での状態遷移なんてのは不要になるという予想ですが、じゃーどーするのってのは不明なんです。ご助言をお願いします!(2002/09/04) --yasu
- Shiro: comp.lang.schemeに、副作用を使わないオブジェクトシステムの分かりやすい例が投稿されていました。参考迄。(2002/11/03 16:17:32 PST)
これでええのんかいなTip「escmでパラメータを使う」 (2002/09/04)
- 適当にやったら、動きました。なぜかは不明です。(^^;
- Shiro: cgi-mainがQUERY_STRING等を読みに行っているためです。
ただ、cgi-mainはエラーが起こった時にエラーページを生成したりもしますし、いちいちlambdaを書くのも面倒でしょう。
escm内で使うなら、(define param-list (cgi-parse-parameters)) とかどうですか。(2002/09/05 03:56:10 PDT)
- (define param-list (cgi-parse-parameters))がいいです! 下コードでは、(set! param-list params)で出力ページにparam-listが表示されていたし(^^;
#! /usr/local/bin/escm -c
#? /usr/bin/gosh
Content-type: text/html
<head></head>
<?
(use www.cgi)
(define param-list ())
(define (main args)
(cgi-main
(lambda (params)
`(,
(set! param-list params)))))
(main '())
!>
<head></head>
<body>
<?
上の手続きにより、param-listを使えました。
!>
</body></html>
[Q]Schemeを用いたWebアプリケーションの作成では、Webフレームワーク(Struts,Turbine,etc)のようなものがあれば便利ではないでしょうか?
Webフレームワークには以下のようなメリットを列記してみます。
- CGIではなく、スレッドプールを用意して、レスポンスを改善する(←→Servlet)
- DBの実装に依存しないメカニズム(←→JDBC,EJB)
- セッション関連(←→ActionFormBean by Struts)
- 国際化対応のメッセージメカニズム(←→MessageResource)
- 柔軟性(←→Action Mapping)
- 分散処理(←→RMI)
- Schemeの場合も、MVC2という考え方は有効かな?
- (Shiro) Schemeをメジャーに押し上げるのに、良いWebフレームワークを
提供するのはいいかもしれませんね。誰かやっていそうな気もするけれど、
今のところ知りません。Schemeで書かれたhttpdはあるみたいですが。
何か思い付いたらアイディア交換しましょう。(2002/07/23 07:03:28 PDT)
- JavaのWebフレームワークはSchemeでも有効か、それともSchemeの特徴を活かしたアプローチがあるのか、興味があります。--yasu
- Tomcatでは3つのタイプのコンテナがあります。Schemeでの開発をするのならば** [Q]Schemeを用いたWebアプリケーションの作成では、Webフレームワーク(Struts,Turbine,etc)のようなものがあれば便利ではないでしょうか?
- Webフレームワークには以下の、簡単のためにまずは「スタンドアロン」的なものが良いのかな。--yasu
- スタンドアロン型S** [Q]Schemeを用いたWebアプリケーションの作成では、Webフレームワーク(Struts,Turbine,etc)のようなものがあれば便利ではないでしょうか?
- Webフレームワークには以下のようなメリットを列記してみます。
- プロセス内Servletコンテナ
- プロセス外Servletコンテナ
- 以前Schemeによる動的なWebサイトを見たことがあります。リクエストごとの状態を継続として保存しておいて、クライアント側がブラウザの「戻る」ボタンで戻ると、サーバー側もコンテキストを戻して以前の状態からやりなおせるという非常に面白いものだったのですが、どこだったか忘れてしまいました。--SHIMADA
- 「継続」使ってるのですか。まだメリットを理解してないです(^^; それにしても、SchemeはMOPとかマクロとか奥深いですね~。私はGaucheを使ってCGIしていますが、これも十分に楽しいですね。
--yasu (2002/08/28)
[Q] Gaucheに適した「html->sexpr」、つまりtext.html-liteとの相性のよい「html->sexpr」はどんなものでしょう? (2002/08/28)
- 複雑なhtmlファイルを生成する場合には、Scheme版JSPの最高峰escm様が素晴らしいです。でもcgi-mainを使いたい場合、html->sexprが必要になるんです。
- それにしても、XML+javaよりもS式+Schemeの方が断然いいです。「HaXmlがいい!」っていう論文もあるようだから、やっぱり関数型が・・・。
Schemeを用いたhttpdのメリットは、実装によって異なるので、一概には言えません。しかし、既存製品のプロモーションの内容から、おおよその特徴が予測できそうです。
- AllegroServe
- LispacheWebServer
- ダイナミックコンテンツに最適設計された高速動的 Web サーバ
- CGI 処理を高速、高効率に処理
---サーバ自身のバージョンアップや CGI 更新時にも無停止の動的完全無停止パッチ機能
---フルマルチスレッド技術により、CGI 処理を高速かつ効率よく実現 ? セキュアかつ高速性を要求される大容量コンテンツ処理に最適
- ロードバランサによる高度なスケーラビリティと多層の粒度カスタマイズ性に優れる。
汎用的なScheme用UnitTestツールは見つけられませんでした。
- gauche.testって見つけた。これ、ひっとして・・!? --yasu
- ごく簡単なテストフレームワークです。ツールと呼べる程のものでもありませんが。
Gauche自身のテストがソースファイルのtestディレクトリ以下にあるので
使い方の参考になるかもしれません。APIは汎用的ですが、実装はGauche依存ですShiro
- 御回答、ありがとうございます。チェックしてみます!--yasu(2002/08/28)
[Q]Schemeはオブジェクト指向を必要としないのか?
Schemeの表現は、メソッドが列記されているだけで、人間に優しい形になっていないように見えます。オブジェクト指向のように、人間のイマジネーションを刺激するような形にはなるのでしょうか? それとも関数型プログラミングでは、人間のイマジネーションを刺激しなくてもよく、ただ数学的であるだけで全部解決できてしまうのでしょうか?
(define animal-human-run (略))
(define animal-human-eat (略))
- 大変ためになる説明をありがとうございます。何度も読み直して、完璧に理解します。(^^;
--yasu
- Schemeの関数型プログ
ラミングのアプローチとオブジェクト指向は両立するという説明については納得しました。次は自分で使ってみて、さらに納得してみます。--yasu
- X.a()形式のshiro.run()は、英語(典型的な自然言語?)のMr.Shiro run ... と並びが同じです。したがって、X.a()形式のオブジェクト指向的な表記は英語に似ているという意味で、「自然」だと思います。一方、schemeはオブジェクト指向プログラミングで言うところのメソッド、関数名から始まります。これは英語とは並びが異なり、その意味で「自然」には感じられない、というOOな人は多いでしょうね。私としては、並び順の相違はそれ以上のものではないと思いました。--yasu
Last modified : 2012/02/23 03:57:25 UTC