From: david
Subject: please review my complete working program
Date: 
Message-ID: <0874f95e-887b-428d-9537-a347fb269bb0@r34g2000vbp.googlegroups.com>
my apologies to everyone who tried to show me a better way.


(defclass chessboard ()
  ((board-position :accessor state
	           :initform (make-array '(8 8) :initial-element '0))))

(defmethod put-piece ((board chessboard) x y p)
  (setf (aref (state board) x y) p))

(defun empty-cell-p (cell) (eql 0 cell))

(defmethod print-board-to-string ((board chessboard))
  (with-output-to-string (*standard-output*)
    (flet ((columns ()
	     (format t "    | A  | B  | C  | D  | E  | F  | G  | H  |    ~
%"))
           (line    ()
	     (format t "----+----+----+----+----+----+----+----+----+----~
%")))
      (loop :for i :from 7 :downto 0
         :initially (terpri) (columns) (line)
         :do (loop :for j :from 0 :below 8
                :initially (format t " ~2D |" (1+ i))
                :for cell = (aref (state board) j i)
                :do (if (empty-cell-p cell)
                        (princ "    |")
                        (format t " ~2A |" cell))
                :finally (format t " ~2D ~%" (1+ i)) (line))
         :finally (columns)))))

(defmethod print-object ((board chessboard) stream)
  (print-unreadable-object (board stream :identity t :type t)
    (let ((*print-readably* nil))
      (format stream " ~A" (print-board-to-string board))))
  board)

(defun get-four-unique-random-numbers ()
  (loop
     :with results = '()
     :for alea = (random 64)
     :while (< (length results) 4)
     :do (pushnew alea results)
     :finally (return results)))

(defun rank-file (position)
  (multiple-value-bind (quotient remainder)
                       (truncate position 8)
    (list  quotient  remainder)))

(defun reverse-rank-file (lst)
  (let ((x (first lst))
	(y (second lst)))
    (+ y (* 8 x))))

(defun get-positions ()
  (mapcar #'cons '(wk wn wb x) (get-four-unique-random-numbers)))

(defun neighbor (x)
  (list (1- x) x (1+ x)))

(defun bad-squares (wk)
"bad-squares is bad because it doesn't care about edge cases."
  (let ((column-neighbors (neighbor (second wk))))
    (loop for x in (neighbor (first wk))
          append (loop for y in column-neighbors
                      collect (list x y)))))

(defun legal-position()
  (let* ((lst (get-positions))
	 (wk (rank-file (cdr (assoc 'wk lst))))
	 (x (rank-file (cdr (assoc 'x lst)))))
    (if (not (member (reverse-rank-file x)
		     (mapcar #'reverse-rank-file (bad-squares wk))))
	lst (legal-position))))

(defun numberify-position ()
	   (let ((lst (legal-position)))
	     (loop for i in '(wk wn wb x)collect
		  (cdr (assoc i lst)))))

(defun random-chessboard ()
"Returns a fresh random chessboard with pieces wk wb wn and b."
   (let ((chessboard (make-instance 'chessboard)))
     (mapc #'(lambda (pos piece)
              (put-piece chessboard (first pos)
                         (second pos) piece))
          (mapcar #'rank-file (numberify-position)) '(wk wb wn x))
     chessboard))

(defun compress (x)
  (if (consp x)
      (compr (car x) 1 (cdr x))
      x))

(defun compr (elt n lst)
  (if (null lst)
      (list (n-elts elt n))
      (let ((next (car lst)))
        (if (eql next elt)
            (compr elt (+ n 1) (cdr lst))
            (cons (n-elts elt n)
                  (compr next 1 (cdr lst)))))))

(defun n-elts (elt n)
  (if (> n 1)
      n elt))

(defun make-fenlist ()
  (let* ((a (random-chessboard))
	 (b (reverse (loop for j from 0 to 7
		     collect (loop for i from 0 to 7
				collect (aref (state a) i j)))))
	 (c (subst 1 0 (mapcar #'compress b))))
     c))

(defun list2string (list)
  (apply #'concatenate 'string (mapcar #'(lambda(a)
                                           (if (stringp a)
                                               a
                                             (if (symbolp a)
                                                 (symbol-name a)
                                               (princ-to-string a))))
                                 list)))

(defun frob-list ()
	   (let ((lst (make-fenlist)))
	     (setf lst (list2string lst))
	     (setf lst (remove #\( lst))
	     (setf lst (substitute #\/ #\) lst))
	     (setf lst (remove #\space lst))
	     (setf lst (remove #\W lst))
	     (setf lst (remove #\/ lst :start (1- (length lst))))
	     (setf lst (substitute #\k #\X lst))))

(defun almost-there ()
  (concatenate 'string (frob-list) " b - - 0 1"))

(with-open-file (stream
		 "C:\\Documents and Settings\\david\\Desktop\\bkend.fen"
	         :direction :output
		 :if-exists :supersede
		 :if-does-not-exist :create)
		 (format stream (almost-there)))

From: Thomas A. Russ
Subject: Re: please review my complete working program
Date: 
Message-ID: <ymi8wnkltlc.fsf@blackcat.isi.edu>
david <······@gmail.com> writes:

> my apologies to everyone who tried to show me a better way.
> 
> 
> (defclass chessboard ()
>   ((board-position :accessor state
> 	           :initform (make-array '(8 8) :initial-element '0))))

Perhaps an :initial-element of NIL?  It doesn't have to be numeric, so
there's no real reason to prefer a zero.  Especially since you then end
up using a special purpose routine to test for it.

Better to go with the standard lisp default of NIL, which has the
benefit of exactly meaning nothing anyway.  And it will simplify some
other code.

> (defun empty-cell-p (cell) (eql 0 cell))

This is no longer directly necessary.  You can just use NULL as the test
if you use a more standard NIL as the empty list.

That also lets you simplify the printing of the contents, since there
are special test operators in the format language that understand NIL in
is role as a test.  In fact, a standard format idiom for special
printing of possibly NIL values is to use

   ~:[  ~;~:*~A~]
     1   2  3 4 5
where
  1. With the colon takes a test and contains a NIL and non-NIL branch
  2. Terminates the first (NIL) branch of the conditional format
  3. With the colon, backs up one argument
  4. Formats the argument that was just backed up
  5. Closes the conditional format section.


> (defmethod print-board-to-string ((board chessboard))
>   (with-output-to-string (*standard-output*)
>     (flet ((columns ()
> 	       (format t "    | A  | B  | C  | D  | E  | F  | G  | H  |    ~%"))
>            (line    ()
> 	       (format t "----+----+----+----+----+----+----+----+----+----~%")))
>       (loop :for i :from 7 :downto 0
>          :initially (terpri) (columns) (line)
>          :do (loop :for j :from 0 :below 8
>                 :initially (format t " ~2D |" (1+ i))
====================================================

>                 :for cell = (aref (state board) j i)
>                 :do (if (empty-cell-p cell)
>                         (princ "    |")
>                         (format t " ~2A |" cell))
====================================================
You can then replace the above section with

                   :do (format t " ~:[  ~;~:*~2A~] |" |" 
                               (aref (state board) j i))

If you want to make the number of spaces easier to see and keep in sync
with the A format directive, you could use the ·@T directive like this:

                   :do (format t " ~:[··@T~;~:*~2A~] |" |" 
                               (aref (state board) j i))

>                 :finally (format t " ~2D ~%" (1+ i)) (line))
>          :finally (columns)))))
> 
> (defmethod print-object ((board chessboard) stream)
>   (print-unreadable-object (board stream :identity t :type t)
>     (let ((*print-readably* nil))
>       (format stream " ~A" (print-board-to-string board))))
>   board)

Now, you could also simplify the above two functions by avoiding the
need the whole excursion via strings in the first place by changing

  (defmethod print-board-to-string ((board chessboard)) ...)

to 

  (defmethod print-board ((board chessboard) &optional (stream *standard-output*))
     ...) 

and using the STREAM argument in all the FORMAT statements or perhaps
even easier, by rolling that all into the PRINT-OBJECT method.

Then you could trivially write PRINT-BOARD-TO-STRING by

   (defmethod print-board-to-string ((board chessboard)) 
      (with-output-to-string (s) (print-board board s)))

or, if you went the PRINT-OBJECT route -- and didn't care about the
extra information provided by PRINT-UNREADABLE-OBJECT, by a very simple

    (format nil "~A" board)

and not even bother to have a separate function for it.

> (defun n-elts (elt n)
>   (if (> n 1)
>       n elt))

I have no idea what that N-ELTS is supposed to do.


> (defun list2string (list)
>   (apply #'concatenate 'string (mapcar #'(lambda(a)
>                                            (if (stringp a)
>                                                a
>                                              (if (symbolp a)
>                                                  (symbol-name a)
>                                                (princ-to-string a))))
>                                  list)))

First off, when you have cascaded tests, you would generally use COND
instead of nested IF statements.  So instead of 

  (if (stringp a)
      a
      (if (symbolp a)
          (symbol-name a)
          (princ-to-string a)))

one would just use a COND, since that is exactly what it does (but with
extra parentheses)

  (cond ((stringp a)
          a)
        ((symbolp a)
          (symbol-name a))
        (t
          (princ-to-string a)))

Second, if your main reason for doing a set of such tests is to figure
out what to do with arguments of different types, there is again a
specialized form for exactly that idiom:  TYPECASE

  (typecase a
     (string
        a)
     (symbol
        (symbol-name a))
     (t
       (princ-to-string a)))

Third, there's no reason not to just use #'PRINC-TO-STRING in place of
this entire test in your lambda, since it handles strings and symbols
exactly the same way that your other tests do.

(defun list2string (list)
   (apply #'concatenate 'string (mapcar #'princ-to-string list)))

I will also note that if LIST gets too long, you could run into trouble
with APPLY, since there is a limit to the number of arguments that
functions can take.  This is implementation dependent and given by the
constant CALL-ARGUMENTS-LIMIT.  The minimum value is, IIRC, required to
be at least 50, and generally it's much higher.  But it does exist.


And finally:
Simpler (assuming Pascal didn't convince you you didn't need it):

(defun list2string (list)
  (format nil "~{~A~}" list))

since the ~A format command will print strings, symbols and everything
else exactly the same way as your complicated lambda expression will.
In fact, this is some simple that you probably don't even want to bother
writing your own function for it, but just use the FORMAT statement
whenever you need this to happen.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <37f1093d-a04b-42f8-8f58-24ab146e9a10@p11g2000yqe.googlegroups.com>
thanks for your teachings. i see i will be
spending some time experimenting with format.
From: Rob Warnock
Subject: Re: please review my complete working program
Date: 
Message-ID: <uradnUx0icbfBS3UnZ2dnUVZ_gSWnZ2d@speakeasy.net>
david <······@gmail.com> wrote:
+---------------
| thanks for your teachings. i see i will be
| spending some time experimenting with format.
+---------------

Hint: In its full-blown glory, FORMAT is even more complex than LOOP,
a complete separate sub-language, embedded in a single string! Thus
you should approach it in baby steps, so as not to get overwhelmed.

Once you get your footing with simple stuff, you can start exploring
the wonders of control flow (backing up, branching, & looping), layout
control, and pretty-printer ops.[1]

That said, it does help to learn very early the full generality of
the FORMAT "embedded directive" syntax, the thing introduced by the
tilde ("~") and terminated by a format control character, discussed
in the 8th & 9th paragraphs of CLHS "22.3 Formatted Output", since
almost every non-trivial directive uses some combination of the
available optional modifiers.


-Rob

[1] <http://www.99-bottles-of-beer.net/language-common-lisp-114.html>,
    while *quite* amusing, isn't actually a particularly complex FORMAT
    if you take out the artsy line-break hidings and clean it up a little.

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: William James
Subject: Re: please review my complete working program
Date: 
Message-ID: <goqrrs01pav@enews5.newsguy.com>
Rob Warnock wrote:

> 
> [1] <http://www.99-bottles-of-beer.net/language-common-lisp-114.html>,
>     while quite amusing, isn't actually a particularly complex FORMAT
>     if you take out the artsy line-break hidings and clean it up a little.

(in-package "CL-USER")

(defun bottle-song (&optional (in-stock 99) (stream *standard-output*))

  (format

           stream 
         "-----~2%~
          ~{~&~1&~
          ~[~^~:;~
          ·····@(~
          ~R~) bo~
         ttle~:P o~
        f beer on t~
      he wall~01:*~[.~
      ~:;,·······@(~R~
      ~) bottle~:*~P ~
      of beer.~%You t~
      ake one down, p~
      ass it around, ~
      ~01%~[*No* more~
      ·········@(~R~)~
      ~] bottle~:*~P ~
      of beer on the ~
      wall.~2&-----~%~
      ~1%~:*~]~]~}~0%"

   (loop for bottle from in-stock downto 0 collect bottle)))


(bottle-song)


-----


I think a Clojure version would be more readable and maintainable.

(defn bottles [n & cap]
  (str (if (> n 0) n (if (first cap) "No more" "no more"))
    " bottle" (if (= 1 n) "" "s") " of beer" ))

(defn bot-wall [n & cap] (str (bottles n cap) " on the wall"))

(defn sing [stock]
  (doseq [i (range stock -1 -1)]
    (printf "%s, %s.\n%s.\n\n"
      (bot-wall i true) (bottles i)
      (apply str
        (if (> i 0)
          ["Take one down and pass it around, " (bot-wall (dec i))]
          ["Go the the store and buy some more, " (bot-wall stock)]
        )))))

(sing 3)
From: Pillsy
Subject: Re: please review my complete working program
Date: 
Message-ID: <333a24f5-bc2c-4d86-8fab-df3a72b3c66a@o11g2000yql.googlegroups.com>
On Mar 6, 4:54 am, "William James" <·········@yahoo.com> wrote:
[...]
> I think a Clojure version would be more readable and maintainable.

"This language allows me to write programs that are more readable and
maintainable than bthe average Obfuscated C award winner! Isn't it
awesome?"

Cheers,
Pillsy
From: Nicolas Neuss
Subject: Re: please review my complete working program
Date: 
Message-ID: <87y6vj7yjz.fsf@ma-patru.mathematik.uni-karlsruhe.de>
"William James" <·········@yahoo.com> writes:

> I think a Clojure version would be more readable and maintainable.

Boy, the CL bottle song program is art!  It does not have to be
"maintained"!

Nicolas
From: William James
Subject: Re: please review my complete working program
Date: 
Message-ID: <goqu0u01qr9@enews5.newsguy.com>
Nicolas Neuss wrote:

> "William James" <·········@yahoo.com> writes:
> 
> > I think a Clojure version would be more readable and maintainable.
> 
> Boy, the CL bottle song program is art!  It does not have to be
> "maintained"!
> 
> Nicolas

Actually, it's pure crap.  It doesn't even print the song correctly.
And it's not even good ASCII art.  It's nothing.

It's COBOL-LISP.
From: ··················@gmail.com
Subject: Re: please review my complete working program
Date: 
Message-ID: <7de4a6f5-d1a0-432b-967c-7f52bb747aab@i2g2000prd.googlegroups.com>
On Mar 6, 5:30 am, "William James" <·········@yahoo.com> wrote:
> Nicolas Neuss wrote:
> > "William James" <·········@yahoo.com> writes:
>
> > > I think a Clojure version would be more readable and maintainable.
>
> > Boy, the CL bottle song program is art!  It does not have to be
> > "maintained"!
>
> > Nicolas
>
> Actually, it's pure crap.  It doesn't even print the song correctly.
> And it's not even good ASCII art.  It's nothing.
>
> It's COBOL-LISP
Lies.

You just agreed that Common Lisp is for doing God's Will on earth.

(you argue it is both too verbose, and not verbose enough... in other
words, /perfect/)

I think that now that we all know how much you really love lispy
languages like Clojure and CL,
and hate blub languages like Ruby, you can quit trolling and write
some code.

I suggest that you do a version of the bottle song in Common Lisp.
From: John Thingstad
Subject: Re: please review my complete working program
Date: 
Message-ID: <op.uqezghy1ut4oq5@pandora.alfanett.no>
P� Fri, 06 Mar 2009 10:54:04 +0100, skrev William James  
<·········@yahoo.com>:


Here are some versions for other languages..
In fact 227 of them. So you see it sais little about Lisp.

http://www.westnet.com/mirrors/99bottles/beer.html

--------------
John Thingstad
From: Thomas Stenhaug
Subject: Re: please review my complete working program
Date: 
Message-ID: <87vdqlazvt.fsf@sed.eklatla.org>
"William James" <·········@yahoo.com> writes:

> I think a Clojure version would be more readable and maintainable.
>
> (defn bottles [n & cap]
>   (str (if (> n 0) n (if (first cap) "No more" "no more"))
>     " bottle" (if (= 1 n) "" "s") " of beer" ))
>
> (defn bot-wall [n & cap] (str (bottles n cap) " on the wall"))
>
> (defn sing [stock]
>   (doseq [i (range stock -1 -1)]
>     (printf "%s, %s.\n%s.\n\n"
>       (bot-wall i true) (bottles i)
>       (apply str
>         (if (> i 0)
>           ["Take one down and pass it around, " (bot-wall (dec i))]
>           ["Go the the store and buy some more, " (bot-wall stock)]
>         )))))

Where did the bottle go?

--
Thomas
From: Marco Antoniotti
Subject: Re: please review my complete working program
Date: 
Message-ID: <46bb83c5-aa6c-49d5-8c2c-f5836c6bb042@j39g2000yqn.googlegroups.com>
On Mar 7, 8:36 pm, Thomas Stenhaug <···············@gmail.com> wrote:
> "William James" <·········@yahoo.com> writes:
> > I think a Clojure version would be more readable and maintainable.
>
> > (defn bottles [n & cap]
> >   (str (if (> n 0) n (if (first cap) "No more" "no more"))
> >     " bottle" (if (= 1 n) "" "s") " of beer" ))
>
> > (defn bot-wall [n & cap] (str (bottles n cap) " on the wall"))
>
> > (defn sing [stock]
> >   (doseq [i (range stock -1 -1)]
> >     (printf "%s, %s.\n%s.\n\n"
> >       (bot-wall i true) (bottles i)
> >       (apply str
> >         (if (> i 0)
> >           ["Take one down and pass it around, " (bot-wall (dec i))]
> >           ["Go the the store and buy some more, " (bot-wall stock)]
> >         )))))
>
> Where did the bottle go?
>

The Ruby Guy stole it and drank it.

Cheers
--
Marco
From: Pascal J. Bourguignon
Subject: Re: please review my complete working program
Date: 
Message-ID: <87hc290xwd.fsf@galatea.local>
david <······@gmail.com> writes:

> (defun bad-squares (wk)
> (defun legal-position()

If this is a predicate, the convention is to terminate it with p or -p
when the name contains -. Therefore: legal-position-p 
Idem for bad-squares-p


> (defun compr (elt n lst)

I cannot find COMPR in any dictionary.  You should write a
documentation string to explain what it should do.


> (defun n-elts (elt n)
>   (if (> n 1)
>       n elt))

Could you find another use of this function?  Or at least, could you
find a more meaningful name for this function?

If it, it would be better to keep it a local function, using FLET or
LABELS.


> (defun make-fenlist ()

A function without parameters should be a constant, and always return
the same thing.

Instead write a function 
(defun fen-list-from-board (board) ...)
 

>   (let* ((a (random-chessboard))
>          (b (reverse (loop for j from 0 to 7
>                    collect (loop for i from 0 to 7
>                               collect (aref (state a) i j)))))
>          (c (subst 1 0 (mapcar #'compress b))))
>      c))

If you cannot find better names than a, b, c to your values, then DO
NOT GIVE THEM NAMES!

(defun fen-list-from-board (board)
  (subst 1 0
         (mapcar
          (function compress)
          (loop
             :for j :from 7 :downto 0
             :collect (loop
                         :for i :from 0 :to 7
                         :collect (aref (state board) i j))))))

 

> (defun list2string (list)

We like better list-to-string
or list->string if you're influenced by scheme.

There has been some discussions tending to demonstrate that
string-from-list would be better, eg. when you need to chain several
conversions:

    (string-from-list (list-from-vector (vector-from-file "xyz")))




> (defun frob-list ()
> (defun almost-there ()

These names don't mean anything.
If you can't give a name, then don't try!

You can write anonymous functions with LAMBDA, or just LET expressions.



> 	   (let ((lst (make-fenlist)))
> 	     (setf lst (list2string lst))
> 	     (setf lst (remove #\( lst))
> 	     (setf lst (substitute #\/ #\) lst))
> 	     (setf lst (remove #\space lst))
> 	     (setf lst (remove #\W lst))
> 	     (setf lst (remove #\/ lst :start (1- (length lst))))
> 	     (setf lst (substitute #\k #\X lst))))

This is horrible.  You are trying to undo all the wrongness you did in
list2string.  Why don't you generate the fen notation directly from
the fen list?

(defun generate-fen-notation (board)
  (format nil "~{~{~A~}~^/~} b - - 0 1" (fen-list-from-board board)))

(generate-fen-notation (random-chessboard))
--> "8/WB7/4X3/8/4WK3/4WN3/8/8 b - - 0 1"

Beware of FORMAT calls such as:

   (format stream (almost-there))

if the control string returned by the function may contain tilde, they
will be interpreted as format specifiers.  It would be better to use
PRINC, WRITE-LINE or a literal string in FORMAT:

   (write-line (generate-fen-notation (random-chessboard)) stream)
or:
   (princ (generate-fen-notation (random-chessboard))  stream) 
   (terpri stream)
or:
   (format stream "~A~%" (generate-fen-notation (random-chessboard)))


-- 
__Pascal Bourguignon__
From: Mark Wooding
Subject: Re: please review my complete working program
Date: 
Message-ID: <87sklsg91u.fsf.mdw@metalzone.distorted.org.uk>
···@informatimago.com (Pascal J. Bourguignon) writes:

> A function without parameters should be a constant, and always return
> the same thing.

What a peculiar idea!  Surely if you have a constant, make it be a
constant.

So: here are the standard Common Lisp functions which accept no
arguments and return a constant:

        NEXT-METHOD-P (local -- might be constant)
        LISP-IMPLEMENTATION-TYPE
        LISP-IMPLEMENTATION-VERSION
        LONG-SITE-NAME
        MACHINE-INSTANCE
        MACHINE-TYPE
        MACHINE-VERSION
        SHORT-SITE-NAME
        SOFTWARE-TYPE
        SOFTWARE-VERSION

I'm not really sure why most of those are functions at all.

Here are the functions which you can call with or without arguments, and
just return constants if you pass no arguments.  In many cases, these
are unedifying base cases for more general operations.

        VALUES -- returns nothing at all
        LIST -- returns NIL
        GCD -- returns 0
        LCM -- returns 1
        + -- returns 0
        * -- returns 1
        LOGAND -- returns -1
        LOGEQV -- returns -1
        LOGIOR -- returns 0
        LOGXOR -- returns 0
        APPEND -- returns NIL
        NCONC -- returns NIL
        USER-HOMEDIR-PATHNAME

This next bunch can be called with or without arguments, and do
something interesting when called with no arguments as well as returning
a constant.

        BREAK
        CLEAR-INPUT
        CLEAR-OUTPUT
        FINISH-OUTPUT
        FORCE-OUTPUT
        TERPRI
        ROOM -- returns something implementation-defined which might
        	well be constant.
        ED -- and again

This bunch doesn't return a constant when called with no arguments.

        CALL-NEXT-METHOD -- could do almost anything!
        GENSYM -- always returns something new
        GENTEMP -- always returns something new
        VECTOR -- always returns a fresh empty vector
        ABORT -- doesn't return at all
        CONTINUE -- doesn't return at all, usually
        COMPUTE-RESTARTS -- returns different lists in different dynamic
                environments
        MAKE-RANDOM-STATE -- returns a fresh random-state
        MAKE-HASH-TABLE -- returns a fresh hash-table
        MAKE-PATHNAME -- returns a fresh (but unedifying) path name
        LISTEN -- returns whether *STANDARD-INPUT* is readable
        FRESH-LINE -- returns whether a newline was output
        MAKE-BROADCAST-STREAM -- returns a fresh sink stream
        MAKE-CONCATENATED-STREAM -- returns a fresh empty source stream
        MAKE-STRING-OUTPUT-STREAM -- returns a fresh string stream
        PEEK-CHAR -- returns next character on *STANDARD-INPUT*
        READ-CHAR -- returns next character on *STANDARD-INPUT*
        READ-CHAR-NO-HANG -- returns next character or NIL
        READ-LINE -- returns next line on *STANDARD-INPUT*
        YES-OR-NO-P -- returns result of interacting with user
        Y-OR-N-P -- returns result of interacting with user
        COPY-PPRINT-DISPATCH -- returns fresh copy of pprint-dispatch table
        COPY-READTABLE -- returns fresh copy of readtable
        READ -- returns next object read from *STANDARD-INPUT*
        READ-PRESERVING-WHITESPACE -- returns next object again
        DRIBBLE -- doesn't return (with no arguments)

And finally, these can only be called without arguments, and don't
return constants.

        LIST-ALL-PACKAGES -- changes when packages are added
        GET-DECODED-TIME -- one hopes this isn't constant!
        GET-INTERNAL-REAL-TIME -- and this!
        GET-INTERNAL-RUN-TIME -- this too!
        GET-UNIVERSAL-TIME -- and this one!

>> (defun list2string (list)
>
> We like better list-to-string
> or list->string if you're influenced by scheme.

Just LIST-STRING seems to fit in better with the standard functions
(e.g., DIGIT-CHAR, CHAR-CODE, CODE-CHAR, ...).

-- [mdw]
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <6aef2716-920c-4a50-8bee-596060fa72b9@z9g2000yqi.googlegroups.com>
On Mar 4, 3:40 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Beware of FORMAT calls such as:
>
>    (format stream (almost-there))
>
> if the control string returned by the function may contain tilde, they
> will be interpreted as format specifiers.

thanks for your insights. i don't understand: what is control string
returned by the function?
From: Thomas A. Russ
Subject: Re: please review my complete working program
Date: 
Message-ID: <ymi63in918x.fsf@blackcat.isi.edu>
david <······@gmail.com> writes:

> On Mar 4, 3:40 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
> > Beware of FORMAT calls such as:
> >
> >    (format stream (almost-there))
> >
> > if the control string returned by the function may contain tilde, they
> > will be interpreted as format specifiers.
> 
> thanks for your insights. i don't understand: what is control string
> returned by the function?

The second argument to FORMAT is called the control-string.

Perhaps a safer way would be to supply the control string explicitly
rather than using the return value of the function as the control
string.

 (format stream "~A" (almost-there))

But again, for this, using WRITE-STRING would be more straight-forward
and also a lot more efficient, since FORMAT has a certain amount of
overhead, even for simple format strings.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal J. Bourguignon
Subject: Re: please review my complete working program
Date: 
Message-ID: <87r61bzpkh.fsf@galatea.local>
david <······@gmail.com> writes:

> On Mar 4, 3:40 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> Beware of FORMAT calls such as:
>>
>>    (format stream (almost-there))
>>
>> if the control string returned by the function may contain tilde, they
>> will be interpreted as format specifiers.
>
> thanks for your insights. i don't understand: what is control string
> returned by the function?

Use the Common Lisp Hyper Spec = CLHS, the reference, the ANSI
standard on the web: 
http://www.lispworks.com/documentation/HyperSpec/Front/index.htm

The page for FORMAT:
http://www.lispworks.com/documentation/HyperSpec/Body/f_format.htm
shows the syntax of the FORMAT function call:

   (FORMAT destination control-string &rest args) => result

The control-string is merely the second argument.  In the same page,
belowe we can further read that control-string is a "format control",
which is a term defined in the glossary (follow the link).


To see what the problem could be, try out:

(flet ((almost-there () "~~A~Really-Nice~String~~"))
  (princ "First one:  ")                    (finish-output)
  (format t "~A~%" (almost-there))          (finish-output)
  (princ "Second one: ")                    (finish-output)
  (format t (almost-there) 42 24) (terpri)  (finish-output)
  (princ "Third one:  ")                    (finish-output)
  (format t (almost-there)) (terpri)        (finish-output))

-- 
__Pascal Bourguignon__
From: ··················@gmail.com
Subject: Re: please review my complete working program
Date: 
Message-ID: <def39f93-ce89-470c-98b9-6b48884e0ac2@k36g2000pri.googlegroups.com>
Another good thing to download to your desktop is Commmon Lisp the
Language Second Edition.

For me it is like the Holy Book of our Commune Lisp commune.

From God to guy steel (and assorted others) to print to the internet.

(You can read through it if you like, but I prefer to use the index
and just look stuff up)

Every time that I think 'Hey i need to know how to _ maybe i should go
get ask on c.l.l'
I first refer to CLTL2 and the majority of the time I get my answer.

CLTL2:
http://www.cs.cmu.edu/Groups/AI/html/cltl/cltl2.html

For style questions you'll have to refer to other sources.
(There are  about a dozen 'intermediate/advanced' books that are
excellent once you get the basics down...)
From: William James
Subject: Re: please review my complete working program
Date: 
Message-ID: <goql8r0289n@enews2.newsguy.com>
··················@gmail.com wrote:

> Another good thing to download to your desktop is Commmon Lisp the
> Language Second Edition.
> 
> For me it is like the Holy Book of our Commune Lisp commune.

Yes.  It is.

> 
> From God to guy steel (and assorted others) to print to the internet.

God's will be done on earth, as it is in heaven.
From: Paul Wallich
Subject: Re: please review my complete working program
Date: 
Message-ID: <gorgvp$rin$1@reader1.panix.com>
··················@gmail.com wrote:
> Another good thing to download to your desktop is Commmon Lisp the
> Language Second Edition.
> 
> For me it is like the Holy Book of our Commune Lisp commune.
> 
> From God to guy steel (and assorted others) to print to the internet.
> 
> (You can read through it if you like, but I prefer to use the index
> and just look stuff up)
> 
> Every time that I think 'Hey i need to know how to _ maybe i should go
> get ask on c.l.l'
> I first refer to CLTL2 and the majority of the time I get my answer.

There is sometimes a minor problem in that CLTL2 describes a language 
that is very close to but not exactly Common Lisp as standardized and 
subsequently implemented. But he writes way better than the hyperspec.
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <66c04d65-40f1-40dd-a6cd-cfa260c75918@h5g2000yqh.googlegroups.com>
On Mar 5, 2:23 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> david <······@gmail.com> writes:
> > On Mar 4, 3:40 pm, ····@informatimago.com (Pascal J. Bourguignon)
> > wrote:
> >> Beware of FORMAT calls such as:
>
> >>    (format stream (almost-there))
>
> >> if the control string returned by the function may contain tilde, they
> >> will be interpreted as format specifiers.
>
> > thanks for your insights. i don't understand: what is control string
> > returned by the function?
>
> Use the Common Lisp Hyper Spec = CLHS, the reference, the ANSI
> standard on the web:http://www.lispworks.com/documentation/HyperSpec/Front/index.htm
>
> The page for FORMAT:http://www.lispworks.com/documentation/HyperSpec/Body/f_format.htm
> shows the syntax of the FORMAT function call:
>
>    (FORMAT destination control-string &rest args) => result
>
> The control-string is merely the second argument.  In the same page,
> belowe we can further read that control-string is a "format control",
> which is a term defined in the glossary (follow the link).
>
> To see what the problem could be, try out:
>
> (flet ((almost-there () "~~A~Really-Nice~String~~"))
>   (princ "First one:  ")                    (finish-output)
>   (format t "~A~%" (almost-there))          (finish-output)
>   (princ "Second one: ")                    (finish-output)
>   (format t (almost-there) 42 24) (terpri)  (finish-output)
>   (princ "Third one:  ")                    (finish-output)
>   (format t (almost-there)) (terpri)        (finish-output))
>
> --
> __Pascal Bourguignon__

thanks, now i understand. i am aware of hyperspec and cltl.
i've been using the franz reference mostly. and google.
sometimes i am just stupid. i hope just sometimes :)
From: ·····@franz.com
Subject: Re: please review my complete working program
Date: 
Message-ID: <d8410c88-2f5b-4712-8add-3b30f80d9465@w9g2000yqa.googlegroups.com>
On Mar 7, 1:23 am, david <······@gmail.com> wrote:

> thanks, now i understand. i am aware of hyperspec and cltl.
> i've been using the franz reference mostly. and google.
> sometimes i am just stupid. i hope just sometimes :)

Part of the "franz reference" material includes our own copy of the
hyperspec:

http://www.franz.com/support/documentation/current/ansicl/ansicl.htm

and the index for our major documentation:

http://www.franz.com/support/documentation/current/doc/index.htm

contains entries that point into that hyperspec at appropriate
locations.

Duane
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <529fc656-d4d2-4286-8aaf-d236782acdfa@v39g2000yqm.googlegroups.com>
so i will need at least one globally declared chessboard
to pass around?
From: Pascal J. Bourguignon
Subject: Re: please review my complete working program
Date: 
Message-ID: <87mybzzpe1.fsf@galatea.local>
david <······@gmail.com> writes:

> so i will need at least one globally declared chessboard
> to pass around?

No. Why would you want to have a global variable?
But yes, you will pass arround parameters.

Notice how these functions take a BOARD parameter and some of them
pass the BOARD parameter as argument to other functions:

(defun fen-list-from-board (board)
  (subst 1 0
         (mapcar
          (function compress)
          (loop
             :for j :from 7 :downto 0
             :collect (loop
                         :for i :from 0 :to 7
                         :collect (aref (state board) i j))))))

(defun generate-fen-notation (board)
  (format nil "~{~{~A~}~^/~} b - - 0 1" (fen-list-from-board board)))


There's no need for a global variable.  Functions take arguments and
pass further them to other function: it's data flow, clearly stated,
so you can know what happens.

When you use global variables, the data flow is not obvious so the
code is much harder to understand, and harder to make bug-free.


-- 
__Pascal Bourguignon__
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <67f7f7b4-de6b-49db-b481-f2c6eb9907b0@w35g2000yqm.googlegroups.com>
On Mar 5, 2:27 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> david <······@gmail.com> writes:
> > so i will need at least one globally declared chessboard
> > to pass around?
>
> No. Why would you want to have a global variable?
> But yes, you will pass arround parameters.
>

i meant to say something like:
so i have a line such as

(defparameter *board* (make-instance 'chessboard)
From: Pascal J. Bourguignon
Subject: Re: please review my complete working program
Date: 
Message-ID: <87d4ctxtqi.fsf@galatea.local>
david <······@gmail.com> writes:

> On Mar 5, 2:27 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> david <······@gmail.com> writes:
>> > so i will need at least one globally declared chessboard
>> > to pass around?
>>
>> No. Why would you want to have a global variable?
>> But yes, you will pass arround parameters.
>>
>
> i meant to say something like:
> so i have a line such as
>
> (defparameter *board* (make-instance 'chessboard))

What for?

It's ok to have such a global variable to hold the objects you're
working with while debugging.  But in a program it is not very useful.
What you will have is a local variable in the main:

(defun main ()
   (let ((board (make-instance 'checkboard)))
      (do-stuff board)))

That said, you may have a small number of global variables in a
program, if it really simplifies things.  If the board is used in
almost all your functions, it would be painful to pass it always.

But if you can avoid global variables your programs will be easier to
understand and will have less bugs.

-- 
__Pascal Bourguignon__
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <7f583e16-b058-4e22-b012-c61390da4796@p20g2000yqi.googlegroups.com>
On Mar 7, 9:01 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> david <······@gmail.com> writes:
> > On Mar 5, 2:27 pm, ····@informatimago.com (Pascal J. Bourguignon)
> > wrote:
> >> david <······@gmail.com> writes:
> >> > so i will need at least one globally declared chessboard
> >> > to pass around?
>
> >> No. Why would you want to have a global variable?
> >> But yes, you will pass arround parameters.
>
> > i meant to say something like:
> > so i have a line such as
>
> > (defparameter *board* (make-instance 'chessboard))
>
> What for?
>
> It's ok to have such a global variable to hold the objects you're
> working with while debugging.  But in a program it is not very useful.
> What you will have is a local variable in the main:
>
> (defun main ()
>    (let ((board (make-instance 'checkboard)))
>       (do-stuff board)))
>
> That said, you may have a small number of global variables in a
> program, if it really simplifies things.  If the board is used in
> almost all your functions, it would be painful to pass it always.
>
> But if you can avoid global variables your programs will be easier to
> understand and will have less bugs.
>
> --
> __Pascal Bourguignon__

thanks. ok, i have taken out all my horrible code.
and replaced as below. and i could consider the
with-open-file statement to be the main()?
now i feel i am back in c :)
but i get it now. i think.

(defun fen-list-from-board (board)
  (subst 1 0
         (mapcar
          (function compress)
          (loop
             :for j :from 7 :downto 0
             :collect (loop
                         :for i :from 0 :to 7
                         :collect (aref (state board) i j))))))

(defun generate-fen-notation (board)
  (format nil "~{~{~A~}~^/~} b - - 0 1" (fen-list-from-board board)))

(with-open-file (stream
		 "C:\\Documents and Settings\\david\\Desktop\\bkend.fen"
	         :direction :output
		 :if-exists :supersede
		 :if-does-not-exist :create)
  (format stream "~A~%" (generate-fen-notation (random-chessboard))))
From: Chris Riesbeck
Subject: Re: please review my complete working program
Date: 
Message-ID: <71al5sFjvhfaU1@mid.individual.net>
Pascal J. Bourguignon wrote:
> david <······@gmail.com> writes:
> 
>> (defun compr (elt n lst)
> 
> I cannot find COMPR in any dictionary.  You should write a
> documentation string to explain what it should do.
 > ...
 >> (defun n-elts (elt n)
 >>   (if (> n 1)
 >>       n elt))
 >
 > Could you find another use of this function?  Or at least, could you
 > find a more meaningful name for this function?

These come from Graham's ANSI Common Lisp book, which defined a 
run-length compression function which, as I recall, sent David off on 
this journey.

Not disagreeing here. Naming is one of Graham's weakest points.
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <d5373059-5b10-41d6-82bc-07d04599acf8@e18g2000yqo.googlegroups.com>
On Mar 4, 3:40 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:

> (defun generate-fen-notation (board)
>   (format nil "~{~{~A~}~^/~} b - - 0 1" (fen-list-from-board board)))
>

wow, i finally understand this control-string.
i have a headache, but it was worth it :)
From: William James
Subject: Re: please review my complete working program
Date: 
Message-ID: <gon5ak01sl7@enews4.newsguy.com>
david wrote:

> (defun list2string (list)
>   (apply #'concatenate 'string (mapcar #'(lambda(a)
>                                            (if (stringp a)
>                                                a
>                                              (if (symbolp a)
>                                                  (symbol-name a)
>                                                (princ-to-string a))))
>                                  list)))

You and COBOL-LISP make a dynamite combination, an unbeatable
tag-team!  I can only look on with awe, wonder, and envy.

Clojure:

user=> (defn list-to-string [x] (apply str x))
#'user/list-to-string
user=> (list-to-string (list 2 'foo 3 :bar))
"2foo3:bar"
From: Leandro Rios
Subject: Re: please review my complete working program
Date: 
Message-ID: <gon9rk$6k1$1@news.motzarella.org>
William James escribi�:
> david wrote:
> 
>> (defun list2string (list)
>>   (apply #'concatenate 'string (mapcar #'(lambda(a)
>>                                            (if (stringp a)
>>                                                a
>>                                              (if (symbolp a)
>>                                                  (symbol-name a)
>>                                                (princ-to-string a))))
>>                                  list)))
> 
> You and COBOL-LISP make a dynamite combination, an unbeatable
> tag-team!  I can only look on with awe, wonder, and envy.

Good! You've progressed from posting simplistic Ruby code snippets to 
spanking newbies in cll. I can only look at you with awe, wonder and envy.

> 
> Clojure:
> 
> user=> (defn list-to-string [x] (apply str x))
> #'user/list-to-string
> user=> (list-to-string (list 2 'foo 3 :bar))
> "2foo3:bar"

CL:

(defun list-to-string (x)
  (format nil "~{~S~}" x))

CL-USER> (list-to-string (list 2 'foo 3 :bar))
"2FOO3:BAR"

Leandro
From: Marco Antoniotti
Subject: Re: please review my complete working program
Date: 
Message-ID: <7ae7c351-3cf3-4395-901c-cd98f118f786@r3g2000vbp.googlegroups.com>
On Mar 5, 1:11 am, "William James" <·········@yahoo.com> wrote:
> david wrote:
> > (defun list2string (list)
> >   (apply #'concatenate 'string (mapcar #'(lambda(a)
> >                                            (if (stringp a)
> >                                                a
> >                                              (if (symbolp a)
> >                                                  (symbol-name a)
> >                                                (princ-to-string a))))
> >                                  list)))
>
> You and COBOL-LISP make a dynamite combination, an unbeatable
> tag-team!  I can only look on with awe, wonder, and envy.

You better!  How are the two homeworks required of you coming?  I have
not seen anybody in comp.lang.ruby, http://groups.google.com/group/clojure,
or the F# sites helping you.

> Clojure:
>
> user=> (defn list-to-string [x] (apply str x))
> #'user/list-to-string
> user=> (list-to-string (list 2 'foo 3 :bar))
> "2foo3:bar"

    (defun list-to-string (l) (format nil "~{~A~}" l))

or

    (defun list-to-string (l) (apply 'to-string l))

    (defun to-string (&rest objs) (format nil "~{~A~}" objs))

Now.  Find the bit that's different between the above definition of
'to-string' and clojure 'str'.  This makes three, 3, THREE, tres, tre,
III, tria, drei, trois homeworks required of you (sorry I ran out of
languages).  Pile up more unfinished ones and you fail :)

Cheers
--
Marco
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <699d5912-77da-4efe-828c-60d6a6687d0c@x38g2000yqj.googlegroups.com>
On Mar 4, 6:11 pm, "William James" <·········@yahoo.com> wrote:
> You and COBOL-LISP make a dynamite combination, an unbeatable
> tag-team!  I can only look on with awe, wonder, and envy.

i like commune-lisp better. awe and wonder are good. envy will
poison your spirit.
From: André Thieme
Subject: Re: please review my complete working program
Date: 
Message-ID: <gors49$a8r$1@news.motzarella.org>
William James schrieb:
> david wrote:
> 
>> (defun list2string (list)
>>   (apply #'concatenate 'string (mapcar #'(lambda(a)
>>                                            (if (stringp a)
>>                                                a
>>                                              (if (symbolp a)
>>                                                  (symbol-name a)
>>                                                (princ-to-string a))))
>>                                  list)))
> 
> You and COBOL-LISP make a dynamite combination, an unbeatable
> tag-team!  I can only look on with awe, wonder, and envy.
> 
> Clojure:
> 
> user=> (defn list-to-string [x] (apply str x))
> #'user/list-to-string
> user=> (list-to-string (list 2 'foo 3 :bar))
> "2foo3:bar"

I think it is not a typical function one would define in Clojure.
First of all the "(apply str" is shorter than "(list2string".
Also, why should one stick on lists? applying str can be done on
lists, vectors, hashmaps, structure maps, sets, Java Vectors,
HashTables, arrays and all collection types.
Plus David uses it just once.
Why did you decide to comment this function?
You could have suggested to display the chessboard in a more modern
way, by having a real GUI. Instead of trying to paint with ASCII art
that would look much nicer IMO.
You could have mentioned that
(defun get-four-unique-random-numbers ()
   (loop
      :with results = '()
      :for alea = (random 64)
      :while (< (length results) 4)
      :do (pushnew alea results)
      :finally (return results)))

could be as well be expressed as
(defn get-four-unique-random-numbers []
   (take 4 (distinct (repeatedly #(rand-int 64))))

or instead of
(defun rank-file (position)
   (multiple-value-bind (quotient remainder)
                        (truncate position 8)
     (list  quotient  remainder)))

something like
(defn rank-file [position]
   [(quot position) (rem position)])

Maybe instead of
(defun reverse-rank-file (lst)
   (let ((x (first lst))
	(y (second lst)))
     (+ y (* 8 x))))

you could have suggested
(defn reverse-rank-file [[x y]]
   (+ y (* 8 x)))

Also it seems that he does not need all the low level functionality of
(with-open-file (stream
		 "C:\\Documents and Settings\\david\\Desktop\\bkend.fen"
	         :direction :output
		 :if-exists :supersede
		 :if-does-not-exist :create)
		 (format stream (almost-there)))

and would have used clojure.contrib.duck-streams and then said
(spit "/Documents and Settings/david/Desktop/bkend.fen" (almost-there))

Anyway, you two are making good progress. David and you are getting
better every day and find more into the lisp way of doing things :)


Andr�
-- 
Lisp is not dead. It�s just the URL that has changed:
http://clojure.org/
From: William James
Subject: Re: please review my complete working program
Date: 
Message-ID: <gon5gc01spo@enews4.newsguy.com>
david wrote:

> with-open-file (stream
> 		 "C:\\Documents and Settings\\david\\Desktop\\bkend.fen"

Did you try
"C:/Documents and Settings/david/Desktop/bkend.fen" ?

If not, why not?
From: david
Subject: Re: please review my complete working program
Date: 
Message-ID: <2fc27cfb-c0bd-4339-9390-37b007e13508@d19g2000yqb.googlegroups.com>
On Mar 4, 6:14 pm, "William James" <·········@yahoo.com> wrote:
> david wrote:
> > with-open-file (stream
> >             "C:\\Documents and Settings\\david\\Desktop\\bkend.fen"
>
> Did you try
> "C:/Documents and Settings/david/Desktop/bkend.fen" ?
>
> If not, why not?

i didn't try that but i will.
i was thinking since windows use forward slash i would
leave it that way.
thanks, david