Skip to content

Instantly share code, notes, and snippets.

@cametan001
Created May 15, 2010 17:07
Show Gist options
  • Save cametan001/402293 to your computer and use it in GitHub Desktop.
Save cametan001/402293 to your computer and use it in GitHub Desktop.
(do (( <<変数1>> <<初期値1>> <<ステップ1>>)
...
( <<変数m>> <<初期値m>> <<ステップm>>))
(<<終了条件>> <<式>>...<<式>>)
<<式1>>
...
<<式n>>)
CL-USER> (let ((i 0))
(my-while%% (< i 10)
(print i)
(incf i)))
0
1
2
3
4
5
6
7
8
9
9 ; やった!返り値が 9 になった!
CL-USER>
CL-USER> (let ((i 0))
(my-while% (< i 10)
(print i)
(incf i)))
0
1
2
3
4
5
6
7
8
9
10 ; あれ!?やっぱり10になっている!
CL-USER>
CL-USER> (defmacro my-while (test &body body)
`(do ()
((not ,test))
,@body))
MY-WHILE
CL-USER> (let ((i 0))
(my-while (< i 10)
(print i)
(incf i)) ; (setf i (+ i 1)) と同じ
i) ; i を返してみる
0
1
2
3
4
5
6
7
8
9
10 ;何と i は 10 になってる!
CL-USER>
CL-USER> (last '(0 1 2 3 4 5))
(5)
CL-USER> (butlast '(0 1 2 3 4 5))
(0 1 2 3 4)
CL-USER>
(defmacro my-while%% (test &body body)
;; var0 の初期値は nil で、(last body) は do のボディの式が評価されてから実行される
`(do ((var0 nil ,@(last body))
;; var1 の初期値も nil で、更新値は「前回の」var0 の値
(var1 nil var0))
((not ,test) var1) ; 返り値は var1 になる
,@(butlast body)))
(defmacro my-while% (test &body body)
;; var の初期値は nil で、(last body) は do のボディの式が評価されてから実行される
`(do ((var nil ,@(last body)))
((not, test) var)
,@(butlast body))) ; body の最後尾以外の評価がボディの仕事
;; ファイルを読み込んで行数を表示する手続き(Scheme)
(define (count-lines filename)
(call-with-input-file filename
(lambda (p)
(let loop ((c (read-char p))
(count 0))
(cond ((eof-object? c) (close-input-port p) count)
(else (loop (read-char p) (if (char=? c #\newline)
(+ count 1)
count))))))))
(define (count-lines/do filename)
(call-with-input-file filename
(lambda (p)
(do ((c (read-char p) (read-char p))
(count 0 (if (char=? c #\newline)
(+ count 1)
count)))
((eof-object? c) (close-input-port p) count)))))
;; ファイルを読み込んで表示して、行数を表示する手続き(Scheme)
(define (print-and-count-lines filename)
(call-with-input-file filename
(lambda (p)
(let loop ((c (read-char p))
(count 0))
(cond ((eof-object? c) (close-input-port p) count)
(else (display c) ; 基本 begin に頼って形式的には汚くなる
(loop (read-char p) (if (char=? c #\newline)
(+ count 1)
count))))))))
(define (print-and-count-lines/do filename)
(call-with-input-file filename
(lambda (p)
(do ((c (read-char p) (read-char p))
(count 0 (if (char=? c #\newline)
(+ count 1)
count)))
((eof-object? c) (close-input-port p) count)
(display c))))) ;ボディに出力命令がサッと置ける
(let name ((<<変数1>> <<初期値1>>) ... (<<変数m>> <<初期値m>>))
(cond (<<終了条件>>
<<式>> ... <<式>>)
(else
(name <<ステップ1>> ... <<ステップm>>))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment