1

インデックスがリストにある配列にアクセスしたい。この utility と呼びましょうarefl。次のように定義されています。

(arefl array '(x y z ...)) equals (aref array x y z ...) 

私の目標は、任意のサイズの行列で動作するいくつかの汎用関数を作成することです。

私はマクロでそのようなことを実装することに失敗しましたaref. 私が持っている最も近いものは次のとおりです。

(defmacro arefl (array is)
  "Access array by a list of indices"
  `(apply #'aref (cons ,array ,is)))

これは動作し、実際には動作し(setf (arefl array is) value)ますが、コンパイラは、少なくともsbclを再定義していることを知らせる警告をスローしますsetf(私は推測します) apply。警告は次のとおりです。

; in: DEFUN (SETF AREFL**)
;     (SETF (APPLY #'AREF ARRAY (REDUCE 'CONS ARGS :FROM-END T)) NEW-VALUE)
; --> LET* MULTIPLE-VALUE-BIND LET APPLY MULTIPLE-VALUE-CALL 
; ==>
;   #'(SETF AREF)
; 
; caught STYLE-WARNING:
;   defining as a SETF function a name that already has a SETF macro:
;     (SETF AREF)
; 
; compilation unit finished
;   caught 1 STYLE-WARNING condition

--

より良い方法はありますか?私はうまくsetf機能し、別の関数への呼び出しを必要としない実装を探してapplyいます。cons

4

2 に答える 2

2

わかりました、define-setf-expanderこれはやり過ぎです。

(defun arefl (array list)
  (apply #'aref array list))
(defun (setf arefl) (x array list)
  (setf (apply #'aref array list) x))

「APPLY Forms as Places」を参照してください: http://clhs.lisp.se/Body/05_abe.htm

于 2013-10-29T12:58:11.937 に答える
2

最初に、私はあなたが言ったことを認識しますが

私はうまくsetf機能し、別の関数への呼び出しを必要としない実装を探してapplyいます。cons

ただし、ここでは単純に使用でき、の最後の引数のみがリストである必要があるため、ingを行う必要はありませんつまり、次のすべてが同等であることを意味します。apply 'arefconsapply

(aref array 0 1)
(apply 'aref (list array 0 1))
(apply 'aref array (list 0 1))
(apply 'aref array 0 (list 1))
(apply 'aref array 0 1 '())

最も重要なことは、呼び出しを避けたい場合consは、できることを意味します

(apply 'aref array indices)

これも使用できますsetf(ただし#'array、 ではなくを使用する必要があります'array)。

(setf (apply #'aref array indices) new-value)

ここで機能するので、関数と関数applyを作成するだけです( と類似しています):aref*(setf aref*)list*

(defun aref* (array &rest args)
  (apply 'aref array (reduce 'cons args :from-end t)))
             
(defun (setf aref*) (new-value array &rest args)
  (setf (apply #'aref array (reduce 'cons args :from-end t)) new-value))

それらのは、展開可能な引数リスト designators(reduce 'cons args :from-end t)をサポートするために使用されます。このイディオムを使用すると、 で使用できるのとまったく同じ種類の引数を に渡すことができます。これは、あなたが説明したユースケースよりも少し複雑かもしれませんが、どのような種類の引数が必要かを具体的に説明する必要はなく、(のドキュメントのように)簡単に言うことができることを意味します。展開可能な引数リスト指定子であり、引数に適用されます。apply(aref* ...)(apply #'aref ...)aref*applyaref*aref*aref

于 2013-10-29T12:58:22.123 に答える