Skip to content

Latest commit

 

History

History
105 lines (78 loc) · 2.26 KB

0148-modf.org

File metadata and controls

105 lines (78 loc) · 2.26 KB

modf

This system provides a macro which acts like setf but does not change original data-structure. It will be useful if you want to write the code in a functional style, without side-effects:

POFTHEDAY> (defparameter *foo*
             '(#(1 2 3 4 5)
               #(6 7 8)
               #(9)))

POFTHEDAY> (defparameter *bar*
             (modf:modf (aref (second *foo*)
                              1)
                        :blah))

POFTHEDAY> *foo*
(#(1 2 3 4 5)
 #(6 7 8)
 #(9))

POFTHEDAY> *bar*
(#(1 2 3 4 5)
 #(6 :BLAH 8)
 #(9))

Resulting data structure can share some parts with the original:

POFTHEDAY> (eq *foo*
               *bar*)
NIL

POFTHEDAY> (eq (first *foo*)
               (first *bar*))
T

POFTHEDAY> (eq (second *foo*)
               (second *bar*))
NIL

POFTHEDAY> (eq (third *foo*)
               (third *bar*))
T

But this does not work for some lisp forms. For example, it is impossible to change plist using getf:

POFTHEDAY> (defparameter *foo*
             '(:name "Bob"
               :points #(1 2 3 4 5)))

POFTHEDAY> (defparameter *bar*
             (modf:modf (aref (getf *foo*
                                    :points)
                              2)
                        100500))
; Debugger entered on #<SIMPLE-ERROR "How shall I invert GETF?">

Hopefuly, the library can be extended and we might define our own function to modify plists:

POFTHEDAY> (modf:define-modf-function getf 2 (new-val plist key)
             (let ((new-plist (copy-list plist)))
               (setf (getf new-plist key)
                     new-val)
               new-plist))

POFTHEDAY> (defparameter *bar*
             (modf:modf (aref (getf *foo*
                                    :points)
                              2)
                        100500))

POFTHEDAY> *foo*
(:NAME "Bob" :POINTS #(1 2 3 4 5))

POFTHEDAY> *bar*
(:NAME "Bob" :POINTS #(1 2 100500 4 5))

There are a few other ways to extend modf. They are listed in the documentation but there are no examples. But you can find them in the source code.