トップページ⇒tech
982コメント324KB

LISP Scheme Part4

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさんNGNG
過去スレ
Part1: http://piza2.2ch.net/tech/kako/987/987169286.html
Part2: http://pc.2ch.net/test/read.cgi/tech/1002584344/
Part3: http://pc.2ch.net/test/read.cgi/tech/1008220265/
リンクは>>2-10のどこか
0153デフォルトの名無しさんNGNG
>>152
オブジェクト生成の爆発を避けるために
256バイトとかでテーブル参照でもやってるんでしょう。
gc起動が一番コストがでかいから。
0154デフォルトの名無しさんNGNG
256個の文字で固定すれば
属性フラグ+文字で1オブジェクト2〜4バイトとして考えても
最大1024バイト程度のテーブル参照で済むから、
そういうのは積極的にやってると思う。
実際ソース読んで見ないとわからないけども。
でもgaucheは漢字も1文字として解釈するんだよね。
0155152NGNG
あっ、、eq ぢゃないや(汗

>>153-154
そういうことなんですか、実装のことまでは分からないけど。俺もいつかは
scheme 処理系書くぞ。でも今は scheme 書けるようになるのが先だけど。
0156デフォルトの名無しさんNGNG
過去ログに単語lambdaが長いとあったけど
lambda->lm
はどうよ?
(de list(lm x x))
0157デフォルトの名無しさんNGNG
schemaの処理系ねー
継続以外の処理は、すぐにでも作れるけど・・・
みんな、どうな風に作ってるんだろ?
(ソースみて勉強しないとねー)
0158デフォルトの名無しさんNGNG
lambda は lambda だから カコ(・∀・)イイ!! のに、とか言ってみるテスト。
0159150NGNG
>>151
#!/usr/bin/guile だけではできませんが、

#!/usr/bin/guile -s
!#

と書けばできます。

#! から !# までをコメントとする guile 独自の拡張らしい。
0160デフォルトの名無しさんNGNG
>>150
":"; exec gosh -b $0 "$@"

gauche だけどこれでできたから逝けるかも。-b は batch mode. 後ろの 2つ
は何だか知らないけど多分引数を渡すやつ。shell によっては変えないとだめ
かも。
0161デフォルトの名無しさんNGNG
やっぱ
#!/usr/bin/env gosh
の方が簡単かも。引数渡せるかは調べてないから調べて判ったら教えてね。
0162130NGNG
もちっとSICP読み進んでSchemeにも慣れたら
「SICP読む→ウマー」ってスレ立てようかと思ってるんですけど、お前らいかがですか。
0163デフォルトの名無しさんNGNG
scheme教えてスレはホスィ
0164150NGNG
>>160-161
":"; exec gosh -b $0 "$@"

こういう sh の書き方は知りませんでした。
#!
しかないと思ってた。
これでできるかも知れません。サンクス!
0165デフォルトの名無しさんNGNG
誰か Scheme らしいお題をプリーズ!
0166(define (x) (x))NGNG
でも盛り上がるかどうか。。。
0167デフォルトの名無しさんNGNG
このスレがpart4まで来るぐらいだから、SICP興味ある(or実際読んだ)人は少なくないのでは?
オンライン版なら誰でもアクセスできるわけだし。
0168デフォルトの名無しさんNGNG
[問題]
ある地点を(x,y,z)とあらわせるとする。
x,y,zは符号付整数。
ある地点A,B,C・・・を結ぶためのパイプを設置する事を考える。
パイプのコストはなるべく安くすませたい。
パイプは長さ1に対して、コストL円かかる。
パイプを連結するのにB円かかる。
ひとつの連結パーツで最大6つのパイプを一点で連結する事ができるが、
それぞれのパイプの角度は90*n度でなくてはならない。(nは整数)
それから、パイプの方向は(1,0,0),(0,1,0)(0,0,1)のいずれかでなくてはならない。

パイプの配置方法を求めるプログラムを作成せよ。

以上、とある高校の夏休みの宿題。

作ってくれ
0169SICP 問題1.5にNGNG
(define (p) (p))

(define (test x y)
(if (= x 0)
0
y))

(test 0 (p))

を実行してみると面白いことがわかる、と書いてあるけど、それ以前にこれ実行できないんですけど。。。。
素人目に見ても、1行目の関数定義のところが違ってるように見える。(define (p) (p))の最初のpは関数名に取られるわけだから、「引数のない関数は受付ません」というエラーが出るのも当然な気が・・・
何か間違ってるのかな? 
0170追記NGNG
プロシージャは、必ずしも引数が必要でないことはわかりました。ここは、思い違いしていました。

(define (no-argument) 5);引数なしプロシージャの定義

(no-argument);実行!

のような、引数なしのプロシージャもOKなんですな。
0171デフォルトの名無しさんNGNG
>>162-163
このスレがあるからいらない。
0172デフォルトの名無しさんNGNG
あまり沢山アンカーつけるとdatの容量が大きくなるから控えめにね。
0173デフォルトの名無しさんNGNG
誤爆スマソ。。。
0174デフォルトの名無しさんNGNG
だれかreverseをschemeで書いてちょ。
0175デフォルトの名無しさんNGNG
名前付きletで書くのと、内部定義で手続き作ってからその手続きを呼ぶよう
な手続きって同じことができる?
0176デフォルトの名無しさんNGNG
>>169
その問題は
評価の仕方が作用順か正規順かで
とまるかとまらないかということ。
0177デフォルトの名無しさんNGNG
>>174
(define (my-reverse s)
(let loop ((s s) (reversed '()))
(if (null? s)
reversed
(loop (cdr s) (cons (car s) reversed)))))
0178デフォルトの名無しさんNGNG
>>177
ありがと。簡単そうだけど書こうと思ったら書けなかった(厨
0179腰の曲がったおじいさんNGNG
>>145
> 正しくは、引数書き換え&goto文 だと思われ。

書き換えはatomicに起きます。
0180177NGNG
>>178
一筋縄でいかないと思ったら、問題を分割すると良いですよ。
reverse みたいに下請けを用意するとか、相互再帰する手続きを作るとか。
偉そうな事いえた器じゃないですけど。
0181デフォルトの名無しさんNGNG
>>161
の方法でも大丈夫なようです。

$gosh -V
Gauche scheme interpreter, version 0.4.10

で、引数を取れることを確認しました。確認したのは、附属していたドキュメン
トのまんまですが ↓ です。

---- ここから
#!/usr/bin/env gosh

(define (main args)
(if (null? args)
(copy-port (current-input-port) (current-output-port))
(for-each (lambda (file)
(call-with-input-file file
(lambda (in)
(copy-port in (current-output-port)))))
args))
0)
---- ここまで
0182デフォルトの名無しさんNGNG
>>180
相互再帰って何?
二つの関数がお互い同士を呼び合って、再帰するやつだったっけ?
できればサンプルプログラムを使って教えてください。
(相互再帰って3つ以上の関数同士でも出来るのかな?)
0183デフォルトの名無しさんNGNG
>>182
「なんでも再帰」とかおもしろいよ。
http://www.shiro.dreamhost.com/scheme/index-j.html
0184177NGNG
>>182
そうですね。複数個の手続きを通して再帰される場合、相互再帰。

1. 対等な関係にある 2 つの状態を調べる述語を書くとき。
典型的なのは、偶数と奇数を調べるもの。実際には letrec を使うのが
良いかも。

(define (my-even? n)
 (if (= n 0)
   #t
   (my-odd? (- n 1))))

(define (my-odd? n)
 (if (= n 0)
   #f
   (my-even? (- n 1))))

2. 手続き呼出。eval をするためには apply をしなければならないが、
apply をするためには引数を eval しなければならない。

3. S 式の解析。手続き read はデータをひとつ読みますが、

データ → アトムかリスト
リスト → データ、データ、データ...

なので、read とペアになる read_form でも定義して、それらを相互再帰
させます。

他にも色々使えると思いますが、慣れるとスイスイ相互再帰な手続きが
書けるようになります。
0185デフォルトの名無しさんNGNG
>>181
mit-scheme ではできたの?
0186177NGNG
要は入れ子のデータ構造を解析・解釈するような場合ですね。
長々とすみません。
0187デフォルトの名無しさんNGNG
>>174
(define (foldl bop iv ls)
 (if (null? ls)
   iv
   (foldl bop (bop iv (car ls)) (cdr ls))))
(define (my-reverse ls)
 (foldl (lambda (y x) (cons x y)) '() ls))
0188182NGNG
>>177
しんせつな解説有難うございます。
相互再帰かー。かっこいいなー。

リストと再帰を使いこなせるように精進します。
(zipとか使いこなせると括弧良いねー)
0189デフォルトの名無しさんNGNG
>>183
「なんでも再帰」
なんと相互再帰つかうと、関数と状態が1対1対応出来るんですね。
関数型プログラミングのパワー炸裂ですね。
0190デフォルトの名無しさんNGNG
>>188

>括弧良いねー

(((・∀・)))イイ!
0191デフォルトの名無しさんNGNG
「なんでも再帰」の一番最後の count-words の in-paren っていう手続きは
おかしくないですか?括弧はネスト可能ってなってるけど括弧ネストしてあっ
たらエラーになる。
0192191NGNG
>開き括弧が出て来たら、閉じ括弧が出て来るまでを 一単語とみなす。但し、
>括弧はネスト可能、つまり、 `abc (def (ghi) jkl) mno' は、`abc', `(def
>(ghi) jkl)', `mno' の3単語とみなすんだ。 但しダブルクオートで囲まれた
>文字列の中では括弧は機能しないとする。さてどうだ。

(define (count-words)
(define (in-word c count)
(cond ((eof-object? c) count)
((char-whitespace? c) (in-space (read-char) count))
((char=? c #\") (in-quote (read-char) (+ count 1)))
((char=? c #\() (in-paren (read-char) (+ count 1)))
(else (in-word (read-char) count))))
(define (in-space c count)
(cond ((eof-object? c) count)
((char-whitespace? c) (in-space (read-char) count))
((char=? c #\") (in-quote (read-char) (+ count 1)))
((char=? c #\() (in-paren (read-char) (+ count 1)))
(else (in-word (read-char) (+ count 1)))))
(define (in-quote c count)
(cond ((eof-object? c) (error "EOF in quoted word"))
((char=? c #\") (in-space (read-char) count))
((char=? c #\\) (read-char) (in-quote (read-char) count))
(else (in-quote (read-char) count))))
(define (in-paren c count)
(cond ((eof-object? c) (error "EOF in parenthesis"))
((char=? c #\() (in-paren (read-char) count) (in-paren (read-char) count))
((char=? c #\)) (in-space (read-char) count))
((char=? c #\") (in-quote (read-char) count) (in-paren (read-char) count))
(else (in-paren (read-char) count))))
(in-space (read-char) 0))
0193191NGNG
abc (def (ghi) jkl) mno は3語になるんだけど
in-paren が #\) を見つけたときに in-space に跳んでっちゃうからいけない
んだと思うんだけどどうですか?
0194LisperNGNG
今マ版のLispスレageて来たからそっちにも行ってケロ
0195デフォルトの名無しさんNGNG
マ板つまんない。。。
0196デフォルトの名無しさんNGNG
schemeは入出力が弱いらしいですがお前らどうですか?R5RSにある機能だけで
作ったファイルを消したいときはどうやるんですか?
0197デフォルトの名無しさんNGNG
あなたは、Common LispとSchemeどちらを愛してますか?
0198RubyistNGNG
Ruby!
0199デフォルトの名無しさんNGNG
>>196
http://www.shiro.dreamhost.com/scheme/docs/schemersway-j.html

↑Schemer's way の Schemeプログラミングへがその質問へ回答かと。

話は変わるけど、Scheme FAQ を Scheme の勉強がてら翻訳しています。
プログラミング初心者なもので、難儀しています。
既に、日本語訳がありましたら、参考にしたいので教えて下さい。

http://www.schemers.org/Documents/FAQ/
0200デフォルトの名無しさんNGNG
>>198
ここではSchemerとでも名乗ってください
0201デフォルトの名無しさんNGNG
(assert (or schemerp lisperp))
0202デフォルトの名無しさんNGNG
お前らschemeで何して遊んでるんですか?
0203デフォルトの名無しさんNGNG
schemeを作るための勉強をしたいのですが、ソース公開してるシンプル
な処理系ってどんなのがあります?
0204デフォルトの名無しさんNGNG
>203
SICPの4章
は冗談として、シンプルな処理系としてSECDR-Schemeはどうかな。
SECDマシンという仮想機械にバイトコンパイルして動作する。
あとmini-schemeとか。ソースコード1ファイルで約2500行
当然だけど、継続や末尾再帰もサポート。
どっちも昔niftyのFPLにあったけど、多分Webでも拾えると思う。
Tiny-Schemeはmini-schemeのコードを元に作ってるみたいだし。

Tiny-Scheme
http://tinyscheme.sourceforge.net/
0205デフォルトの名無しさんNGNG
mini-scheme
http://tinyscheme.sourceforge.net/minischeme.tar.gz
0206デフォルトの名無しさんNGNG
>>204
SICPの4章にのってるんですか?今webのやつ3章まで読んでるんですが。4章楽
しみだな。
>>205
ありがとうございます。今から見てみます。
0207デフォルトの名無しさんNGNG
>181
> Gauche scheme interpreter, version 0.4.10

えーん。あたらしいのにしようよー。
0208デフォルトの名無しさんNGNG
>>205
良いね!
0209デフォルトの名無しさんNGNG
みんな、僕もっと大きくなったら schemacs を作るよ。待っててね。
0210デフォルトの名無しさんNGNG
http://gemacs.sourceforge.net/ とはちがうの?
0211デフォルトの名無しさんNGNG
Guile Emacs
発音するとゲマクス。
カコワルイ
0212デフォルトの名無しさんNGNG
guile emacs って make できない。。。
0213デフォルトの名無しさんNGNG
>207
Gauche は今 0.5.2 になってるね。
0214デフォルトの名無しさんNGNG
schemeやってる人って少ないのかねぇ。
厨房増えまくっても嫌だけど。
0215デフォルトの名無しさんNGNG
まだマクロを書いたことがない初心者なんですけど,
Haskellで言うところのリスト内包表記をマクロで定義することもできるんですかね?
たとえば,1..10のうち偶数を取り出すというのをリスト内包表記で表すと
[x | x <- [1..10], even x]
のように,数学の式と同様に表現できます.
内容は,| 以降の条件をすべて満たしたxの集合を表します.
こういうシンタックスシュガーは,Schemerは好まないものですかね?
0216デフォルトの名無しさんNGNG
Haskellっておもろい?
ってスレ違いか。
0217デフォルトの名無しさんNGNG
The Little Schemerをamazon.co.jpで頼んじゃった
まだ全然Schemeを使いこなせてないのにぃ
0218デフォルトの名無しさんNGNG
>>217
お。奇遇だね。俺もたった今注文してきたとこだよ。
俺もschemeまだまだわからないけど。多分あの本ってこれからschemeをやろうっ
ていう人が読むような本なんじゃないかな。
0219デフォルトの名無しさんNGNG
Little Schemerは名著です。
0220デフォルトの名無しさんNGNG
しばしば「Common Lisp は実践的、Scheme はアカデミック」みたいな事が
書かれている文書を見るのですが、何がそう言わしめているのでしょうか。
個人的には、Scheme は十分実践的だと思っています。
Common Lisp ライブラリ関数の膨大さ故でしょうか。

0221デフォルトの名無しさんNGNG
Common Lisp には Allegro CL があるから
0222デフォルトの名無しさんNGNG
Chez Schemeはダメなんだろうか.
0223デフォルトの名無しさんNGNG
>>220
> 個人的には、Scheme は十分実践的だと思っています。
「個人的」だからじゃないかな?
0224デフォルトの名無しさんNGNG
gaucheを「日常業務の中でのちょっとした処理を行うスクリプトを気軽にScheme
で書」くために使わせてもらっています。というか勉強中です。
0225デフォルトの名無しさんNGNG
>>220
Common Lisp は remove と delete, reverse と nreverse といったように、
同じ動作で効率を重視した破壊的関数が用意されているあたり実践的なんじゃないかな。

あと、一つの関数でもキーワード引数で
* (remove 2 '(1 2 3 1 2 3))
(1 3 1 3)
* (remove 2 '(1 2 3 1 2 3) :count 1)
(1 3 1 2 3)
* (remove 2 '(1 2 3 1 2 3) :count 1 :from-end t)
(1 2 3 1 3)
* (remove 2 '(1 2 3 1 2 3) :test #'>)
(2 3 2 3)
と使いでがあるあたりも。
0226220NGNG
>>223
「僕の個人的な意見としては」という意味だったんですが。
それとも「個人的な意見」に留まってしまっているのが原因、と?

>>225
なるほど。他にも &optional のような、一見クリーンでなくても実践的な
仕様がありますね。なにも「Scheme は実践的ではない」という意味で
捉えなくても良いって事でしょうかね。
0227Gauche しゅごーい。NGNG
>>224
俺と同じ人がいた。
0228デフォルトの名無しさんNGNG
Schemeで質問です。
let/let* と letrec の違いがいまいち理解できてないのですが、

let/let* はclosureが評価された値をバインド
letrec はclosureそのものをバインド

という理解でいいのでしょうか?
0229デフォルトの名無しさんNGNG
ちがいます。>228
0230デフォルトの名無しさんNGNG
>>228
これでも読みませう。
http://www.stdio.h.kyoto-u.ac.jp/~hioki/gairon-enshuu/SchemeNotes/let.html
0231デフォルトの名無しさんNGNG
>>228
このスレのPart3(いま見えないけど)にあったvarマクロ使ってるけど、
あれネストが減っていいですよ。
(var a 1
var b 2
var c (+ a b)
c
)
=>3
0232デフォルトの名無しさんNGNG
誰か call/cc で java 風な例外処理できるやつ書いて見せてくれないかなぁ。。
とか逝ってみるテスト
0233デフォルトの名無しさんNGNG
>>232
(try
...(throw tag)
catch tag
...
finally
...)
って感じのならあるけど、アプしようと思って、今読み返したら、
結構長かった。
作りは、
・lispのcatch & throwのエミュ
・lispのunwind-protectのエミュ(javaのfinallyに対応)
・(try ... catch ... finally)を許す様に簡単な構文変換
の組み合わせで、
catch/throwはcatchで継続と一緒にタグをグローバルな変数へ登録、
throwでその変数を検索といった感じです。
0234デフォルトの名無しさんNGNG
>>233
call/cc の使い方について、ループからの脱出以外にどんなものがあるかを知
りたいので、
>・lispのcatch & throwのエミュ
だけ良かったら見せてもらえますか?これも長くなりますか?
0235233NGNG
>>234
(define -*-root-*- '()) ;トップレベルに戻るための環境
(call/cc (lambda (cont)
 (set! -*-root-*- cont) ))

(define *exception* '()) ;例外補足用のtag環境リスト
;(catch <tag> . cont)または
;(catch all . cont)または
;(finally . cont)

(define (throw-value tag result)
 (let loop ((x *exception*))
  (if (pair? x)
   (cond
    ; catch <tag>
    ((and (eq? (caar x) 'catch) (eq? tag (cadar x)))
     (set! *exception* (cdr x))
     ((cddar x) result))
    ; catch-all
    ((and (eq? (caar x) 'catch) (eq? 'all (cadar x)))
     (set! *exception* (cdr x))
     ((cddar x) result))
    ;finally
    ((eq? (caar x) 'finally)
     ((cdar x)) ; finally
     (set-cdr! (car x) (lambda())) ; dmy-closure
     (loop (cdr x))
    )
    (else (loop (cdr x)))
   )
   (begin
    (set! *exception* x)
    (puts "Cannot throw tag and perform a reset"
     (list 'throw-value tag result))
    (-*-root-*- result)
   ))))
0236233NGNG
;sequenceかどうか
(define (sequence? l)
 (and (pair? l)
    (pair? (cdr l))))

;sequenceを置けるthrow (throw tag seq...)
(define-macro (throw tag . body)
 (list 'throw-value tag
  (if (sequence? body)
    (cons 'begin body)
    (car body))))

(define (lisp-catch tag body)
 (call/cc (lambda (cont)
  (set! *exception* (cons (cons 'catch (cons tag cont)) *exception*))
  (throw-value tag (body)))))

(define-macro (catch tag . body)
 `(lisp-catch ,tag (lambda () ,@body)))

(define (call-with-catch tag test catch)
 (let ((throw? #t))
  (let ((result
   (call/cc (lambda (cont)
    (set! *exception* (cons (cons 'catch (cons tag cont)) *exception*))
    (throw-value tag (prog1 (test) (set! throw? #f)))))))
   (if throw?
    (catch result)
    result))))

(define (unwind-protect test finally)
 (let ((current *exception*))
  (push (cons 'finally finally) *exception*)
  (let ((r (test)))
   (set! *exception* current)
   (finally)
   r)))

0237233NGNG
>>236
>(define-macro (catch tag . body)
> `(lisp-catch ,tag (lambda () ,@body)))

(define-macro (catch tag . body)
 `(lisp-catch ',tag (lambda () ,@body)))
でした。
0238234NGNG
>>235-237
ありがとうございます。今から研究します。
0239デフォルトの名無しさんNGNG
CommonLispの本、出た?
0240デフォルトの名無しさんNGNG
>ANSI Common Lisp入門 
> -5月下旬発売予定-
http://www.pearsoned.co.jp/washo/nbindex_may.html
0241デフォルトの名無しさんNGNG
Schemeって最初は継続ってなかったんでしたっけ? だからSICPには載ってな
いとかこのスレかどっかで見た覚えがあるんですが。
0242デフォルトの名無しさんNGNG
SICPの4章のschemeインタプリタを
継続対応にするにはどうすればいいんですか?
0243デフォルトの名無しさんNGNG
GUYの論文よめ
0244デフォルトの名無しさんNGNG
λμ計算ってなに?
継続や例外処理が使えるようにλ理論の拡張したものらしいけど・・
何か参考になる本、Web無い?
誰か教えてー。
0245デフォルトの名無しさんNGNG
論文はたくさんあるけど、本は知らないなあ。スマソ。
かわりといっては何だがhttp://www.cs.uu.nl/~franka/refでもどぞ。
プログラミング言語理論のオンラインテキスト集。(既出か?)
0246デフォルトの名無しさんNGNG
http://www.shiro.dreamhost.com/scheme/trans/being-popular-j.html

Lisperらしき人がCommon Lispをボロクソに言っているように見えますが、こ
のスレのLisper/Schemerな人たちどう思いますか?
Schemeはhackerのための言語でしょうか。ライブラリが充実しているかどうかっ
ていうところが問題かな?
0247デフォルトの名無しさんNGNG
もしかして既出だったらごめん。
0248デフォルトの名無しさんNGNG
 商業的な利用が少ないのもそこら辺が一番のネックなのだろうか。
 >ライブラリが貧弱
0249デフォルトの名無しさんNGNG
これって2001年に書かれたんだよね。
schemeについて全く触れられてないけど。。。
0250デフォルトの名無しさんNGNG
>>246
Gauche の開発者の人の訳文だし、このスレの人は結構見てるかも。
Common Lisp への批判は、今日の Java への批判に通じる物があるね。
この文章を書いたた人は Python が好きそう。
0251デフォルトの名無しさんNGNG
Common Lisp について批判しているのは、便利なライブラリが揃っていないのと
ハックに使いにくい事みたいだけど、本当ですか?
0252デフォルトの名無しさんNGNG
Common Lispでコードを書き始めると、最後までCommon Lispで仕上げる
ことになりがち。他の言語やツールと連携することは、可能ではあっても、
快適にできるというわけではないから。だからハック向きの言語ではない
と言って良いと思う。Perl/Python/Rubyは他の言語やツールと連携する
のが得意だし、カンタンな処理はごく短いコードで書けるから、ハック向
きの言語だよね。

件のページに書かれているように、今すぐ書いて処理したい仕事では、文
字列処理がその多くを占める。だから強力な文字列ライブラリのある言語
は「実用的」だと言えるよね。Common Lispはそうじゃない。カンタンな
フィルタプログラムを書こうと思っても、そんなにカンタンじゃない。
UNIX文化にどっぷりつかっている言語と、OS側の機能を前提としない言語
の違いと言ってもいいかもね。
■ このスレッドは過去ログ倉庫に格納されています