Subject: Re: Are these two functions equivalent ?
From: rpw3@rigden.engr.sgi.com (Rob Warnock)
Date: 2000/04/16
Newsgroups: comp.lang.lisp
Message-ID: <8dbh8c$3jki$1@fido.engr.sgi.com>
Arne Knut Roev  <akroev@online.no> wrote:
+---------------
| (defun get-reference-pair-from-keyboard ()
|   (let
|       ((web-address "")
|        (web-label ""))
|     (format t "~&Please type the address of the web page:~%")
|     (setf web-address (read-line))
|     (format t "~&Please type the label you want displayed for this link:~%")
|     (setf web-label (read-line))
|     (cons web-address web-label)))
| 
| For some reason, I was not satisfied with this version (I didn't like
| having to use two lexical variables)...
+---------------

Part of it may be that you aren't using lexicals in the natural
functional style. I strongly prefer the following version:

  (defun get-reference-pair-from-keyboard ()
    (format t "~&Please type the address of the web page:~%")
    (let ((web-address (read-line)))
      (format t "~&Please type the label you want displayed for this link:~%")
	(let ((web-label (read-line)))
          (cons web-address web-label))))

Look, ma, no "setq"s!  

[Yes, the final "let" could be replaced by just (cons web-address (read-line)),
but I prefer the additional documentation which naming the value gives you.]

And as <Martti.Halminen@solibri.com> noted about robustness &
modularity/reusability:
+---------------
| I'd probably do this by creating some kind of general user-prompting
| function, usage something like (ask-user <stream> <checkfunction>
| <promptstring> &rest <promptargs>)
| - looping with re-prompting until the read-line returns something acceptable.
| =>
| (ask-user t #'url-string-p "Please type the address of the web page:")
| (ask-user t #'acceptable-label-p 
|          "Please type the label you want displayed for this link:")
+---------------

Once you have "ask-user" (or equiv.), it's even more compact [though I
decided to split those *long* prompt strings out as separate lexvars]:

  (defun get-reference-pair-from-keyboard ()
    (let* ((msg1 "Please type the address of the web page:")
	   (web-address (ask-user t #'url-string-p msg1))
	   (msg2 "Please type the label you want displayed for this link:")
	   (web-label (ask-user t #'acceptable-label-p msg2)))
      (cons web-address web-label)))


-Rob

-----
Rob Warnock, 41L-955		rpw3@sgi.com
Applied Networking		http://reality.sgi.com/rpw3/
Silicon Graphics, Inc.		Phone: 650-933-1673
1600 Amphitheatre Pkwy.		PP-ASEL-IA
Mountain View, CA  94043