読者です 読者をやめる 読者になる 読者になる

可変配列 - 微修正

common lisp read macro

可変配列マクロ(?)の最新版。
index部分もS式で指定可能に。ex. @array#(+ 1 1)
エラーチェックとかが適当なのは、以前のものと同様。
@array#(incf i)などのように式は、(incf i)が二度評価されてしまうので注意が必要

(defmacro assure-access (vector index)
  `(locally
    (declare ,@(if (symbolp index)  `((fixnum ,index)))
	     ,@(if (symbolp vector) `((vector ,vector)))
	     (optimize (safety 0)))
    (when (>= ,index (length ,vector))
       (setf ,vector (adjust-array ,vector (* ,index 2))))
    ,vector))

(flet ((split (str stream)
         (dotimes (i (length str))
	   (case (char str i)
	     ((#\? #\#)
	      (return-from split
	        (values (read-from-string (subseq str 0 i))
			(char str i)
                        ;; ↓ここが以前と違う
			(if (< i (1- (length str)))
			    (read-from-string (subseq str (1+ i)))
			  (read stream)))))))))

  (set-macro-character #\@
    (lambda (stream c)
      (declare (ignore c))
      (let ((exp (read stream)))
	(multiple-value-bind (array delim index) 
			     (if (symbolp exp)
				 (split (symbol-name exp) stream)
			       (values exp (read-char stream) (read stream)))
	  (if (char= delim #\?)
	      `(aref (assure-access ,array ,index) ,index)
	    `(aref ,array ,index)))))))