From: Madhu on

* Kenneth Tilton <4af59568$0$22536$607ed4bc(a)cv.net> :
Wrote on Sat, 07 Nov 2009 10:42:32 -0500:

| Pascal J. Bourguignon wrote:
|> Kenneth Tilton <kentilton(a)gmail.com> writes:
|>
|>> There's no way to funcall a setter! FUNCTION does not take variables!
|
| Ah, silly me, I looked at fdefinition but didn't Get It.

The point of going through get-setf-expansion is because FDEFINITION is
not guranteed to work on DEFSTRUCT-defined accessors: See
<http://groups.google.com/group/comp.lang.lisp/msg/08ffb56f97156c5c>

--
Madhu
From: Ron Garret on
In article <m3d43ujxy7.fsf(a)moon.robolove.meer.net>,
Madhu <enometh(a)meer.net> wrote:

> * Kenneth Tilton <4af5624a$0$31273$607ed4bc(a)cv.net> :
> Wrote on Sat, 07 Nov 2009 07:04:30 -0500:
>
> | There's no way to funcall a setter! FUNCTION does not take variables!
>
> So create a funcallable from the `setter's' name and funcall it! Here's
> an implementation that even compiles the setter and caches it!
>
> (defvar *setter-cache* (make-hash-table :test #'eq))
>
> (defun find-or-make-setter (accessor-symbol
> &optional (accessor-cache *setter-cache*))
> (check-type accessor-symbol symbol)
> (check-type accessor-cache hash-table)
> (or (gethash accessor-symbol accessor-cache)
> (setf (gethash accessor-symbol accessor-cache)
> (multiple-value-bind
> (vars vals store-vars writer-form reader-form)
> (get-setf-expansion (list accessor-symbol 'object))
> (declare (ignore reader-form))
> ;;(warn "computing ~A." accessor-symbol)
> (let* ((bindings
> (nconc
> (pairlis vars (mapcar 'list vals))
> (pairlis store-vars (list '(new-value)))))
> (form `(lambda (new-value object)
> (let ,bindings ,writer-form))))
> (compile nil form))))))
>
>
> ;; Example Use
> (defstruct foo a)
> (defvar $a (make-foo))
> (funcall (find-or-make-setter 'foo-a) 10 $a) ; => #S(FOO :A 10)
>
> --
> Madhu

Note that this fails for accessors that take more than one argument:

? (find-or-make-setter 'nth)
;Compiler warnings :
; In an anonymous lambda form: In the call to CCL::%SETNTH with
arguments (#:G270 #:G269),
; 2 arguments were provided, but at least 3 are required
; by the current global definition of CCL::%SETNTH
#<Anonymous Function #x300041F5D2DF>
? (funcall * '(1 2 3) 1 2)
> Error: Too many arguments in call to #<Anonymous Function #x300041F5D2DF>:
> 3 arguments provided, at most 2 accepted.

AFAIK, there is no way to fix this in portable CL because there is no
potable way to query a function for its argument list, and so no
portable way to construct a complete accessor form from a naked accessor
function.

rg
From: Madhu on

* Ron Garret <rNOSPAMon-66A018.17493007112009(a)news.albasani.net> :
Wrote on Sat, 07 Nov 2009 17:49:31 -0800:

|
| Note that this fails for accessors that take more than one argument:

The code I exhibited to Ken Tilton was expected to work only for
accessors of one argument. Sorry if I did not make that explicit.


HTH

--
Madhu