home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 10 / lspext.lst < prev    next >
Lisp/Scheme  |  1988-10-31  |  5KB  |  250 lines

  1. _ADDING EXTENSIONS TO LISP_
  2. by
  3. Jonathan Amsterdam
  4.  
  5. Listing 1.
  6.  
  7. (defmacro for (var-from-to &rest body)
  8.   (let ((var (first var-from-to))
  9.     (from (second var-from-to))
  10.     (to (third var-from-to)))
  11.     `(prog (,var)
  12.        (setq ,var ,from)
  13.      loop
  14.        (cond ((> ,var ,to) (go end)))
  15.        ,@body
  16.        (setq ,var (+ ,var 1))
  17.        (go loop)
  18.      end)))
  19.  
  20. ----------------------------------------------------------------
  21. Listing 2.
  22.  
  23. (defmacro for (var-from-to &rest body)
  24.   (let ((var (first var-from-to))
  25.     (from (second var-from-to))
  26.     (to (third var-from-to)))
  27.     (cond
  28.      ((and (numberp from) (numberp to) (< (- to from) 2))
  29.       ;; If from and to are both numbers, and they differ by at most 1...
  30.       (cond ((< (- to from) 0)
  31.          ;; they differ by < 0, hence there's no loop to generate
  32.          nil)
  33.         ((= (- to from) 0)
  34.          ;; they're the same, so just a single iteration
  35.          `(let ((,var ,from))
  36.         ,@body))
  37.         (t 
  38.          ;; else, they differ by one: so two iterations
  39.          `(let ((,var ,from))
  40.         ,@body
  41.         (setq ,var ,to)
  42.         ,@body))))
  43.      (t ;; the general case
  44.       `(prog (,var)
  45.          (setq ,var ,from)
  46.        loop
  47.          (cond ((> ,var ,to) (go end)))
  48.          ,@body
  49.          (setq ,var (+ ,var 1))
  50.          (go loop)
  51.        end)))))
  52.  
  53. ----------------------------------------------------------------
  54. Listing 3.
  55.  
  56. (defmacro for (clause &rest body)
  57.   (let* ((code (funcall (get (second clause) 'for-expander) 
  58.             (first clause) (cddr clause)))
  59.      (init (first code))
  60.      (test (second code))
  61.      (update (third code)))
  62.     `(prog ()
  63.        ,@init
  64.      loop
  65.        (cond (,test (go end)))
  66.        ,@body
  67.        ,@update
  68.        (go loop)
  69.      end)))
  70.  
  71. ----------------------------------------------------------------
  72. Listing 4.
  73.  
  74. (defmacro for (&rest forms)
  75.   (let* ((do-part (member 'do forms))
  76.      (body (cdr do-part))
  77.      (clauses (ldiff forms do-part)) ;clauses = everything before "do"
  78.      (init nil)
  79.      (test nil)
  80.      (update nil))
  81.     (dolist (clause clauses)
  82.       (let ((code (funcall (get (second clause) 'for-expander)
  83.                (first clause) (cddr clause))))
  84.     (setq init (append init (first code)))
  85.     (push (second code) test)
  86.     (setq update (append update (third code)))))
  87.     (setq test (cons 'or (nreverse test)))
  88.     `(prog ()
  89.        ,@init
  90.      loop
  91.        (cond (,test (go end)))
  92.        ,@body
  93.        ,@update
  94.        (go loop)
  95.      end)))
  96.  
  97.  
  98. ----------------------------------------------------------------
  99. Listing 5.
  100.  
  101. (defmacro defrecord (name &rest components)
  102.     `(progn
  103.        ,@(accessor-macro-defs name components)
  104.        (defun ,(symbol-append 'make- name) ,components
  105.      (let ((new-record (make-array ,(length components))))
  106.        ,@(component-setting-list name components)
  107.        new-record))))
  108.        
  109. (defun component-setting-list (name components)
  110.   (let ((set-list nil))
  111.     (for (comp in components)
  112.      do
  113.      (push `(setf (,(accessor-name name comp) new-record) ,comp)
  114.            set-list))
  115.     set-list))
  116.  
  117. (defun accessor-macro-defs (name components)
  118.   (let ((def-list nil))
  119.     (for (i from 0 to (- (length components) 1))
  120.      do
  121.      (push `(defmacro ,(accessor-name name (nth i components)) (x) 
  122.           (list 'aref x ,i))
  123.            def-list))
  124.     def-list))
  125.  
  126. (defun symbol-append (&rest symbols)
  127.   (intern (apply #'string-append symbols)))
  128.  
  129. (defun accessor-name (rec-name comp-name)
  130.   (symbol-append rec-name '- comp-name))
  131.  
  132.  
  133. Example 1.
  134.  
  135. (prog (i) 
  136.       (setq i 1) 
  137.     loop 
  138.       (cond ((> i 10) (go end))) 
  139.       (print i) 
  140.       (setq i (+ i 1)) 
  141.       (go loop) 
  142.     end)
  143.  
  144.  
  145. Example 2.
  146.  
  147. (setq i 1)
  148. (while (<= i 10)
  149.   (print i)
  150.   (setq i (+ i 1)))
  151.  
  152.  
  153. Example 3.
  154.  
  155. (defmacro while (test &rest body)
  156.   `(prog ()
  157.        loop
  158.      (cond ((not ,test) (go end)))
  159.      ,@body
  160.          (go loop)
  161.        end))
  162.  
  163.  
  164. Example 4.
  165.  
  166. (prog ()
  167.     loop
  168.       (cond ((not (>= i 10)) (go end)))
  169.       (print i)
  170.       (setq i (+ i 1))
  171.       (go loop)
  172.     end)
  173.  
  174.  
  175. Example 5.
  176.  
  177. (for (i 1 10)
  178.   (print i))
  179.  
  180.  
  181. Example 6.
  182.  
  183.  
  184. (defmacro setf (form value) 
  185.   (setq form (macroexpand form)) 
  186.   (cond 
  187.    ((symbolp form) 
  188.     `(setq ,form ,value)) 
  189.    (t 
  190.     (funcall (get (car form) 'setf-method) form value)))) 
  191.  
  192.  
  193. Example 7.
  194.  
  195. (defun car-setf-method (form value) 
  196.   `(rplaca ,(second form) ,value))
  197.  
  198.  
  199. Example 8. 
  200.  
  201. (defun aref-setf-method (form value) 
  202.   (let ((array (second form)) 
  203.     (indices (cddr form))) 
  204.     `(aset ,array ,value ,@indices)))
  205.  
  206.  
  207.  
  208.  
  209. Example 9.
  210.  
  211. (defun num-expander (var from-to) 
  212.   (let ((from (first from-to)) 
  213.     (to (third from-to))) 
  214.     (list `((setq ,var ,from))          ; initialization 
  215.       (if to 
  216.           `(> ,var ,to))            ; test 
  217.       `((setq ,var (1+ ,var))))))   ; update 
  218.  
  219.  
  220. Example 10.
  221.  
  222. (defun list-el-expander (var list) 
  223.   (setq list (car list)) 
  224.   (let ((sublis-var (gensym))) 
  225.     (list `((setq ,sublis-var ,list) 
  226.         (setq ,var (car ,sublis-var))) ;initialization 
  227.       `(null ,sublis-var)              ;test 
  228.       `((setq ,sublis-var (cdr ,sublis-var)) 
  229.         (setq ,var (car ,sublis-var)))))) ;update 
  230.  
  231.  
  232.  
  233. Example 11.  
  234.  
  235. (for (i from 0 to (- (length list) 1)) 
  236.      (setf (aref array i) (nth i list))) 
  237.  
  238.  
  239.  
  240. Example 12.
  241.  
  242. (for (el in list) 
  243.      (i from 0) 
  244.    do (setf (aref array i) el)) 
  245.  
  246.  
  247.  
  248. END OF FILE
  249.  
  250.