jakHunter
jakHunter

Reputation: 315

Why does my list keep resetting itself in lisp?

I have an exercise that requires me to write a program for a hotel.

Everything is good but my guest list keeps resetting itself.

I have not implemented the other 2 options so here is all of my code

I've marked the problem with four semicolons.

(defun guest (_name _nbrguest _phone _duration _price _discount)
  (setf (get _name 'nbrguest) _nbrguest) 
  (setf (get _name 'phone) _phone) 
  (setf (get _name 'duration) _duration) 
  (setf (get _name 'price) _price) 
  (setf (get _name 'discount) _discount)
  (setf (get _name 'final_price) (- _price (discount _price _discount)))
  (return-from guest _name))

(defun discount (original discounter)
  (setq result (* (* original 1.0) (/ (* discounter 1.0) 100.0)))
  (if (<= discounter 0) 
      (setq result original))
  (return-from discount result))

(defun input_person ()
  (format t "name: ")
  (setq name (read))
  (format t "Guest number: ")
  (setq nbrguest (read))
  (format t "Guest phone number: ")
  (setq phone (read))
  (format t "Stay duration: ")
  (setq duration (read))
  (format t "Room price: ")
  (setq price (read))
  (format t "Discount: ")
  (setq discount (read))
  (return-from input_person
               (guest name nbrguest phone duration price discount)))

(defun hotel ()
  (loop 
   (format t "1. Add guest~%")
   (format t "2. Output guests~%")
   (format t "3. Output guests who have paid more than input~%")
   (format t "4. Remove guest~%")
   (format t "5. Exit~%")
   (format t "~%Enter choice: ")
   (setq choice (read))
   (setq _guests '())
   (cond
     ((eq choice 5)
      (return))
     ;;;; this part doesn't work as desired
     ((eq choice 1)
      (if (null _guests)
          (setq _guests (cons (input_person) _guests))
          (setq _guests (append _guests (input_person)))))
     ;;;;
     ((eq choice 2)
      (dolist (n _guests)
              (princ n))))))

Can someone please explain the problem to me? And how do I fix it? Thank you!

Upvotes: 0

Views: 146

Answers (1)

Will Ness
Will Ness

Reputation: 71119

In hotel, move ( setq _guests '() ) above (loop ....

Right now you're re-initializing your _guests variable on each iteration of the loop.

You'd see it much easier if you were using a saner more accepted line spacing style in your code, like this:

( defun guest ( _name _nbrguest _phone _duration _price _discount )

           ( setf ( get _name 'nbrguest ) _nbrguest ) 
           ( setf ( get _name 'phone ) _phone ) 
           ( setf ( get _name 'duration ) _duration ) 
           ( setf ( get _name 'price ) _price ) 
           ( setf ( get _name 'discount ) _discount )
           ( setf ( get _name 'final_price ) 
                  ( - _price ( discount _price _discount ) ) )
           ( return-from guest _name ) )

( defun discount ( original discounter )

           ( setq result ( * ( * original 1.0 ) 
                             ( / ( * discounter 1.0 ) 100.0 ) ) )
           ( if ( <= discounter 0 ) 
                (  setq result original  ) )
           ( return-from discount result ) )

 ( defun input_person ( )
            ( format t "name: " )
            ( setq name ( read ) )
            ( format t "Guest number: " )
            ( setq nbrguest ( read ) )
            ( format t "Guest phone number: " )
            ( setq phone ( read ) )
            ( format t "Stay duration: " )
            ( setq duration ( read ) )
            ( format t "Room price: " )
            ( setq price ( read ) )
            ( format t "Discount: " )
            ( setq discount ( read ) )
            ( return-from input_person 
              ( guest name nbrguest phone duration price discount ) ) )

( defun hotel ( )
          ( loop 
            ( format t "1. Add guest~%" )
            ( format t "2. Output guests~%" )
            ( format t "3. Output guests who have paid more than input~%" )
            ( format t "4. Remove guest~%" )
            ( format t "5. Exit~%" )
            ( format t "~%Enter choice: " )
            ( setq choice ( read ) )
            ( setq _guests '() )

            ( cond
              ( ( eq choice 5 ) ( return ) )
                  ;;;; this part doesn't work as desired
              ( ( eq choice 1 ) 
                ( if ( null _guests ) 
                   ( setq _guests ( cons ( input_person ) _guests ) )  
                   ( setq _guests ( append _guests ( input_person ) ) ) ) )
                  ;;;;
              ( ( eq choice 2 ) 
                ( dolist ( n _guests )
                  ( princ n ) ) ) ) ) )

Of course the extra spacing around each paren is also unusual, but it's less of a problem. The double line spacing you were using really made your code unreadable.

Upvotes: 2

Related Questions