home *** CD-ROM | disk | FTP | other *** search
- _ADDING EXTENSIONS TO LISP_
- by
- Jonathan Amsterdam
-
- Listing 1.
-
- (defmacro for (var-from-to &rest body)
- (let ((var (first var-from-to))
- (from (second var-from-to))
- (to (third var-from-to)))
- `(prog (,var)
- (setq ,var ,from)
- loop
- (cond ((> ,var ,to) (go end)))
- ,@body
- (setq ,var (+ ,var 1))
- (go loop)
- end)))
-
- ----------------------------------------------------------------
- Listing 2.
-
- (defmacro for (var-from-to &rest body)
- (let ((var (first var-from-to))
- (from (second var-from-to))
- (to (third var-from-to)))
- (cond
- ((and (numberp from) (numberp to) (< (- to from) 2))
- ;; If from and to are both numbers, and they differ by at most 1...
- (cond ((< (- to from) 0)
- ;; they differ by < 0, hence there's no loop to generate
- nil)
- ((= (- to from) 0)
- ;; they're the same, so just a single iteration
- `(let ((,var ,from))
- ,@body))
- (t
- ;; else, they differ by one: so two iterations
- `(let ((,var ,from))
- ,@body
- (setq ,var ,to)
- ,@body))))
- (t ;; the general case
- `(prog (,var)
- (setq ,var ,from)
- loop
- (cond ((> ,var ,to) (go end)))
- ,@body
- (setq ,var (+ ,var 1))
- (go loop)
- end)))))
-
- ----------------------------------------------------------------
- Listing 3.
-
- (defmacro for (clause &rest body)
- (let* ((code (funcall (get (second clause) 'for-expander)
- (first clause) (cddr clause)))
- (init (first code))
- (test (second code))
- (update (third code)))
- `(prog ()
- ,@init
- loop
- (cond (,test (go end)))
- ,@body
- ,@update
- (go loop)
- end)))
-
- ----------------------------------------------------------------
- Listing 4.
-
- (defmacro for (&rest forms)
- (let* ((do-part (member 'do forms))
- (body (cdr do-part))
- (clauses (ldiff forms do-part)) ;clauses = everything before "do"
- (init nil)
- (test nil)
- (update nil))
- (dolist (clause clauses)
- (let ((code (funcall (get (second clause) 'for-expander)
- (first clause) (cddr clause))))
- (setq init (append init (first code)))
- (push (second code) test)
- (setq update (append update (third code)))))
- (setq test (cons 'or (nreverse test)))
- `(prog ()
- ,@init
- loop
- (cond (,test (go end)))
- ,@body
- ,@update
- (go loop)
- end)))
-
-
- ----------------------------------------------------------------
- Listing 5.
-
- (defmacro defrecord (name &rest components)
- `(progn
- ,@(accessor-macro-defs name components)
- (defun ,(symbol-append 'make- name) ,components
- (let ((new-record (make-array ,(length components))))
- ,@(component-setting-list name components)
- new-record))))
-
- (defun component-setting-list (name components)
- (let ((set-list nil))
- (for (comp in components)
- do
- (push `(setf (,(accessor-name name comp) new-record) ,comp)
- set-list))
- set-list))
-
- (defun accessor-macro-defs (name components)
- (let ((def-list nil))
- (for (i from 0 to (- (length components) 1))
- do
- (push `(defmacro ,(accessor-name name (nth i components)) (x)
- (list 'aref x ,i))
- def-list))
- def-list))
-
- (defun symbol-append (&rest symbols)
- (intern (apply #'string-append symbols)))
-
- (defun accessor-name (rec-name comp-name)
- (symbol-append rec-name '- comp-name))
-
-
- Example 1.
-
- (prog (i)
- (setq i 1)
- loop
- (cond ((> i 10) (go end)))
- (print i)
- (setq i (+ i 1))
- (go loop)
- end)
-
-
- Example 2.
-
- (setq i 1)
- (while (<= i 10)
- (print i)
- (setq i (+ i 1)))
-
-
- Example 3.
-
- (defmacro while (test &rest body)
- `(prog ()
- loop
- (cond ((not ,test) (go end)))
- ,@body
- (go loop)
- end))
-
-
- Example 4.
-
- (prog ()
- loop
- (cond ((not (>= i 10)) (go end)))
- (print i)
- (setq i (+ i 1))
- (go loop)
- end)
-
-
- Example 5.
-
- (for (i 1 10)
- (print i))
-
-
- Example 6.
-
-
- (defmacro setf (form value)
- (setq form (macroexpand form))
- (cond
- ((symbolp form)
- `(setq ,form ,value))
- (t
- (funcall (get (car form) 'setf-method) form value))))
-
-
- Example 7.
-
- (defun car-setf-method (form value)
- `(rplaca ,(second form) ,value))
-
-
- Example 8.
-
- (defun aref-setf-method (form value)
- (let ((array (second form))
- (indices (cddr form)))
- `(aset ,array ,value ,@indices)))
-
-
-
-
- Example 9.
-
- (defun num-expander (var from-to)
- (let ((from (first from-to))
- (to (third from-to)))
- (list `((setq ,var ,from)) ; initialization
- (if to
- `(> ,var ,to)) ; test
- `((setq ,var (1+ ,var)))))) ; update
-
-
- Example 10.
-
- (defun list-el-expander (var list)
- (setq list (car list))
- (let ((sublis-var (gensym)))
- (list `((setq ,sublis-var ,list)
- (setq ,var (car ,sublis-var))) ;initialization
- `(null ,sublis-var) ;test
- `((setq ,sublis-var (cdr ,sublis-var))
- (setq ,var (car ,sublis-var)))))) ;update
-
-
-
- Example 11.
-
- (for (i from 0 to (- (length list) 1))
- (setf (aref array i) (nth i list)))
-
-
-
- Example 12.
-
- (for (el in list)
- (i from 0)
- do (setf (aref array i) el))
-
-
-
- END OF FILE
-
-