やりたいことを正確に行う方法はないかもしれませんが、似たようなことをハックする方法がいくつかあります。1 つのオプションは、関数を呼び出し可能なオブジェクトにローカルにバインドできるようにする新しいバインディング フォーム with-callable を定義することです。たとえば、
(with-callable ((x (make-array ...)))
(x ...))
にほぼ等しい
(let ((x (make-array ...)))
(aref x ...))
with-callable の可能な定義は次のとおりです。
(defmacro with-callable (bindings &body body)
"For each binding that contains a name and an expression, bind the
name to a local function which will be a callable form of the
value of the expression."
(let ((gensyms (loop for b in bindings collect (gensym))))
`(let ,(loop for (var val) in bindings
for g in gensyms
collect `(,g (make-callable ,val)))
(flet ,(loop for (var val) in bindings
for g in gensyms
collect `(,var (&rest args) (apply ,g args)))
,@body))))
あとは、オブジェクトにアクセスするためのクロージャーを返す make-callable のさまざまなメソッドを定義するだけです。たとえば、配列に対してそれを定義するメソッドは次のとおりです。
(defmethod make-callable ((obj array))
"Make an array callable."
(lambda (&rest indices)
(apply #'aref obj indices)))
この構文は見栄えが悪いので、マクロを使用してよりきれいにすることができます。
(defmacro defcallable (type args &body body)
"Define how a callable form of TYPE should get access into it."
`(defmethod make-callable ((,(car args) ,type))
,(format nil "Make a ~A callable." type)
(lambda ,(cdr args) ,@body)))
配列を呼び出し可能にするには、次を使用します。
(defcallable array (obj &rest indicies)
(apply #'aref obj indicies))
ずっといい。これで、オブジェクトへのアクセスを可能にするローカル関数を定義するフォーム with-callable と、他の型の呼び出し可能なバージョンを作成する方法を定義できるマクロ defcallable ができました。この戦略の欠点の 1 つは、オブジェクトを callable にするたびに with-callable を明示的に使用する必要があることです。
呼び出し可能なオブジェクトに似た別のオプションは、ssyntaxにアクセスする Arc の構造です。基本的に x.5 は、x のインデックス 5 の要素にアクセスします。Common Lisp でこれを実装することができました。私が書いたコードはこことここで見ることができます。私はそれのテストも持っているので、ここでそれがどのように見えるかを見ることができます.
私の実装がどのように機能するかは、本体内のすべてのシンボルを調べ、それらの一部に対してマクロとシンボルマクロを定義するマクロ w/ssyntax を作成したことです。たとえば、x.5 のシンボル マクロは (get x 5) になります。ここで、get は構造体にアクセスするために定義した汎用関数です。これの欠点は、ssyntax を使用したい場合は常に w/ssyntax を使用する必要があることです。幸いなことに、defun のように機能するマクロ def 内にそれを隠すことができます。