gisshow 发表于 2008-7-17 20:30:00

[求助]子函数能否调用自身来进行循环?

<p>[求助]子函数能否调用自身来进行循环?</p><p>&nbsp;</p>

Andyhon 发表于 2008-7-17 21:30:00


前辈的一些讨论
Ref: http://autocad.xarch.at/stdlib/archive/10/msg00054.html

;;; by Randy Richardson
(defun subst1 (index new lst / counter lst1)
(setq counter 0)
(repeat index
    (setq lst1 (cons (nth counter lst) lst1))
    (setq counter (1+ counter))
)
(setq lst1 (cons new lst1))
(setq counter (1+ counter))
(repeat (- (length lst) (length lst1))
    (setq lst1 (cons (nth counter lst) lst1))
    (setq counter (1+ counter))
)
(reverse lst1)
)
;;; by Frank Oquendo
(defun replace-element (index newelement lst / tmp)
(repeat index
    (setq tmp (cons (car lst) tmp)
   lst (cdr lst)
    )
)
(append (reverse tmp) (list newelement) (cdr lst))
)

;;; by Tony Tanzillo
(defun SetNth (index newitem lst / i)
   (setq i -1)
   (mapcar
   '(lambda (elem)
         (if (eq index (setq i (1+ i)))
            newitem
            elem
         )
      )
      lst
   )
)
There's a number of posts here offering solutions, but
if you need to perform multiple replacements of elements
in the same list, by position, then none of the solutions
you've seen so far, including the one Reini posts a link
to (with a password), are very effective.
If you have to do many replacements, you should
index your list, by cons'ing each element with a
unique integer value. This allows you to use (SUBST)
to quickly replace elements:
(defun index-list (lst / i)
   (setq i -1)
   (mapcar '(lambda (elem) (cons (setq i (1+ i)) elem)) lst)
)
Given the list (A B C D E F), the above function
returns the list:
    ((0 . A) (1 . B) (2 . C) (3 . D) ...)
With this resulting list, you can now use (subst)
to replace only one element by position. This is
much more effecient if you have many replacements
to perform on the same list.
To replace an element at a given position:
   (setq indexed-list
      (subst (cons <index> <newvalue>)
             (nth <index> indexed-list)
             indexed-list
      )
   )
You can still quickly reference elements in the list
by position, using (cdr (nth <index> <indexed-list>))
Or, once you're finished replacing elements, you can
just do (mapcar 'cdr <indexed-list>) to remove the
indexing.
;;; by Tony Tanzillo ===============================

;;; by Reini Urban
(defun std-%setnth (new i lst / fst len)
(cond
    ((minusp i) lst)
    ((> i (setq len (length lst))) lst)
    ((> i (/ len 2))
      (reverse (std-%setnth new (1- (- len i)) (reverse lst))))
    (T
      (append
      (progn
          (setq fst nil)      ; ; possible VL lsa compiler bug
          (repeat (rem i 4)
            (setq fst (cons (car lst) fst)
                  lst (cdr lst)))
          (repeat (/ i 4)
            (setq fst (cons (cadddr lst)
                            (cons (caddr lst)
                                  (cons (cadr lst)
                                        (cons (car lst) fst))))
                  lst (cddddr lst)))
          (reverse fst)
      )
      (if (listp new) new (list new)) ; v0.4001
      (cdr lst)))))
;|
;;; old slower versions:
(defun STD-RPLACE (lst i new)
(if (< -1 i (length lst))   ; fixed v0.3003
    (append (std-firstn i lst)
            (list new)
            (std-nthcdr (1+ i) lst))
    lst))
|;

;;; by Marc'Antonio Alessi
;;; newitem /= nil
(defun ALE_SUBST_NTH (index newitem lst / len r_lst olditem )
(if (and newitem (> (setq len (- (length lst) (1+ index))) -1))
    (progn
      (setq
      r_lst   (reverse lst)
      olditem (nth index lst)
      )
      (while (/= index (length (setq r_lst (cdr (member olditem r_lst))))))
      (while (/= len   (length (setq lst   (cdr (member olditem   lst))))))
      (append (reverse r_lst)(list newitem) lst)
    )
    lst
)
)

ZZXXQQ 发表于 2008-7-17 21:49:00

函数自身调用就是“递归”。只要有限次的“递归”(确保堆栈不溢出),且函数结束条件设定合理就行。
页: [1]
查看完整版本: [求助]子函数能否调用自身来进行循环?