Returns NIL 的 LISP 循环

LISP Loop For Returns NIL

我有这个小程序可以根据输入是正数还是负数来向前或向后打印三角形。它工作得很好,除了在每个循环结束时它打印 NIL。我试着改变循环的边界,但每次我这样做都会影响三角形的大小。有什么解决办法吗?请在下面找到代码。

(defun triangle(k) 
    (cond ((or(not(integerp k)) (= k 0)) '("invalid number; please enter a positive or a negative integer"))
          ((< k -1) 
             (loop for x from k to -1 do
                 (loop for y from k to -1 do 
                       (if (< y x) 
                           (princ #\Space)
                           (princ '*) 
                       ) 
                     
                  ) 
                (terpri)
              )
          )  
        
         ((or (= k 1) (= k -1)) '*) 
         (t(loop  for x from 0 to k do 
               (loop for y from 0 to k do  
                 (if (< x y)    
                     (princ '*) 
                 )
                ) 
                (terpri)
           ) 
         ) 
    ) 
)
(defun triangle (k) 
  (cond ((or (not (integerp k))
             (= k 0))
         '("invalid number; please enter a positive or a negative integer"))
        ((< k -1) 
         (loop for x from k to -1 do
               (loop for y from k to -1 do 
                     (if (< y x) 
                         (princ #\Space)
                       (princ '*))) 
                (terpri)))
        ((or (= k 1) (= k -1))
         '*) 
        (t
         (loop for x from 0 to k do 
               (loop for y from 0 to k do  
                     (if (< x y)    
                         (princ '*))) 
               (terpri))))
  (values))

示例:

CL-USER 8 > (triangle 3)
***
**
*


CL-USER 9 > 

考虑到您的问题是关于循环的,我知道这是题外话,但我建议将数据生成、操作和表示分开,这始终是一个好习惯。您可以制作一个三角形生成器,然后根据需要将其反转。它可能看起来像这样,例如:

(defun mk-tri (n)
  (when (plusp n)
    (loop for i from 1 to n
          collect (nconc (loop repeat i collect #\*)
                         (loop repeat (- n i) collect #\space)))))

(defun print-field (field)
  (format t "~{~{~a~}~%~}" field))

(print-field (mk-tri 5))
;; *    
;; **   
;; ***  
;; **** 
;; *****

(defun invert-v (data)
  (reverse data))

(print-field (invert-v (mk-tri 5)))
;; *****
;; **** 
;; ***  
;; **   
;; *    

(defun invert-h (data)
  (mapcar #'reverse data))

(print-field (invert-h (mk-tri 5)))
;;     *
;;    **
;;   ***
;;  ****
;; *****

这会给您带来全新的自由度,就像您可以想象这个用于图案绘制的小工具包一样:

(defun concat-v (d1 d2)
  (append d1 d2))

(defun concat-h (d1 d2)
  (mapcar #'append d1 d2))

(defun repeat-v (n data)
  (reduce #'concat-v (loop repeat n collect data)))

(defun repeat-h (n data)
  (reduce #'concat-h (loop repeat n collect data)))

(let* ((tri (mk-tri 5))
       (tri2 (concat-v tri (invert-v tri)))
       (rect (concat-h tri2 (invert-h tri2))))
  (print-field (repeat-v 2 (repeat-h 3 rect))))
;; *        **        **        *
;; **      ****      ****      **
;; ***    ******    ******    ***
;; ****  ********  ********  ****
;; ******************************
;; ******************************
;; ****  ********  ********  ****
;; ***    ******    ******    ***
;; **      ****      ****      **
;; *        **        **        *
;; *        **        **        *
;; **      ****      ****      **
;; ***    ******    ******    ***
;; ****  ********  ********  ****
;; ******************************
;; ******************************
;; ****  ********  ********  ****
;; ***    ******    ******    ***
;; **      ****      ****      **
;; *        **        **        *