From: david
Subject: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <696e4651-4cab-4830-b67a-7fbf5cfb6273@k19g2000yqg.googlegroups.com>
i am very much obliged to the labors of messieurs Bourguignon and
Margolin. i have made free use of their code.

(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 get-positions ()
  (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)))

(defvar wk)
(defvar wb)
(defvar wn)
(defvar bk)
(defvar a)

(destructuring-bind (wk-temp wb-temp wn-temp bk-temp)
                    (get-positions)
  (setq wk (rank-file wk-temp)
        wb (rank-file wb-temp)
        wn (rank-file wn-temp)
        bk (rank-file bk-temp)))

(setf a (make-instance 'chessboard))

(put-piece a (first wk)(second wk) 'wk)
(put-piece a (first wb)(second wb) 'wb)
(put-piece a (first wn)(second wn) 'wn)
(put-piece a (first bk)(second bk) 'bk)

From: Leandro Rios
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <gnp2fj$im$1@news.motzarella.org>
david escribi�:
> i am very much obliged to the labors of messieurs Bourguignon and
> Margolin. i have made free use of their code.
> 
> (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 get-positions ()
>   (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)))
> 
> (defvar wk)
> (defvar wb)
> (defvar wn)
> (defvar bk)
> (defvar a)

Remember the earmuffs convention.

> 
> (destructuring-bind (wk-temp wb-temp wn-temp bk-temp)
>                     (get-positions)
>   (setq wk (rank-file wk-temp)
>         wb (rank-file wb-temp)
>         wn (rank-file wn-temp)
>         bk (rank-file bk-temp)))
> 
> (setf a (make-instance 'chessboard))
> 
> (put-piece a (first wk)(second wk) 'wk)
> (put-piece a (first wb)(second wb) 'wb)
> (put-piece a (first wn)(second wn) 'wn)
> (put-piece a (first bk)(second bk) 'bk)

All this can be reduced to:

(mapc #'(lambda (pos piece)
	  (put-piece a (first pos) (second pos) piece))
       (mapcar #'rank-file (get-positions)) '(wk wb wn bk))

This way you get rid of the intermediate globals wk wb wn and bk.

Abstracting board generation into a single function:

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

Now you can generate multiple keyboards because they are no longer 
stored in the global variable a. You can store them, of course, if you 
need to:

(defparameter *board* (random-chessboard))


Leandro
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <4c99796d-9c49-4109-b125-03e171245428@l39g2000yqn.googlegroups.com>
On Feb 21, 8:18 am, Leandro Rios <··················@gmail.com>
wrote:
> Remember the earmuffs convention.
>

thanks. i will incorporate into the next version.
speaking of versions, i wonder if i should start
learning a vcs yet.
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <be2312b3-847a-4ec7-a55d-bd49a92ef9a3@e18g2000yqo.googlegroups.com>
On Feb 21, 8:18 am, Leandro Rios <··················@gmail.com> wrote:
> All this can be reduced to:
>
> (mapc #'(lambda (pos piece)
>           (put-piece a (first pos) (second pos) piece))
>        (mapcar #'rank-file (get-positions)) '(wk wb wn bk))
>
> This way you get rid of the intermediate globals wk wb wn and bk.
>
> Abstracting board generation into a single function:
>
> (defun random-chessboard ()
> "Returns a fresh random chessboard with pieces wk wb wn and bk."
>    (let ((chessboard (make-instance 'chessboard)))
>      (mapc #'(lambda (pos piece)
>               (put-piece chessboard (first pos)
>                          (second pos) piece))
>           (mapcar #'rank-file (get-positions)) '(wk wb wn bk))
>      chessboard))
>
> Now you can generate multiple keyboards because they are no longer
> stored in the global variable a. You can store them, of course, if you
> need to:
>
> (defparameter *board* (random-chessboard))
>
> Leandro

i have written a function illegalp that uses *wk* and *bk*
if random-chessboard return an illegal position it needs to
try again. how can i integrate this function? or is this
the wrong function to have written. i am thinking good cl
style would define general methods to know where pieces are
and their relation to each other. but this is deep water for
me. i am thinking perhaps i should table this project until
i read 2 or 3 more lisp books. i am thinking cll is no big
on quick and dirty :)
i have too many thinkuns in my noggin.
thanks, david
From: Thomas A. Russ
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <ymiocwsu5h4.fsf@blackcat.isi.edu>
david <······@gmail.com> writes:
> 
> i have written a function illegalp that uses *wk* and *bk*
> if random-chessboard return an illegal position it needs to
> try again. how can i integrate this function?

You sould normally just call it where you needed to.
Presumably at some point before returning a position.

If the current candidate position doesn't pass, just generate another
one.  A simply method would be:

(loop for candidate = (generate-candicate-setup)
      while (illegalp candidate)
      finally (return candidate))

>  or is this
> the wrong function to have written. i am thinking good cl
> style would define general methods to know where pieces are
> and their relation to each other. but this is deep water for
> me. i am thinking perhaps i should table this project until
> i read 2 or 3 more lisp books.

Perhaps.  But once you have read one book, it helps to try out a project
and see what areas are unclear.  Only then will the additional books
really help.

>  i am thinking cll is no big
> on quick and dirty :)

Actually, lisp is ideal for quick and dirty.  And on cll you will often
see just such a solution before some of the more thoughtful and
elaborate solutions will be posted.

Depending on your needs the quick and dirty solution may be entirely
adequate.  And the interactive environment makes it easy to put such a
solution together and try it out.

Of course, we do prefer the adjective "agile" to "quick and dirty". ;-)


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Rob Warnock
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <-tadnW0HDM1F1D7UnZ2dnUVZ_i2WnZ2d@speakeasy.net>
Thomas A. Russ <···@sevak.isi.edu> wrote:
+---------------
| david <······@gmail.com> writes:
| > i am thinking cll is no big on quick and dirty :)
| 
| Actually, lisp is ideal for quick and dirty.
...
| Of course, we do prefer the adjective "agile" to "quick and dirty". ;-)
+---------------

(*sigh*) I wished you'd mentioned that several years ago.
I could have named my toy CL subset "Agile Lisp" instead
of "Quick and Dirty Lisp" (QDL)!!  ;-}  ;-}


-Rob

-----
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 new *working* code - now with 20% more oop!
Date: 
Message-ID: <gnvf4f0fjj@enews2.newsguy.com>
Thomas A. Russ wrote:

> 
> If the current candidate position doesn't pass, just generate another
> one.  A simply method would be:
> 
> (loop for candidate = (generate-candicate-setup)
>       while (illegalp candidate)
>       finally (return candidate))

Clojure:

(first (drop-while illegal? (repeatedly generate-candidate)))
From: DanL
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <4f61c572-227c-44fe-9869-20d6f0b94366@m42g2000yqb.googlegroups.com>
On Feb 24, 1:31 am, "William James" <·········@yahoo.com> wrote:
> (first (drop-while illegal? (repeatedly generate-candidate)))

(collect-first (choose-if (complement #'illegalp) (#mgenerate-
candidate)))
From: William James
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <gnvfop1fjj@enews2.newsguy.com>
William James wrote:

> Thomas A. Russ wrote:
> 
> > 
> > If the current candidate position doesn't pass, just generate another
> > one.  A simply method would be:
> > 
> > (loop for candidate = (generate-candicate-setup)
> >       while (illegalp candidate)
> >       finally (return candidate))
> 
> Clojure:
> 
> (first (drop-while illegal? (repeatedly generate-candidate)))

Ruby:

while (x = rand) < 0.99 do  end; x
    ==>0.995675146956753
From: Pascal J. Bourguignon
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <87y6vwaa5j.fsf@galatea.local>
david <······@gmail.com> writes:
> i have written a function illegalp that uses *wk* and *bk*
> if random-chessboard return an illegal position it needs to
> try again. how can i integrate this function? 

Perhaps you'd have less problem integrating it if it didn't use global
variables?

Try to write it as (defun illegalp (wk bk) ...)

and call it as (illegalp *wk* *bk*) where you need it.


> or is this
> the wrong function to have written. i am thinking good cl
> style would define general methods to know where pieces are
> and their relation to each other. 

Yes, that's a good idea.

> but this is deep water for
> me. i am thinking perhaps i should table this project until
> i read 2 or 3 more lisp books. i am thinking cll is no big
> on quick and dirty :)
> i have too many thinkuns in my noggin.

Well, you can learn a lot in doing.  Perhaps you'll be ashamed of your
code in a few years, but it's ok, you're learning, you cannot produce
expert quality code the first time.


So, to come back to this idea of having high level "methods" about the
pieces positions and relationships, it's not too hard to do.

You first start by writting in English the sentences you want to be
able to say. eg.
   "the left up diagonal of bishop B"
   "the first piece covered on the right down diagonal of bishop B"
   "the pieces covered by king K"
   "the cell two rows on the right, one column up from cell C"
etc.

Then coarsely, you take the nouns in and make them classes, and the
verbs and make them methods.

You may have classes such CELL, DIAGONAL, ROW, COLUMN.
You already have classes such as BOARD, PIECE.

Then you can define methods, such as (cell on-the-right) 
or (diagonal first-piece-covered).


(The key is to see CELLs as independent objects, in relation with
their 8 neighbors).


-- 
__Pascal Bourguignon__
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <f026c8a6-7e30-4081-84d7-a6d3e3f5fe85@u38g2000yqe.googlegroups.com>
On Feb 23, 7:36 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Perhaps you'd have less problem integrating it if it didn't use global
> variables?
>
if i am free to pass around globals i would be done already :)
someone told me: "Using global variables is wrong anyways.  It will
bite you.  Just say no." i was trying to integrate my test into
Leandro Rios' very nice
code. i understand the benefits (i think) of programming this way,
but it is a new way of thinking for me. also i am still mystified
by print-fen method you wrote :)


> Well, you can learn a lot in doing.  Perhaps you'll be ashamed of your
> code in a few years, but it's ok, you're learning, you cannot produce
> expert quality code the first time.
>

if i ever produce any expert quality code i will print it out and
frame it.
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <06f32e29-d308-4b74-b15e-cd7bd6eafad7@q9g2000yqc.googlegroups.com>
doh! i forgot my code:

(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-positions ()
  (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)))

(defvar *wk*)
(defvar *wb*)
(defvar *wn*)
(defvar *bk*)
(defvar *a*)

(destructuring-bind (wk-temp wb-temp wn-temp bk-temp)
                    (get-positions)
  (setq *wk* (rank-file wk-temp)
        *wb* (rank-file wb-temp)
        *wn* (rank-file wn-temp)
        *bk* (rank-file bk-temp)))

(setf *a* (make-instance 'chessboard))

(put-piece *a* (first wk)(second wk) 'wk)
(put-piece *a* (first wb)(second wb) 'wb)
(put-piece *a* (first wn)(second wn) 'wn)
(put-piece *a* (first bk)(second bk) 'bk)

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

(defun illegalp ()
  (let ((badsquares (loop for x in (neighbor (first *wk*))
		      append (loop for y in (neighbor (second *wk*))
				collect (list x y)))))
    (position *bk* badsquares)))




well not so much is actually my code now :)
please for thinkuns.
From: Rob Warnock
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <2t-dnV2TcazAyj7UnZ2dnUVZ_s7inZ2d@speakeasy.net>
Leandro Rios <··················@gmail.com> wrote:
+---------------
| Remember the earmuffs convention.
..[and a DESTRUCTURING-BIND suggestion]...
+---------------
 
To which David <······@gmail.com> replied:
+---------------
| (defvar *wk*)
| (defvar *wb*)
| (defvar *wn*)
| (defvar *bk*)
| (defvar *a*)
| 
| (destructuring-bind (wk-temp wb-temp wn-temp bk-temp)
|                     (get-positions)
|   (setq *wk* (rank-file wk-temp)
|         *wb* (rank-file wb-temp)
|         *wn* (rank-file wn-temp)
|         *bk* (rank-file bk-temp)))
| 
| (setf *a* (make-instance 'chessboard))
| 
| (put-piece *a* (first wk)(second wk) 'wk)
| (put-piece *a* (first wb)(second wb) 'wb)
| (put-piece *a* (first wn)(second wn) 'wn)
| (put-piece *a* (first bk)(second bk) 'bk)
+---------------

Two comments:

First, I suspect Leandro was really trying to suggst eliminating the
*WK*/*WB*/*WN*/*BK* global variables *entirely*! Something like this:

    (defvar *a* (make-instance 'chessboard))

    (destructuring-bind (wk wb wn bk)
	(mapcar #'rank-file (get-positions))
      (macrolet ((frob (x)
		   `(put-piece *a* (first ,x) (second ,x) ',x)))
	(frob wk)
	(frob wb)
	(frob wn)
	(frob bk)))

Or more straightforwardly [IMHO!]:

    (defvar *a* (make-instance 'chessboard))

    (loop for piece in '(wk wb wn bk)
	  and (rank column) in (mapcar #'rank-file (get-positions))
      do (put-piece *a* rank column piece))

Secondly [and somewhat contrary to the above], I personally think
there's nothing wrong with doing a little fast prototyping with global
variables, *if* instead of DEFVAR (with earmuffs on the variables)
one uses DEFLEX[1] (with no earmuffs) for those sorts of developmental
convenience globals. One particular advantage, which I didn't discover
until after I'd been using DEFLEX for a while, is that once you've
figured out what you're doing they're *really* easy to fold into a LET*,
without having to do any massive renaming to get rid of the earmuffs.

For example, I once wrote a quick little hack to scan some CL source
code and build a dependency tree of the DEFSTRUCT includes. The first
cut had a section that looked like this:

    (deflex filename "some/long/fixed/path/to/foo.lisp")

    (deflex node-forms (file-forms filename))

    (deflex structs (remove 'defstruct node-forms
                            :key #'car :test-not #'eq))

    (deflex name-and-options (mapcar #'second structs))

    (defun prune (name-and-options)
      "Given the 2nd subform of a DEFSTRUCT, if there was an :INCLUDE
      option return a list of the structure name and the name of the
      included parent structure, else just retutn the structure name."
      (cond
        ((symbolp name-and-options)
         name-and-options)
        ((atom name-and-options)
         (error "Bad name-and-options: ~s" name-and-options))
        ((find :include (cdr name-and-options) :key #'car)
         (list (car name-and-options)
               (cadr (find :include (cdr name-and-options) :key #'car))))
        ((symbolp (car name-and-options))
         (car name-and-options))
        (t
         (error "Bad name-and-options: ~s" name-and-options))))

    (deflex names-and-includes (mapcar #'prune name-and-options))

    ...[then a topological sort and a tree walk and I was done].

The advantage of this is, of course, that you can get each step
working correctly in isolation before moving on to the next. The
variable are sitting right there at the top-level, easy to print,
poke at, whatever, but guaranteed *not* to conflict with any bound
lexicals in any functions you might be calling, since they're
"lexicals" themselves. And once it was all working, it was then
easy to delete the first token of each of the DEFLEX forms, wrap
a LET* and DEFUN around them, and get this much cleaner form:

    (defun prune (name-and-options) ...[as above]...)

    (defun struct-names-and-includes (filename)
      (let* ((node-forms (file-forms filename))
             (structs (remove 'defstruct node-forms
                              :key #'car :test-not #'eq))
             (name-and-options (mapcar #'second structs)))
        (mapcar #'prune name-and-options)))

[Note that this style of working *doesn't* tend to leave any
DEFLEX forms in your final, production version, which is probably
a good thing until the meme is a little more widely spread...]


-Rob

[1] <http://rpw3.org/hacks/lisp/deflex.lisp>, or something equivalent.

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Rob Warnock
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <oIGdnapotroB9T7UnZ2dnUVZ_hKWnZ2d@speakeasy.net>
Oops! I just wrote:
+---------------
| Or more straightforwardly [IMHO!]:
| 
|     (defvar *a* (make-instance 'chessboard))
| 
|     (loop for piece in '(wk wb wn bk)
|           and (rank column) in (mapcar #'rank-file (get-positions))
|       do (put-piece *a* rank column piece))
+---------------

Silly me! Why invent yet another name to confuse the reader of
one's code when the proper name is staring one right in the face?!?
Given that there is alread a function called #'RANK-FILE, *of course*
the destructuring temp should have been named FILE instead of COLUMN:

    (loop for piece in '(wk wb wn bk)
          and (rank file) in (mapcar #'rank-file (get-positions))
      do (put-piece *a* rank file piece))

Afterthought: The fact that one has to "know" that #'GET-POSITIONS
returns things in the order "WK WB WN BK" makes me uncomfortable.
It's too easy for it to get out of sync as the program evolves.
I'd feel a lot better about this whole thing if the values that
#'GET-POSITIONS returned had the piece name inside and if there were
a #'RANK-FILE-PIECE function so one could simply write this instead:

    (loop for (rank file piece) in (mapcar #'rank-file-piece (get-positions))
      do (put-piece *a* rank file piece))

Or, if you don't like LOOP:

    (dolist (position (get-positions))
      (destructuring-bind (rank file piece)
	  (rank-file-piece position)
	(put-piece *a* rank file piece)))


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <9ff225b3-df87-482b-ace7-8f3712d85344@w34g2000yqm.googlegroups.com>
On Feb 23, 9:25 pm, ····@rpw3.org (Rob Warnock) wrote:

> Or, if you don't like LOOP:
>
>     (dolist (position (get-positions))
>       (destructuring-bind (rank file piece)
>           (rank-file-piece position)
>         (put-piece *a* rank file piece)))
>

i like loop.
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <4bf9f4de-0f18-4a7f-8fd1-88893ae66f8f@h20g2000yqn.googlegroups.com>
On Feb 23, 9:25 pm, ····@rpw3.org (Rob Warnock) wrote:
>
> Afterthought: The fact that one has to "know" that #'GET-POSITIONS
> returns things in the order "WK WB WN BK" makes me uncomfortable.

i don't think one does. get-positions just makes four unique
random numbers. for my program it doesnt matter which get
assigned where. maybe to rename it get-4-urn. and add a doc
string. thanks for your help.
-david
From: Thomas A. Russ
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <ymimycarqpe.fsf@blackcat.isi.edu>
david <······@gmail.com> writes:

> On Feb 23, 9:25 pm, ····@rpw3.org (Rob Warnock) wrote:
> >
> > Afterthought: The fact that one has to "know" that #'GET-POSITIONS
> > returns things in the order "WK WB WN BK" makes me uncomfortable.
> 
> i don't think one does. get-positions just makes four unique
> random numbers. for my program it doesnt matter which get
> assigned where. maybe to rename it get-4-urn. and add a doc
> string. thanks for your help.

Well, maybe just naming it GET-N-BOARD-POSITIONS and passing 4 as the
argument would do it.  For absolute clarity one could also insert the
word "UNIQUE" after "N" in the name.


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <7c7ebaf3-ca4e-41f7-aa33-651c953c3a5b@v19g2000yqn.googlegroups.com>
On Feb 23, 9:25 pm, ····@rpw3.org (Rob Warnock) wrote:
> Afterthought: The fact that one has to "know" that #'GET-POSITIONS
> returns things in the order "WK WB WN BK" makes me uncomfortable.

well it turns out you are absolutely correct.
it did become a problem as my program evolve.
thank you for pointing it out.
-david
From: Pascal J. Bourguignon
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <87ljrw9ptj.fsf@galatea.local>
····@rpw3.org (Rob Warnock) writes:
> Secondly [and somewhat contrary to the above], I personally think
> there's nothing wrong with doing a little fast prototyping with global
> variables, *if* instead of DEFVAR (with earmuffs on the variables)
> one uses DEFLEX[1] (with no earmuffs) for those sorts of developmental
> convenience globals. One particular advantage, which I didn't discover
> until after I'd been using DEFLEX for a while, is that once you've
> figured out what you're doing they're *really* easy to fold into a LET*,
> without having to do any massive renaming to get rid of the earmuffs.

Well I agree, but I'd say even more. 

LET is perfectly good to define "global" variables.
That is, we don't really need global variables, what we need are
variables at the REPL.

Since we are using emacs with which we can easily edit any character
anywhere in an emacs frame,  there's nothing preventing us to edit
exploratory code inside the REPL, and to use LET for REPL variables:

(let ((a (list 1 2 3 4)))
   (remove-if (function evenp) a))

RET then M-p edit and:

(let ((a (list 1 2 3 4)))
   (remove-if (function evenp)
   	          (mapcar (lambda (x) (1+ (* 3 x))) a)))

RET etc and when happy, M-p and substitute defun for let:

(defun foo (a)
   (remove-if (function evenp)
   	          (mapcar (lambda (x) (1+ (* 3 x))) a)))


Also, there's absolutely no reason why not use LET in cll example
code!  Even procedural example code:

(let (a b c x)
  (setf a 1 ; nice example of SETF
        b 2
        c 1)
  (values (list a b c)
          (list 'a 'b 'c))) ; to see the effect of QUOTE.

-- 
__Pascal Bourguignon__
From: William James
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <go0fkq1o3h@enews5.newsguy.com>
Pascal J. Bourguignon wrote:

> 
> (let ((a (list 1 2 3 4)))
>    (remove-if (function evenp)
>    	          (mapcar (lambda (x) (1+ (* 3 x))) a)))

Clojure:

user=> (let [a '(1 2 3 4)]
  (remove even? (map #(+ 1 (* 3 %)) a)))
(7 13)
From: =?UTF-8?B?QW5kcsOpIFRoaWVtZQ==?=
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <go1djt$5rd$2@news.motzarella.org>
William James schrieb:
> Pascal J. Bourguignon wrote:
> 
>> (let ((a (list 1 2 3 4)))
>>    (remove-if (function evenp)
>>    	          (mapcar (lambda (x) (1+ (* 3 x))) a)))
> 
> Clojure:
> 
> user=> (let [a '(1 2 3 4)]
>   (remove even? (map #(+ 1 (* 3 %)) a)))
> (7 13)

It’s good, but one would say [1 2 3 4] vs '(1 2 3 4).
Lists are not so often used in Clojure anymore.
I think Xah Lee enjoys this, because he is scared about CONS ;)


André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/
From: John Thingstad
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <op.upusixbuut4oq5@pandora.alfanett.no>
P� Tue, 24 Feb 2009 09:55:36 +0100, skrev Pascal J. Bourguignon  
<···@informatimago.com>:

>
> (let ((a (list 1 2 3 4)))
>    (remove-if (function evenp) a))
>
> RET then M-p edit and:
>
> (let ((a (list 1 2 3 4)))
>    (remove-if (function evenp)
>    	          (mapcar (lambda (x) (1+ (* 3 x))) a)))
>
> RET etc and when happy, M-p and substitute defun for let:
>
> (defun foo (a)
>    (remove-if (function evenp)
>    	          (mapcar (lambda (x) (1+ (* 3 x))) a)))
>
>
> Also, there's absolutely no reason why not use LET in cll example
> code!  Even procedural example code:
>
> (let (a b c x)
>   (setf a 1 ; nice example of SETF
>         b 2
>         c 1)
>   (values (list a b c)
>           (list 'a 'b 'c))) ; to see the effect of QUOTE.
>

Well I can think of one reason. If you are reusing the same datastructures  
again and again it is convenent to define them in a defparameter. Provided  
you put them in a designated package say (defpackage :testing (:use :cl))  
(in-package :testing) you only need to (in-package :cl-user)  
(delete-package :testing) to get rid of the variables when you are  
finished.

--------------
John Thingstad
From: Rob Warnock
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <x4OdnQQEnLSSgzjUnZ2dnUVZ_hGWnZ2d@speakeasy.net>
Pascal J. Bourguignon <···@informatimago.com> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) writes:
| > Secondly [and somewhat contrary to the above], I personally think
| > there's nothing wrong with doing a little fast prototyping with global
| > variables, *if* instead of DEFVAR (with earmuffs on the variables)
| > one uses DEFLEX[1] (with no earmuffs) for those sorts of developmental
| > convenience globals. One particular advantage, which I didn't discover
| > until after I'd been using DEFLEX for a while, is that once you've
| > figured out what you're doing they're *really* easy to fold into a LET*,
| > without having to do any massive renaming to get rid of the earmuffs.
| 
| Well I agree, but I'd say even more. 
| 
| LET is perfectly good to define "global" variables.
| That is, we don't really need global variables, what we need are
| variables at the REPL.
+---------------

That's what DEFLEX gives you, "variables at the REPL" that can
be safely rebound lexically without confusion.

+---------------
| Since we are using emacs with which we can easily edit any character
| anywhere in an emacs frame...
+---------------

[Note: *You* may be using Emacs; I'm not.]

+---------------
| ...there's nothing preventing us to edit exploratory code inside
| the REPL, and to use LET for REPL variables:
| 
| (let ((a (list 1 2 3 4)))
|    (remove-if (function evenp) a))
+---------------

This problem with this example is that it's way too simplistic.
Suppose the real task you're doing is something like this:

    (let* ((a (some-really-*long*-computation))  ; takes ~20 min to run
	   (b (we-do-not-really-know-yet-what-we-want-to-do-here a)))
      b)

then [IMHO] it's far better to do:

    (deflex a (some-really-*long*-computation))

and then noodle around figuring out what you want to do with the
values in A. You may decide you only want to do some of the
processing in the next step, so first you add that:

    (deflex b (we-do-this-much-at-least a))

and now we have B available to poke around at. We can even back up
and change part of the processing without having to recompute A:

    (deflex b (a-slightly-different-algorithm a))

But then, when it's *all* working correctly, sweep it into a single
LET* in inside a DEFUN:

    (defun foo ()
      (let* ((a (some-really-*long*-computation))
	     (b (a-slightly-different-algorithm a))
	     (c (the-rest-of-the-processing b)))
	c))

But I see no reason to sit there staring at an idle screen for 20
minutes at a shot each time I change something during development.


-Rob

-----
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 new *working* code - now with 20% more oop!
Date: 
Message-ID: <go015t0deo@enews5.newsguy.com>
david wrote:

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

Clojure:

(take 4 (repeatedly #(rand-int 64)))

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

(map #(% position 8) (list quot rem))
From: André Thieme
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <go1def$5rd$1@news.motzarella.org>
William James schrieb:
> david wrote:
> 
>> (defun get-positions ()
>>   (loop
>>      :with results = '()
>>      :for alea = (random 64)
>>      :while (< (length results) 4)
>>      :do (pushnew alea results)
>>      :finally (return results)))
> 
> Clojure:
> 
> (take 4 (repeatedly #(rand-int 64)))

CL
(loop repeat 4 collect (random 64))


Andr�
-- 
Lisp is not dead. It�s just the URL that has changed:
http://clojure.org/
From: Pascal J. Bourguignon
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <87hc2jadyu.fsf@galatea.local>
Andr� Thieme <······························@justmail.de> writes:

> William James schrieb:
>> david wrote:
>> 
>>> (defun get-positions ()
>>>   (loop
>>>      :with results = '()
>>>      :for alea = (random 64)
>>>      :while (< (length results) 4)
>>>      :do (pushnew alea results)
>>>      :finally (return results)))
>> Clojure:
>> (take 4 (repeatedly #(rand-int 64)))
>
> CL
> (loop repeat 4 collect (random 64))

Andr�, you should stop clojure, it burns too much of your neurons. ;-)
GET-POSITION doesn't return a list of four random numbers!
Read it again!

-- 
__Pascal Bourguignon__
From: André Thieme
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <go1esu$p5t$1@news.motzarella.org>
Pascal J. Bourguignon schrieb:
> Andr� Thieme <······························@justmail.de> writes:
> 
>> William James schrieb:
>>> david wrote:
>>>
>>>> (defun get-positions ()
>>>>   (loop
>>>>      :with results = '()
>>>>      :for alea = (random 64)
>>>>      :while (< (length results) 4)
>>>>      :do (pushnew alea results)
>>>>      :finally (return results)))
>>> Clojure:
>>> (take 4 (repeatedly #(rand-int 64)))
>> CL
>> (loop repeat 4 collect (random 64))
> 
> Andr�, you should stop clojure, it burns too much of your neurons. ;-)

Hehe ;)
Well, it is actually pretty good for training neurons.
Finally I can program in my preferred style. This does not make CL
suddenly bad of course. It�s just that I prefer some other Lisp.


> GET-POSITION doesn't return a list of four random numbers!
> Read it again!

Obviously. And, believe it or not, I did not try to implement
get-positions, but instead wanted to do what William did.

I am glad he is much closer to on-topic posts, now that he writes
Lisp.
Anyway, he did not recognize what pushnew is doing.
Some days ago I showed a Clojure solution to that problem. It was:
(take 4 (distinct (repeatedly #(rant-int 64))))


Andr�
-- 
Lisp is not dead. It�s just the URL that has changed:
http://clojure.org/
From: Pascal J. Bourguignon
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <878wnvad1s.fsf@galatea.local>
André Thieme <······························@justmail.de> writes:

> Pascal J. Bourguignon schrieb:
>> André Thieme <······························@justmail.de> writes:
>> 
>>> William James schrieb:
>>>> david wrote:
>>>>
>>>>> (defun get-positions ()
>>>>>   (loop
>>>>>      :with results = '()
>>>>>      :for alea = (random 64)
>>>>>      :while (< (length results) 4)
>>>>>      :do (pushnew alea results)
>>>>>      :finally (return results)))
>>>> Clojure:
>>>> (take 4 (repeatedly #(rand-int 64)))
>>> CL
>>> (loop repeat 4 collect (random 64))
>> André, you should stop clojure, it burns too much of your
>> neurons. ;-)
>
> Hehe ;)
> Well, it is actually pretty good for training neurons.
> Finally I can program in my preferred style. This does not make CL
> suddenly bad of course. It’s just that I prefer some other Lisp.
>
>
>> GET-POSITION doesn't return a list of four random numbers!
>> Read it again!
>
> Obviously. And, believe it or not, I did not try to implement
> get-positions, but instead wanted to do what William did.

Ah, sorry.  These threads become hard to follow...


> I am glad he is much closer to on-topic posts, now that he writes
> Lisp.
> Anyway, he did not recognize what pushnew is doing.
> Some days ago I showed a Clojure solution to that problem. It was:
> (take 4 (distinct (repeatedly #(rant-int 64))))
>
>
> André

-- 
__Pascal Bourguignon__
From: Pascal J. Bourguignon
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <874oyngaq4.fsf@galatea.local>
david <······@gmail.com> writes:

> i am very much obliged to the labors of messieurs Bourguignon and
> Margolin. i have made free use of their code.

You should add a print-object method for your chessboard, so you can
see what happens.


(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)
(put-piece a 0 0 'wr)


C/CB[538]> a
#<CHESSBOARD
   
    | A  | B  | C  | D  | E  | F  | G  | H  |    
----+----+----+----+----+----+----+----+----+----
  8 |    |    |    |    |    |    |    |    |  8 
----+----+----+----+----+----+----+----+----+----
  7 | BK |    |    |    |    |    |    |    |  7 
----+----+----+----+----+----+----+----+----+----
  6 |    |    |    |    |    |    |    |    |  6 
----+----+----+----+----+----+----+----+----+----
  5 |    |    |    |    |    |    |    |    |  5 
----+----+----+----+----+----+----+----+----+----
  4 |    |    |    |    |    |    |    | WK |  4 
----+----+----+----+----+----+----+----+----+----
  3 |    |    |    |    |    |    |    |    |  3 
----+----+----+----+----+----+----+----+----+----
  2 |    | WB |    |    |    |    |    |    |  2 
----+----+----+----+----+----+----+----+----+----
  1 | WR |    |    |    |    |    |    | WN |  1 
----+----+----+----+----+----+----+----+----+----
    | A  | B  | C  | D  | E  | F  | G  | H  |    

  #x1A252EB1>
C/CB[539]> 



This is an important thing newbies need to learn, and one of the
problem alphabetic_rules has currently:  You need to learn to read and
listen to what the computer tells you.  We need to keep in mind two
states, and always be matching then and reconciliate them: 

- first we imagine the state the program should be in when and after
  executing.  This we do by knowing the meaning of the expressions and
  "running" the program in our head.

- then we try the program, and we must read the computer output and
  from this, infer the actual state of the program.

So we can compare both states, and if there is a difference, we must
find out whether it's because we didn't "run" it correctly in our
head, or whether it's because there's an error in the code and we need
to correct the program.


With most development environments, being informed of the program state
is rather difficult.  You must use debuggers that have their own bugs
and shortcommings, or you have to put a lot of PRINT statements all
over the program and be lost in the details of the traces...

With Lisp and other interactive environment, the REPL helps a lot,
since it always prints the result of any expression you type, so you
always get immediate feedback, and you can closely match the program
state with your mental state.  But when you design complex or opaque
data structures (such as CLOS objects), you need to write functions to
print them in a more readable and explicit format to continue
benefiting from this feedback loop.  Some Lisp environments are even
able to "print" graphical or auditive objects, so when you (print
image), you get the image displayed in the REPL.
http://collison.ie/blog/2008/06/pictures-in-the-slime-repl
Imagine you have some complex object such as a graph, and when you get
it from the REPL, it's displayed as an image of the nodes and edges.


-- 
__Pascal Bourguignon__
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <dabe9702-a8e8-4631-9cd9-b8037a59c083@f20g2000yqg.googlegroups.com>
On Feb 21, 7:50 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> You should add a print-object method for your chessboard, so you can
> see what happens.

i added yours. its beautiful.

> This is an important thing newbies need to learn, and one of the
> problem alphabetic_rules has currently:

i do not get this reference to alphabetic_rules

> image), you get the image displayed in the REPL.http://collison.ie/blog/2008/06/pictures-in-the-slime-repl

that is way cool. thanks for your thoughts.
i think i understand what you were saying earlier about
working with a chessboard abstraction instead of thinking
about what i wanted my program to output.

also thanks for those links to sicp in cl.
i was going to put off scheme for a while and try to get some cl
experience. right now i am reading touretzky 'symbolic computation'
and starting norvig paip. i hear sicp is great so would you
recommend trying that in cl, switching to scheme, or finishing paip
and pcl and on lisp etc.

as for my program, next i need to make a method to determine
if a position is legal chess position. in a bishop knight
endgame the only illegal position i can think of is if the
kings are adjacent. since for the purpose of this program
it will always be black to move, castling and enpassant
nil. i was thinking to compare the array indices somehow.
anyway, thanks for taking time to teach an old dog a few
new tricks :)
- david
From: Pascal J. Bourguignon
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <87zlgfeiwz.fsf@galatea.local>
david <······@gmail.com> writes:

> On Feb 21, 7:50 am, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> You should add a print-object method for your chessboard, so you can
>> see what happens.
>
> i added yours. its beautiful.
>
>> This is an important thing newbies need to learn, and one of the
>> problem alphabetic_rules has currently:
>
> i do not get this reference to alphabetic_rules

Sorry, it's alphabet_rules.
I hope you don't read only your own threads.


>> image), you get the image displayed in the REPL.http://collison.ie/blog/2008/06/pictures-in-the-slime-repl
>
> that is way cool. thanks for your thoughts.
> i think i understand what you were saying earlier about
> working with a chessboard abstraction instead of thinking
> about what i wanted my program to output.
>
> also thanks for those links to sicp in cl.
> i was going to put off scheme for a while and try to get some cl
> experience. right now i am reading touretzky 'symbolic computation'
> and starting norvig paip. i hear sicp is great so would you
> recommend trying that in cl, switching to scheme, or finishing paip
> and pcl and on lisp etc.

I think that you can get the best benefit from sicp when you already
know how to program.  SICP is not specifically about scheme, but about
programming.  (It only uses scheme for its examples and exercises as a
simple pseudo-code language).

So finish studying your current books, and then you will read SICP and
become an even better programmer.

>

-- 
__Pascal Bourguignon__
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <18dcfdd7-a578-4be0-a05d-c0f7e566a459@m42g2000yqb.googlegroups.com>
On Feb 21, 12:36 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:
> Sorry, it'salphabet_rules.
> I hope you don't read only your own threads.

> So finish studying your current books, and then you will read SICP and
> become an even better programmer.
> --
> __Pascal Bourguignon__

i had read parts of that thread. and i searched the newsgroup and
google.
i try to be good and do my homework :)
trying to read sicp a while back is what led me back into math.
anyway thats the path i will follow then.
maybe i will post my newbie interpretation of paip for the group to
criticize. google groups is not the best way to read usenet i think.
maybe i will buy a newsgroup feed so i can read them in emacs.
anyway, you sir, have the patience of a saint. i hope to do as well
should i ever finish school and escape the restaurant business.
my writing is a mess, maybe i should subscribe to comp.lang.english
thanks, david
From: J Kenneth King
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <87ocwttbtg.fsf@agentultra.com>
david <······@gmail.com> writes:

> On Feb 21, 12:36 pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> Sorry, it'salphabet_rules.
>> I hope you don't read only your own threads.
>
>> So finish studying your current books, and then you will read SICP and
>> become an even better programmer.
>> --
>> __Pascal Bourguignon__
>
> i had read parts of that thread. and i searched the newsgroup and
> google.
> i try to be good and do my homework :)
> trying to read sicp a while back is what led me back into math.
> anyway thats the path i will follow then.
> maybe i will post my newbie interpretation of paip for the group to
> criticize. google groups is not the best way to read usenet i think.
> maybe i will buy a newsgroup feed so i can read them in emacs.
> anyway, you sir, have the patience of a saint. i hope to do as well
> should i ever finish school and escape the restaurant business.
> my writing is a mess, maybe i should subscribe to comp.lang.english
> thanks, david

FWIW, motzarella.net offers free text-only usenet access
From: david
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <149e43c7-9d82-4c8e-bc63-3fba7c7e76cc@17g2000vbf.googlegroups.com>
On Feb 23, 9:25 am, J Kenneth King <·····@agentultra.com> wrote:
> FWIW, motzarella.net offers free text-only usenet access

thanks. i went ahead and got a news server for 2.99/ mo.
and i'm checking out gnus.
if that doesnt work out i will check out motzarella.
From: Kojak
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <20090221202052.4c738e76@thor.janville.org>
Le Sat, 21 Feb 2009 19:36:44 +0100,
Pascal J. Bourguignon a écrit :

> david <······@gmail.com> writes:
> 
> > On Feb 21, 7:50 am, ····@informatimago.com (Pascal J. Bourguignon)
> > wrote:
> >> This is an important thing newbies need to learn, and one of the
> >> problem alphabetic_rules has currently:
> >
> > i do not get this reference to alphabetic_rules
> 
> Sorry, it's alphabet_rules.
> I hope you don't read only your own threads.

ROTFL ! :-D

Sorry, :-)

-- 
Jacques. ROTFL... :-D
From: Thomas A. Russ
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <ymiwsbht66p.fsf@blackcat.isi.edu>
···@informatimago.com (Pascal J. Bourguignon) writes:


> I think that you can get the best benefit from sicp when you already
> know how to program.  SICP is not specifically about scheme, but about
> programming.  (It only uses scheme for its examples and exercises as a
> simple pseudo-code language).

Interestingly enough, one of the authors of SICP (I forget whether it
was Abelson or G. Sussman) indicated that they had an easier time
teaching the class based on the book to incoming students who had NOT
had any previous computer classes in high school.  Those that came to
SICP with existing notions about computer programming had to first be
de-programmed before they could grasp what was going on.

[And aren't we all familiar with the resistance some new Lisp learners
show toward the different view of programming that Lisp encourages or
requires.]

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Pascal J. Bourguignon
Subject: Re: please review my new *working* code - now with 20% more oop!
Date: 
Message-ID: <87k57harsg.fsf@galatea.local>
···@sevak.isi.edu (Thomas A. Russ) writes:

> ···@informatimago.com (Pascal J. Bourguignon) writes:
>
>
>> I think that you can get the best benefit from sicp when you already
>> know how to program.  SICP is not specifically about scheme, but about
>> programming.  (It only uses scheme for its examples and exercises as a
>> simple pseudo-code language).
>
> Interestingly enough, one of the authors of SICP (I forget whether it
> was Abelson or G. Sussman) indicated that they had an easier time
> teaching the class based on the book to incoming students who had NOT
> had any previous computer classes in high school.  Those that came to
> SICP with existing notions about computer programming had to first be
> de-programmed before they could grasp what was going on.
>
> [And aren't we all familiar with the resistance some new Lisp learners
> show toward the different view of programming that Lisp encourages or
> requires.]

Well, for a newbie it would seem natural and not so enlightning than
for the  poor soul lost in the hell of concrete and repeatitive
programming.  

-- 
__Pascal Bourguignon__