From 4e544af6fc4e4036192d9b4eb506353d190520bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Renaud=20Casenave-P=C3=A9r=C3=A9?= Date: Fri, 19 Sep 2014 17:17:25 +0900 Subject: [PATCH] Add two of On Lisp's utility functions: group and once-only --- src/utils.lisp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/utils.lisp b/src/utils.lisp index e91dbd5..b099352 100644 --- a/src/utils.lisp +++ b/src/utils.lisp @@ -10,6 +10,7 @@ (:export :it :aif :awhen + :group :once-only :restartable :add-hook :remove-hook :run-hook :update-current-time :get-delta-time @@ -32,6 +33,25 @@ (when it ,@body))) +(defun group (source n) + "Regroup the list `source' elements by n." + (when (zerop n) + (error "zero length")) + (labels ((rec (source acc) + (let ((rest (nthcdr n source))) + (if (consp rest) + (rec rest (cons (subseq source 0 n) acc)) + (nreverse (cons source acc)))))) + (if source (rec source nil) nil))) + +(defmacro once-only ((&rest names) &body body) + "Evaluate the symbols in `names' only once, for use in a macro, as per Peter Siebel's Practical Common-Lisp." + (let ((gensyms (loop for n in names collect (gensym)))) + `(let (,@(loop for g in gensyms collect `(,g (gensym)))) + `(let (,,@(loop for g in gensyms for n in names collect ``(,,g ,,n))) + ,(let (,@(loop for n in names for g in gensyms collect `(,n ,g))) + ,@body))))) + (defmacro restartable (unprotected &body body) "Provide a Continue restart unless `unprotected' is t." `(if ,unprotected