Gauche:イディオム

Gauche:イディオム

「Schemerの常識は他のプログラマの非常識」という理念に基づき、 実際のプログラムによく出てくる定型を列挙するコーナー。

といいつつ実際なんの役に立つのかわからないけどとりあえずおもしろいから いいやとか、単に笑えるだけの技なんかも集まるといいなあ。 大きいものは別に項目を立てるとして、こっちは10行くらいをメドに。

モデルにしたのはこのへん。

http://www.asahi-net.or.jp/~dp8t-asm/java/idiom/index.html

当面整理しないでただ並べておく。

関連


何も返さない

 (values)

#<undef>を返す

 (if #f #f)

#<eof>を返す

 (read-from-string "")

exprが#fなら#fを、さもなければ#tを返す

 (if expr #t #f) ;#fが省略できないことに注意!
 or
 (and expr #t)
 or
 (not (not expr))

[Guileには->boolという関数が用意されている]

文字列の連結(最初の2つを除けば文字列以外でもかまわない)

 (string-append str1 str2)
 or
 (use srfi-13)
 (string-concatenate (list str1 str2))
 or
 #`",|str1|,|str2|"
 or
 (format "~a~a" str1 str2)
 or
 (with-output-to-string (lambda () (display str1) (display str2)))

n回の繰り返し

 (dotimes (i 10) (print i))
 or
 (use srfi-1)
 (for-each print (iota 10))

map して filter

(filter values (map proc xs))

or

(use srfi-1)
(filter-map proc xs)

thunk をつくる

(cut proc arg)

例:

(call-with-input-file f
  (lambda (port)
    (port-map fn (cut read-line port))))

確実に後処理をする

(with-error-handler
    (lambda (e) (close-output-port port) (raise e))
  (lambda ()
    (begin0 (proc port) (close-output-port port))))

これは次のようにも書ける。上のコードに展開される。GaucheRefj:unwind-protect

(unwind-protect 
    (proc port)
  (close-output-port port))

call/cc を使って proc の dynamic extent に出入りしない場合は以下も同じだけど、 call/ccが使われるかどうかは一般には知り得ない(procから呼んでるライブラリの 中で使われるかもしれない)ので、こういう目的でdynamic-windを使うことは あまりお薦めしない。

(dynamic-wind
  (cut values #f)
  (cut proc port)
  (cut close-output-port port))

手続き間の状態共有

(define func1 #f)
(define func2 #f)

(let ((shared 1) (variable 2))
    (set! func1 (lambda () ...))
      (set! func2 (lambda () ...)))

or

(define-values (func1 func2)
  (let ((shared 1) (variable 2))
    (values
     (lambda () ...)
     (lambda () ...))))

define-values (var ...) expr なので、internal define は直接つかえない。

(define-values (func1 func2)
  (define shared 1)
  (define variable 2)
  (values
   (lambda () ...)
   (lambda () ...)))    ; => *** ERROR: Compile Error: malformed define-values ...

let をはさめば大丈夫。

(define-values (func1 func2)
  (let ()
    (define shared 1)
    (define variable 2)
    (values
      (lambda () ...)
      (lambda () ...))))

連想リストから値を取りだす

(cond ((assoc key alist) => cdr)
      (else #f))

or

(and-let* ((pair (assoc key alist)))
  (cdr pair))

or

(use util.list)

(assoc-ref alist key)
More ...