Mercurial > core / lisp/std/macs/loop.lisp
changeset 698: |
96958d3eb5b0 |
parent: |
571685ae64f1
|
author: |
Richard Westhaver <ellis@rwest.io> |
date: |
Fri, 04 Oct 2024 22:04:59 -0400 |
permissions: |
-rw-r--r-- |
description: |
fixes |
1 ;;; loop.lisp --- Loop-like Macros 7 ;; ref: https://github.com/bendudson/array-operations 8 (defmacro nested-loop (syms dimensions &body body) 9 "Iterates over a multidimensional range of indices. 11 SYMS must be a list of symbols, with the first symbol 12 corresponding to the outermost loop. 14 DIMENSIONS will be evaluated, and must be a list of 15 dimension sizes, of the same length as SYMS. 18 (nested-loop (i j) '(10 20) (format t '~a ~a~%' i j))" 19 (unless syms (return-from nested-loop `(progn ,@body))) ; No symbols 20 ;; Generate gensyms for dimension sizes 21 (let* ((rank (length syms)) 22 ;; reverse our symbols list, 23 ;; since we start from the innermost. 24 (syms-rev (reverse syms)) 25 ;; innermost dimension first: 26 (dims-rev (loop for i from 0 below rank 28 ;; start with innermost expression 29 (result `(progn ,@body))) 30 ;; Wrap previous result inside a loop for each dimension 31 (loop for sym in syms-rev for dim in dims-rev do 33 (error "~S is not a symbol. First argument to nested-loop must be a list of symbols" sym)) 35 `(loop for ,sym from 0 below ,dim do 37 ;; Add checking of rank and dimension types, 38 ;; and get dimensions into gensym list. 39 (let ((dims (gensym))) 40 `(let ((,dims ,dimensions)) 41 (unless (= (length ,dims) ,rank) 42 (error "Incorrect number of dimensions: Expected ~a but got ~a" ,rank (length ,dims))) 44 (unless (integerp dim) 45 (error "Dimensions must be integers: ~S" dim))) 46 ;; dimensions reversed so that innermost is last: 47 (destructuring-bind ,(reverse dims-rev) ,dims