Re: Question about design, defmacro, macrolet, and &environment
From: Damien Kick (dkick1_at_email.mot.com)
Date: 11/17/03
- Previous message: Lowell Kirsh: "Re: Help with lisp function"
- In reply to: Damien Kick: "Re: Question about design, defmacro, macrolet, and &environment"
- Next in thread: Edi Weitz: "Re: Question about design, defmacro, macrolet, and &environment"
- Reply: Edi Weitz: "Re: Question about design, defmacro, macrolet, and &environment"
- Reply: Kenny Tilton: "Re: Question about design, defmacro, macrolet, and &environment"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 16 Nov 2003 18:52:47 -0600
Well, some more style questions...
;; This was the first version. It uses tail recursion. This is a
;; very Scheme-ish style. I wonder how long it will take someone on
;; c.l.l to propose a version of EXPECT-STRING that uses LOOP. As
;; I've been introduced to CL by Graham's _ANSI Common Lisp_, I have
;; been introduced to an anti-LOOP cl-view and appreciate having been
;; introduced to a pro-LOOP view by c.l.l. However, I'm still not
;; comfortable with LOOP and wish I knew of a tutorial for it.
(defun expect-string--rec (string stream &key (echo t))
(labels ((lemma (string in end match echo pos)
;; If/when CMU CL allows one to trace local functions, I
;; will be able to remove the following WHEN.
(when *trace-expect-string-lemma*
(format t "expect-string lemma ~A~%"
(list string in end match echo pos)))
(unless (= pos end)
(let ((actual (read-char in))
(expect (char string pos)))
(write-char actual match)
(when echo
(write-char actual echo)
(force-output echo))
(let ((next (if (char= actual expect)
(1+ pos)
0)))
(lemma string in end match echo next))))))
(values string
(let ((end (length string))
(echo (synonym-value echo t *standard-output*)))
(with-output-to-string (match)
(lemma string stream end match echo 0))))))
;; I've rewritten the function to use DO instead of recursion.
(defun expect-string (string stream &key (echo t))
"Expects to find the literal STRING on the STREAM."
(values string
(let ((end (length string))
(echo (synonym-value echo t *standard-output*)))
(with-output-to-string (match)
(do ((actual)
(pos 0 (if (char= actual (char string pos))
(1+ pos)
0)))
((= pos end))
;; Okay, I know that I shouldn't be bothered by the
;; SETQ, by I still am. So, I try a couple different
;; versions. Are any of the variations worth the
;; effort? Probably not.
(setq actual (read-char stream))
(write-char actual match)
(when echo
(write-char actual echo)
(force-output echo)))))))
;; Remove the need for the explicit SETQ by doing all of the work in
;; the step forms. However, now we need to use EQL to test the actual
;; character read against the expected character because ACTUAL will
;; be NIL the first time through.
(defun expect-string-1 (string stream &key (echo t))
(values string
(let ((end (length string))
(echo (synonym-value echo t *standard-output*)))
(with-output-to-string (match)
;; Using the LAMBDA form allows me to achieve the side
;; effects as part of the step form of ACTUAL.
(do ((actual nil (funcall #'(lambda (x)
(write-char x match)
(when echo
(write-char x echo)
(force-output echo))
x)
(read-char stream)))
;; Because ACTUAL will be NIL in the first pass, we
;; use EQL instead of CHAR=. Is this potentially
;; slower?
(pos 0 (if (eql actual (char string pos))
(1+ pos)
0)))
((= pos end)))))))
;; Uses DO* instead of DO. Because of this, we know that ACTUAL will
;; be assigned before the test performed in the step form of POS, and
;; so we do not need to handle a case in which ACTUAL may be NIL. Of
;; course, I've read that DO* is frequently considered to be bad
;; style, and so I want to be suspisious about it. However, it kind
;; of doesn't really look all that bad. What am I missing? Would a
;; LOOP version be better than all of these?
(defun expect-string-2 (string stream &key (echo t))
(values string
(let ((end (length string))
(echo (synonym-value echo t *standard-output*)))
(with-output-to-string (match)
;; Again, use the LAMBDA form to achieve the side
;; effects in the step form.
(do* ((actual nil (funcall #'(lambda (x)
(write-char x match)
(when echo
(write-char x echo)
(force-output echo))
x)
(read-char stream)))
;; Because we know that ACTUAL will be assigned
;; before this point, we can use CHAR= as ACTUAL
;; will never be NIL.
(pos 0 (if (char= actual (char string pos))
(1+ pos)
0)))
((= pos end)))))))
- Previous message: Lowell Kirsh: "Re: Help with lisp function"
- In reply to: Damien Kick: "Re: Question about design, defmacro, macrolet, and &environment"
- Next in thread: Edi Weitz: "Re: Question about design, defmacro, macrolet, and &environment"
- Reply: Edi Weitz: "Re: Question about design, defmacro, macrolet, and &environment"
- Reply: Kenny Tilton: "Re: Question about design, defmacro, macrolet, and &environment"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|