From: jrwats
Subject: what is up with the sbcl compiler?!?!
Date: 
Message-ID: <e176ba1f-df79-4377-910d-dc61681c9d97@x69g2000hsx.googlegroups.com>
Ok Here's my glorious code that prints out my chess board all pretty
(decided to force myself to learn LISP by implementing my Chess/AI
course's project in it - from scratch).  When i load the below code it
works just dandy.  When I compile it and load the compiled fasl,
however, I only get the last row gets printed for each row (when you
set (aref (aref str-array i) j) you set each string's j (for all i's -
if that makes sense).

code:
(defun print-pieces (cur-board)
  (let ((count 0)
    (str-array #("--------" "--------" "--------" "--------"
             "--------" "--------" "--------" "--------")))
    (dotimes (i 8)
      (dotimes (j 8)
    (setf (aref (aref str-array i) j) #\-)))
    (iter-sparse-one (i #xFFFFFFFFFFFFFFFF)
      (let ((wpt (get-piece-type i *white-index* cur-board))
        (bpt (get-piece-type i *black-index* cur-board)))
    (cond ((= wpt *PAWN*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\P))
          ((= wpt *KNIGHT*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\N))
          ((= wpt *BISHOP*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\B))
          ((= wpt *ROOK*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\R))
          ((= wpt *QUEEN*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\Q))
          ((= wpt *KING*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\K))
          ((= bpt *PAWN*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\p))
          ((= bpt *KNIGHT*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\n))
          ((= bpt *BISHOP*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\b))
          ((= bpt *ROOK*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\r))
          ((= bpt *QUEEN*) (setf (aref (aref  str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\q))
          ((= bpt *KING*) (setf (aref (aref str-array (- 7 (floor
count 8))) (- 7 (mod count 8))) #\k))))
      (incf count))
    (dotimes (i 8)
      (format t "~a ~a~%" (- 8 i) (aref str-array i)))
    (format t "~%  ABCDEFGH~%")))

output from compile version:
* (print-pieces *board*)
8 rnbqkbnr
7 rnbqkbnr
6 rnbqkbnr
5 rnbqkbnr
4 rnbqkbnr
3 rnbqkbnr
2 rnbqkbnr
1 rnbqkbnr

  ABCDEFGH
NIL

output from "loaded" interpreted version:
* (print-pieces *board*)
8 rnbqkbnr
7 pppppppp
6 --------
5 --------
4 --------
3 --------
2 PPPPPPPP
1 RNBQKBNR

  ABCDEFGH
NIL

So... what's up - as I understand it the compile is for some reason
trying to optimize this function making the string array an array of
strings all pointing to the same string for some odd reason.  What can
I do to prevent this?

Thanks!
John Watson

From: Pillsy
Subject: Re: what is up with the sbcl compiler?!?!
Date: 
Message-ID: <0003dc11-abfb-44e5-aa4e-a68ae2a31d11@v4g2000hsf.googlegroups.com>
On Dec 7, 1:52 am, jrwats <······@gmail.com> wrote:
> When I compile it and load the compiled fasl, however, I only get
> the last row gets printed for each row (when you set
> (aref (aref str-array i) j) you set each string's j (for all i's -
> if that makes sense).

> code:
> (defun print-pieces (cur-board)
>   (let ((count 0)
>     (str-array #("--------" "--------" "--------" "--------"
>              "--------" "--------" "--------" "--------")))

What you're doing here is modifying a literal string, "--------" using
SETF. Modifying literal strings is undefined, presumably to allow
compilers to do the sort of thing SBCL is doing here.

You should create a fresh copy of the string for each element of the
initial vector, perhaps using MAKE-STRING.

>     (cond ((= wpt *PAWN*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\P))

Cheers,
Pillsy
From: Stanisław Halik
Subject: Re: what is up with the sbcl compiler?!?!
Date: 
Message-ID: <fjarpv$fk9$1@news2.task.gda.pl>
thus spoke jrwats <······@gmail.com>:

>  (let ((count 0)
>    (str-array #("--------" "--------" "--------" "--------"
>             "--------" "--------" "--------" "--------")))
> So... what's up - as I understand it the compile is for some reason
> trying to optimize this function making the string array an array of
> strings all pointing to the same string for some odd reason.  What can
> I do to prevent this?

#() creates a literal vector. use VECTOR instead.

-- 
mirrors are more fun than television
From: Stanisław Halik
Subject: Re: what is up with the sbcl compiler?!?!
Date: 
Message-ID: <fjarsd$g98$1@news2.task.gda.pl>
thus spoke jrwats <······@gmail.com>:

>  (let ((count 0)
>    (str-array #("--------" "--------" "--------" "--------"
>             "--------" "--------" "--------" "--------")))
> So... what's up - as I understand it the compile is for some reason
> trying to optimize this function making the string array an array of
> strings all pointing to the same string for some odd reason.  What can
> I do to prevent this?

#() creates a literal vector at read-time. use VECTOR instead.

-- 
mirrors are more fun than television
From: Alan Crowe
Subject: Re: what is up with the sbcl compiler?!?!
Date: 
Message-ID: <867ijqjn1p.fsf@cawtech.freeserve.co.uk>
jrwats <······@gmail.com> writes:

> So... what's up - as I understand it the compile is for some reason
> trying to optimize this function making the string array an array of
> strings all pointing to the same string for some odd reason.  What can
> I do to prevent this?

Pillsy has answered this: you have to use a function that
allocates memory at execute time. He didn't suggest whether
that should be

(let ((str-array (make-array 8
                             :initial-contents 
                             (loop repeat 8
                                   collect
                                   (make-string 8
                                                :initial-element #\-)))))
  ...)

or

(let ((str-array (make-array 8)))
  (map-into str-array (lambda()(make-string 8 :initial-element #\-))))

Both are slightly clumsy. The usual Lisp idea would be to
use a two dimensional array. Allocating space for that, and
initialising it, runs more smoothly 

(let ((str-array (make-array '(8 8) :initial-element #\-)))
  ...)

> Ok Here's my glorious code that prints out my chess board all pretty
> (decided to force myself to learn LISP by implementing my Chess/AI
> course's project in it - from scratch)....

The thing that leaps out at me is that access to the array
of strings, which is repeated 12 times, could go outside the
COND /expression/.

(setf (aref (aref str-array (- 7 (floor count 8)))
            (- 7 (mod count 8)))
      (cond ((= wpt *PAWN*) #\P)
            ((= wpt *KNIGHT*) #\N)
            ((= wpt *BISHOP*) #\B)
            ((= wpt *ROOK*) #\R)
            ((= wpt *QUEEN*) #\Q)
            ((= wpt *KING*) #\K)
            ((= bpt *PAWN*) #\p)
            ((= bpt *KNIGHT*) #\n)
            ((= bpt *BISHOP*) #\b)
            ((= bpt *ROOK*) #\r)
            ((= bpt *QUEEN*) #\q)
            ((= bpt *KING*) #\k)))
            ;; Since we always do the assignment
            ;; we need otherwise clause least
            ;; we write NIL over #\-
            (t #\-))) 

It would be more idiomatic to put the translation into an
association list

(defparameter *piece-letters*
  '((*pawn* . #\p)
    (*knight* . #\n)
    (*bishop* . #\b)
    (*rook* . #\r)
    (*queen* . #\q)
    (*king* . #\k)))

and tidy away any access issues in a function

(defun find-letter (code-number case-function)
  (let ((letter (assoc code-number
                       *piece-letters*
                       :test #'=
                       :key #'symbol-value)))
    (if letter 
        (funcall case-function (cdr letter))
        nil)))

so that the core code that does the real work reads nicely

(setf (aref (aref str-array (- 7 (floor count 8)))
            (- 7 (mod count 8)))
      (or (find-letter wpt #'char-upcase)
          (find-letter bpt #'char-downcase)
          #\-)

instead of

>     (cond ((= wpt *PAWN*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\P))
>           ((= wpt *KNIGHT*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\N))
>           ((= wpt *BISHOP*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\B))
>           ((= wpt *ROOK*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\R))
>           ((= wpt *QUEEN*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\Q))
>           ((= wpt *KING*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\K))
>           ((= bpt *PAWN*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\p))
>           ((= bpt *KNIGHT*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\n))
>           ((= bpt *BISHOP*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\b))
>           ((= bpt *ROOK*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\r))
>           ((= bpt *QUEEN*) (setf (aref (aref  str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\q))
>           ((= bpt *KING*) (setf (aref (aref str-array (- 7 (floor
> count 8))) (- 7 (mod count 8))) #\k))))

Alan Crowe
Edinburgh
Scotland