Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is happening with this Common Lisp code?

I've written the following bit of code to simulate rolling a six-sided die a number of times and counting how many times each side landed up:

(defun dice (num)
  (let ((myList '(0 0 0 0 0 0)))
    (progn (format t "~a" myList)
           (loop for i from 1 to num do
                 (let ((myRand (random 6)))
                   (setf (nth myRand myList) (+ 1 (nth myRand myList)))))
           (format t "~a" myList))))

The function works great the first time I call it, but on subsequent calls the variable myList starts out at the value it had at the end of the last call, instead of being initialized back to all zeros like I thought should happen with the let statement. Why does this happen?

like image 763
Dustin Avatar asked Sep 01 '11 20:09

Dustin


People also ask

Is Common Lisp still used?

While it isn't as popular as C, Python or Perl, Lisp is still used for AI programming as well as several other functions. Lisp continues to be popular in higher education, as students learn Lisp programming tactics and extend this knowledge to the private sector after graduation.

Why did the Lisp Machine fail?

The reason Lisp failed was because it fragmented, and it fragmented because that was the nature of the language and its domain-specific solution style. The network effect worked in reverse.

Is lisp a dead language?

One of the old languages, LISP, has lost its fame and started its journey to death. The language is being rarely used by developers these days. LISP is a language of fully parenthesised prefix notation and is the second oldest high-level programming language, developed in 1960.

Is Common Lisp used in industry?

Common Lisp is not used in industry (or rather, Common Lisp is never seen in the advertisements for employment). The university should teach programming languages that are actually used, so that students have useful knowledge when they graduate.


2 Answers

This is a result of using a constant list in the initializer:

(let ((myList '(0 0 0 0 0 0)))

Change that line to:

(let ((myList (list 0 0 0 0 0 0)))

and it will behave as you expect. The first line only results in an allocation once (since it's a constant list), but by calling list you force the allocation to occur every time the function is entered.

edit: This may be helpful, especially towards the end. Successful Lisp

The answer to this question may also be helpful.

This uses the loop keyword collecting which collects the results of each iteration into a list and returns the list as the value of the loop.

like image 86
asm Avatar answered Oct 21 '22 14:10

asm


SBCL tells you what's wrong:

* (defun dice (num)
  (let ((myList '(0 0 0 0 0 0)))
    (progn (format t "~a" myList)
           (loop for i from 1 to num do
                 (let ((myRand (random 6)))
                   (setf (nth myRand myList) (+ 1 (nth myRand myList)))))
           (format t "~a" myList))))
; in: DEFUN DICE
;     (SETF (NTH MYRAND MYLIST) (+ 1 (NTH MYRAND MYLIST)))
; ==>
;   (SB-KERNEL:%SETNTH MYRAND MYLIST (+ 1 (NTH MYRAND MYLIST)))
; 
; caught WARNING:
;   Destructive function SB-KERNEL:%SETNTH called on constant data.
;   See also:
;     The ANSI Standard, Special Operator QUOTE
;     The ANSI Standard, Section 3.2.2.3
; 
; compilation unit finished
;   caught 1 WARNING condition

DICE

So in essence: Don't call destructive functions (here setf) on constant data.

like image 34
Michael Markert Avatar answered Oct 21 '22 14:10

Michael Markert