[Lisp] Common LispとSchemeの関数対応表

Common Lispの関数やマクロと対応する機能を持つSchemeの手続きや構文を表にまとめる. 随時更新. Common Lisp Scheme 備考 atom なし (not (pair? obj))を使う consp pair? dolist for-each 記法は異なる mapcan append-map!  SRFI 1 mapcar map multiple-value-bind receive SRFI 8, library syntax null null? nth list-ref nthcdr list-tail SRFI 1ではdrop progn begin rplaca set-car! Continue reading [Lisp] Common LispとSchemeの関数対応表

[並行計算][Scheme][Racket] SRFI 18のmutexとcondition variable

RacketはSRFI 18に対応していることになっているが、mutex-lock!やcondition-variable-signal!などどの手続きはrequireしても定義されない。 mutexやcondition variableのような同期機構ではなく、チャネル通信などの機構を使えということなのだと思うが、ロックを使ったほうが素直に実装できる場合もある。 幸いセマフォはあるようなので、セマフォでmutexやcondition variableを次のように書いた。 ;;; mutex (define (make-mutex) (make-semaphore 1)) (define (mutex-lock! m) (semaphore-wait m)) (define (mutex-unlock-primitive! m) (semaphore-post m)) (define (mutex-unlock! m . rest) (let ((condvar (if (null? rest) #f (car rest)))) (mutex-unlock-primitive! m) (when condvar (condition-variable-wait! Continue reading [並行計算][Scheme][Racket] SRFI 18のmutexとcondition variable

[Scheme][Racket] set-car! set-cdr! が使えない

racket コマンドで起動した Racket では set-car! や set-cdr! が定義されていなかった。 調べてみると Racket ではペアへの破壊的な代入を許さないらしい。 代わりに mcons というデータ構造が用意されていてこちらは set-mcar! や set-mcdr! といった手続きで代入ができる。 R5RS に基づいて書かれた Scheme のプログラムを動かすにはペアを扱う手続きを mcons を使うものに定義し直す必要があるが、すでにそれをするパッケージが用意されている。 > (require r5rs) とすると、set-car! や set-cdr! が定義され、cons で作ったペアに再代入できる。 参考: Getting rid of set-car! and set-cdr!

[数式処理][Scheme] 算術式を簡単にする

微分などで複雑になった算術式を簡素化するには次のようにする。 (define (simple exp) (define (flat lst op) (append-map! (lambda (x) (if (and (pair? x) (eq? (car x) op)) (flat (cdr x) op) (list x))) lst)) (define (constant-fold args init op) (define (cf args num acc) (cond ((null? args) (values Continue reading [数式処理][Scheme] 算術式を簡単にする

[数式処理][Scheme] 微分する

複雑な微分をするときは計算機に任せた方が良いように思う。 Scheme で微分するには次のようにする。 (define (deriv exp var) (cond ((eq? exp var) 1) ((not (pair? exp)) 0) ((eq? (car exp) ‘-) `(- ,(deriv (cadr exp) var))) ((eq? (car exp) ‘+) `(+ ,(deriv (cadr exp) var) ,(deriv (caddr exp) var))) ((eq? (car Continue reading [数式処理][Scheme] 微分する

[Scheme][Racket] 相対パスでロード

Racketで相対パスを用いてロードする際の注意。 load で相対パスを使った場合は current-directory (デフォルトでは実行パス)を基点にロードパスが決まる。 ただ、”./filename” や “../filename” といった形式は使えなかった。 current-directory と結合してOSに丸投げするだけでいいのに、信じられない。 ロードされているファイルからそのファイルのあるディレクトリを基点に相対パスでロードする場合は load-relative を用いる。 (load-relative “relative-path”) その際、基点となるディレクトリは current-load-relative-directory 関数で取得できる。

[Scheme] 束縛する値を省略できるように let を書き換える

Common Lisp では CL-USER> (let (a b c) c) NIL のように let で束縛する値を省略できる. 省略された変数は nil に束縛される. しかし,Scheme にはそのような省略記法はない. そこで,マクロを使い Common Lisp のような略記法を導入する. 次のように書く. (define-syntax old-let let) (define-syntax %let (syntax-rules () ((_ (te …) () body …) (old-let (te …) body Continue reading [Scheme] 束縛する値を省略できるように let を書き換える

[Scheme] 循環のあるグラフをコピーする

コンスセルを使った循環のあるグラフをコピーする関数は次のように書ける。 (define (copy-graph-sub ht graph) (cond ((not (pair? graph)) graph) ((hash-table-exists? ht graph) (hash-table-ref ht graph)) (else (let ((p (cons #f #f))) (hash-table-set! ht graph p) (set-car! p (copy-graph-sub ht (car graph))) (set-cdr! p (copy-graph-sub ht (cdr graph))) p)))) (define Continue reading [Scheme] 循環のあるグラフをコピーする