1

I am a novice in the field of lisp... i am writing a code to solve the 8 puzzle in bfs...

I want to store the visited lists in a global list and change its value regularly from within a function...

(defparameter *vlist* nil)
(defun bfs-core(node-list)
        (let (cur-node tmp-node-list)
            (if (null node-list)
                NIL
                (progn
                ;       (if (= 1 (length node-list)) 
                    (setq cur-node (car node-list))
                    (setq tmp-node-list (cdr node-list))
                    (if (goalp  cur-node)
                        cur-node
                    ((setq *vlist* (append cur-node *vlist*))
                       (bfs-core (append tmp-node-list (expand cur-node))))))
                    )
                )
            )

The defparameter one is my global variable... and witjin the function i want to change its value with setq... i have also used defvar, setf,set and all possible combinations..... Can anyone help me out????

1
  • Your code already includes an assignment to *vlist* using setq. It's (setq *vlist* (append cur-node *vlist*). It's not clear what you're asking. Your syntax isn't right, though. if should look like (if (goalp cur-node) cur-node (progn (setq ...) (bfs-core ...))). Commented Sep 28, 2013 at 16:03

3 Answers 3

2

Here is your code (reformatted for standard Lisp style):

(defparameter *vlist* nil)
(defun bfs-core (node-list)
  (let (cur-node tmp-node-list)
    (if (null node-list)
        NIL
        (progn
          ;       (if (= 1 (length node-list)) 
          (setq cur-node (car node-list))
          (setq tmp-node-list (cdr node-list))
          (if (goalp  cur-node)
              cur-node
              ((setq *vlist* (append cur-node *vlist*))
               (bfs-core (append tmp-node-list (expand cur-node)))))))))

Your code as one clear problem.

The form ((setq *vlist* ...) (bfs-core ...)) ends up being a function call. When you have a form like (exp1 exp2 exp3) then exp1 is a function applied to parameter values of exp2 and exp3. Your exp1 is (setq *vlist* ...) which doesn't evaluate to a function and, of course, you never wanted it to.

A rewritten version of your code, that at least would remove the misplaced function call, is:

(defparameter *vlist* nil)
(defun bfs-core (node-list)
  (let (cur-node tmp-node-list)
    (if (null node-list)
        NIL
        (progn
          ;       (if (= 1 (length node-list)) 
          (setq cur-node (car node-list))
          (setq tmp-node-list (cdr node-list))
          (if (goalp  cur-node)
              cur-node
              (progn
                (setq *vlist* (append cur-node *vlist*))
                (bfs-core (append tmp-node-list (expand cur-node)))))))))
Sign up to request clarification or add additional context in comments.

Comments

1

You certainly can change global variables from inside functions:

[1]> (defparameter *visited-lists* nil)
*VISITED-LISTS*
[2]> *visited-lists* 
NIL
[3]> (defun change-global-value ()
  (setf *visited-lists* (append (list 'new-value) 
                                *visited-lists* )))
CHANGE-GLOBAL-VALUE
[4]> *visited-lists* 
NIL
[5]> (change-global-value) 
(NEW-VALUE)
[6]> *visited-lists* 
(NEW-VALUE)
[7]> (change-global-value) 
(NEW-VALUE NEW-VALUE)
[8]> *visited-lists* 
(NEW-VALUE NEW-VALUE)

But let's look at your code some more:

(defun bfs-core(node-list)
        (let (cur-node tmp-node-list)
            (if (null node-list)
                NIL
                (progn
                ;       (if (= 1 (length node-list)) 
                    (setq cur-node (car node-list))
                    (setq tmp-node-list (cdr node-list))
                    (if (goalp  cur-node)
                        cur-node
                    ((setq *vlist* (append cur-node *vlist*))
                       (bfs-core (append tmp-node-list (expand cur-node))))))
                    )
                )
            )

First, let's get closing parentheses on the correct lines, and remove the commented-out code. Most Lisp coders don't close their parens like braces in an ALGOL-style language:

(defun bfs-core(node-list)
  (let (cur-node tmp-node-list)
    (if (null node-list)
        NIL
      (progn
        (setq cur-node (car node-list))
        (setq tmp-node-list (cdr node-list))
        (if (goalp  cur-node)
            cur-node
          ((setq *vlist* (append cur-node *vlist*))
           (bfs-core (append tmp-node-list (expand cur-node)))))))))

Now, we have a nil for the first branch of an if. We can change it to unless, which has a built-in progn, so we don't need that either:

(defun bfs-core(node-list)
  (let (cur-node tmp-node-list)
    (unless (null node-list) ;;changed this line to an unless, dropped nil, progn
      (setq cur-node (car node-list))
      (setq tmp-node-list (cdr node-list))
      (if (goalp  cur-node)
          cur-node
        ((setq *vlist* (append cur-node *vlist*))
         (bfs-core (append tmp-node-list (expand cur-node))))))))

We're also using a let to set some variables to nil, and when we get inside the unless, we immediately set the variables to the values we actually want to work with. Let's switch it so that we only create the variables if we're going to use them:

(defun bfs-core(node-list)
  (unless (null node-list) ;;switched this line and the let below
    (let ((cur-node (car node-list)) ;;also set the variables inside the let
          (tmp-node-list) (cdr node-list))
      (if (goalp  cur-node)
          cur-node
        ((setq *vlist* (append cur-node *vlist*))
         (bfs-core (append tmp-node-list (expand cur-node))))))))

Ok, we're already at much cleaner code. Yay!

Let's look at one of the calls here:

((setq *vlist* (append cur-node *vlist*))
 (bfs-core (append tmp-node-list (expand cur-node))))

Did you mean to put this as a single call, and not two? There's a difference between that and this:

((setq *vlist* (append cur-node *vlist*)))
(bfs-core (append tmp-node-list (expand cur-node)))

Do you see the difference? The first is a single statement; the second is two. You probably want the second, as you want to change *vlist*, then call bfs-core. And, to do that, you'll need progn:

(defun bfs-core(node-list)
  (unless (null node-list)
    (let ((cur-node (car node-list))
          (tmp-node-list) (cdr node-list))
      (if (goalp  cur-node)
          cur-node
        (progn (setq *vlist* (append cur-node *vlist*))
               (bfs-core (append tmp-node-list (expand cur-node))))))))

Comments

1

The other answers are specific to the problem at hand. As a general answer on how to change the value of a variable that is passed to a subroutine, it is possible if the variable is passed as a symbol:

(defun modify (x)
  (set x 100))

(setq d 1)         => value of d is 1
(modify 'd)        => value of d is 100

So, to use the terminology of pass by value and pass by reference and apply that to lisp:

(userfunction 'x)  is pass by reference,
(Userfunction x)   is pass by value.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.