;;AUTOLOAD: lreverse
;;AUTODOC: lreverse - "reverses a list"
;; (lreverse list [:in-place t])
;;
;; Reverses the elements of the list or vector. Returns a copy without 
;; modifying the original, except if given :in-place t, in which case the 
;; list is modified in place, and returned.
;;
;; Exemple:
;; (setq l [1 2 3 4 5 6 7 8 9 10])
;; (lreverse l)         ==> [10 9 8 7 6 5 4 3 2 1]
;; l                    ==> [1 2 3 4 5 6 7 8 9 10]
;; (lreverse l :in-place t) ==> [10 9 8 7 6 5 4 3 2 1]
;; l                        ==> [10 9 8 7 6 5 4 3 2 1]

(defun lreverse (l &key in-place &aux (len (length l)) (last (- len 1)))
  (if in-place
    (with (elt ())
      (dotimes (i (/ len 2))		;reverse in place
	(setq elt (i l))
	(i l (last l))
	(last l elt)
	(incf last -1)
      )
      l
    )
    (with (res (if (typep l Vector) (vector) (list)))
      (dotimes len
	(lappend res (last l))
	(incf last -1)
      )
      res
    )
  )
)

;;AUTOLOAD: plreverse
;;AUTODOC: plreverse - "reverses a p-list"
;; (plreverse list [:in-place t])
;;
;; Reverses the elements of the p-list or vector. Returns a copy without 
;; modifying the original, except if given :in-place t, in which case the 
;; list is modified in place, and returned.
;;
;; Exemple:
;; (setq l '(a 1 b 2 c 3))
;; (plreverse l)               ==> (c 3 b 2 a 1)
;; l                           ==> (a 1 b 2 c 3)
;; (p(lreverse l :in-place t)  ==> (c 3 b 2 a 1)
;; l                           ==> (c 3 b 2 a 1)

(defun plreverse (l &key in-place &aux 
    (len (/ (length l) 2))
    (last (- (* 2 len) 1))
  )
  (if in-place
    (with (elt () i 0 len2 (/ len 2))
      (dotimes len2		;reverse in place
	(incf last -1)
	(setq elt (i l)) (i l (last l)) (last l elt)
	(incf i) (incf last)
	(setq elt (i l)) (i l (last l)) (last l elt)
	(incf i) (incf last -2)
      )
      l
    )
    (with (res (if (typep l Vector) (vector) (list)))
      (dotimes len
	(lappend res ((- last 1) l))
	(lappend res (last l))
	(incf last -2)
      )
      res
    )
  )
)
