Trying to understand setf + isf "magic"

Now I learned about arrays and arefin Lisp. So far, it's pretty easy to understand, and it works like a spell:

(defparameter *foo* (make-array 5))
(aref *foo* 0) ; => nil
(setf (aref *foo* 0) 23)
(aref *foo* 0) ; => 23

I am puzzled by the magic arefthat occurs when you combine arefand setf. It seems that he arefknew about his calling context and then decided whether to return a value or a place that could be used setf.

In any case, at the moment I just perceive it as satisfied and do not think about how it works too much inside.

But now I wanted to create a function that sets the element of the array *foo*to a predetermined value, but I do not want to set the array hard *foo*, instead I want to pass the place:

(defun set-23 (place)
  …)

So basically this function sets the value to 23, regardless of location. My initial naive approach was

(defun set-23 (place)
  (setf place 23))

and call it using:

(set-23 (aref *foo* 0))

This does not lead to an error, but also does not change *foo*. I assume the call arefresolves nil(since the array is currently empty), so this would mean that

(setf nil 23)

is executed, but when I try to do this manually in the REPL, I get an error message:

NIL is a constant, cannot be used as a variable

(And this is absolutely reasonable!)

So finally, I have two questions:

  • What happens in my example and that it does not cause an error and why does it not do anything?
  • How can I solve this problem so that my function set-23works?

thunk , aref, , :

(defun set-23 (fn)
  (setf (funcall fn) 23))

, , Lisp :

(SETF FUNCALL) #.

, , . setf funcall, -, , lambdas, ?

PS: " Lisp" ( , Lisp), :

, setf Common Lisp, . Lisp , : [...]

, , ( ) , , , : -)

+4
2

, -, / . , . Lisp , , , . , setf Lisp , -:

      (slot-value vehicle 'speed)        ; gets the speed
(setf (slot-value vehicle 'speed) 100)   ; sets the speed

setf setter :

(set-slot-value vehicle 'speed 100)      ; sets the speed

:

(set-aref 3d-board 100 100 100 'foo)    ; sets the board at 100/100/100

, setter . setf.

: setter. setf . ? . setf getter call .

      world-time                         ; may return the world time
(setf world-time (get-current-time))     ; sets the world time

...

, : setf, push, pushnew, remf,... , .

(defun set-23 (place)
  (setf place 23))

, place - . . , , :

(defun set-23 (foo)
  (setf foo 23))

foo - . - . - . setf . -, , .

(defmethod set-24 ((vehicle audi-vehicle))
  (setf (vehicle-speed vehicle) 100))

vehicle audi-vehicle. , setf .

Lisp ? , :

(defclass audi-vehicle ()
   ((speed :accessor vehicle-speed)))

:accessor vehicle-speed , .

setf . . setf , Lisp , .

setf: expand:

:

CL-USER 86 > (pprint (macroexpand-1 '(setf (aref a1 10) 'foo)))

(LET* ((#:G10336875 A1) (#:G10336876 10) (#:|Store-Var-10336874| 'FOO))
  (SETF::\"COMMON-LISP\"\ \"AREF\" #:|Store-Var-10336874|
                                   #:G10336875
                                   #:G10336876))

:

CL-USER 87 > (pprint (macroexpand-1 '(setf a 'foo)))

(LET* ((#:|Store-Var-10336877| 'FOO))
  (SETQ A #:|Store-Var-10336877|))

CLOS:

CL-USER 88 > (pprint (macroexpand-1 '(setf (slot-value o1 'bar) 'foo)))

(CLOS::SET-SLOT-VALUE O1 'BAR 'FOO)

:

CL-USER 89 > (pprint (macroexpand-1 '(setf (car some-list) 'foo)))

(SYSTEM::%RPLACA SOME-LIST 'FOO)

, . setf Lisp , .

, , :

  • -
  • ,
+8

:

(defun set-23 (place)
  (setf place 23))

, setf . :

(defmacro set-23 (place)
  `(setf ,place 23))

CL-USER> (set-23 (aref *foo* 0))
23
CL-USER> *foo*
#(23 NIL NIL NIL NIL)

, setf "", , , . setfable.

setf - , , , .

, , , place, .

+6

Source: https://habr.com/ru/post/1543648/


All Articles