为什么我的列表会继续在lisp中重置?

时间:2018-04-09 19:07:08

标签: lisp common-lisp

我有一项练习,要求我为酒店写一个程序。

一切都很好,但我的客人名单不断重置。

我没有实现其他2个选项,所以这里是我的所有代码

我用四个分号标记了这个问题。

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

有人可以向我解释这个问题吗? 我该如何解决? 谢谢!

1 个答案:

答案 0 :(得分:2)

hotel中,将( setq _guests '() ) 移到 (loop ...上方。

现在,您正在循环的每次迭代中重新初始化_guests变量。

如果您在代码中使用 saner 更接受的行间距样式,则会更容易看到,如下所示:

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

当然,每个paren周围的额外间距也不寻常,但这不是问题。您使用的双行间距确实使您的代码无法读取。