modf
文件大小: unknow
源码售价: 5 个金币 积分规则     积分充值
资源说明:A setf like macro for functional programming
* Modf

Modf is a =setf= like macro for functional programming.  Like =setf=, Modf knows
how to modify many Lisp objects such that a place will evaluate to a new value
of your choosing.  Unlike =setf=, Modf doesn't mutate the data in anyway.
Instead it creates a new object with the requested changes in place.  See [[http://directed-procrastination.blogspot.com/2011/05/introducting-modf-setf-for-functional.html][my
blog]] post on Modf for a bit more info.  Be warned though, while the gist is
definitely there, it has become a bit out of date as Modf has progressed.

** What does Modf do?

To give a pathologic example, Modf allows you to change =t= to =nil= in the
following expression easily.

#+BEGIN_SRC lisp
  (defparameter *crazy* '(1 #(a (2 #(b (3 #(c (4 t))))))))
  ==> *CRAZY*
  
  ;; Change that last value with Modf
  (modf
   (cadr (aref (cadr (aref (cadr (aref (cadr *crazy*) 1)) 1)) 1))
   nil)
  ==> (1 #(A (2 #(B (3 #(C (4 NIL)))))))
  
  ;; But note that the original data is unchanged
  ,*crazy*
  ==> (1 #(A (2 #(B (3 #(C (4 T)))))))
  
  ;; Note that the Modf form looks a lot like how you would use setf
  (setf
   (cadr (aref (cadr (aref (cadr (aref (cadr *crazy*) 1)) 1)) 1))
   nil)
  ==> NIL
  
  ,*crazy*
  ==> (1 #(A (2 #(B (3 #(C (4 NIL)))))))
  
  ;; What does Modf gain us, take a look.  Look it over.  It's all necessary
  (macroexpand
   '(modf
     (cadr (aref (cadr (aref (cadr (aref (cadr *crazy*) 1)) 1)) 1))
     nil))
  
  ==>
  (LET ((#:G1556 *CRAZY*))
    (CONS (CAR #:G1556)
          (LET ((#:G1555 (CDR #:G1556)))
            (CONS
             (LET ((#:G1554 (CAR #:G1555)))
               (FUNCALL (MODF-FN AREF)
                        (LET ((#:G1553 (AREF #:G1554 1)))
                          (CONS (CAR #:G1553)
                                (LET ((#:G1552 (CDR #:G1553)))
                                  (CONS
                                   (LET ((#:G1551 (CAR #:G1552)))
                                     (FUNCALL (MODF-FN AREF)
                                              (LET ((#:G1550 (AREF #:G1551 1)))
                                                (CONS (CAR #:G1550)
                                                      (LET ((#:G1549
                                                              (CDR #:G1550)))
                                                        (CONS
                                                         (LET ((#:G1548
                                                                 (CAR #:G1549)))
                                                           (FUNCALL
                                                            (MODF-FN AREF)
                                                            (LET ((#:G1547
                                                                    (AREF #:G1548 1)))
                                                              (CONS (CAR #:G1547)
                                                                    (LET ((#:G1546
                                                                            (CDR
                                                                             #:G1547)))
                                                                      (CONS NIL
                                                                            (CDR
                                                                             #:G1546)))))
                                                            #:G1548 1))
                                                         (CDR #:G1549)))))
                                              #:G1551 1))
                                   (CDR #:G1552)))))
                        #:G1554 1))
             (CDR #:G1555)))))
#+END_SRC

The aim is to make this work for any Lisp object, including CLOS objects and
structures.

** How does Modf work?

It works similar to the way =setf= works.  With =setf= expansions are defined
that take some kind of accessor function and turn it into a function that sets
the value at that place.  In Modf, expansions are defined that turn an accessor
function into a function that builds a new object the specified change in place.

** Where does Modf work?

Modf strives to be portable and work everywhere as long as Modf expansion
functions are defined.  See the section /Defining your own Modf Expansions/.  I
aim to cover all primitive data types in CL.  As of now, it should work in any
Lisp when working with lists, arrays, hash tables, and, given you have defined
your Modf expanders for your data types, class instances and structs.

For usability purposes, however, a lot of effort has gone into making Modf work
for data even if Modf expansions haven't been defined.  This is a very difficult
to impossible task.  For one, we have no way of knowing which argument holds the
actual data structure.  If no expansion is defined, we assume it is at the first
argument of the place (adjusting for =apply= statements).

In the case of class accessor methods without defined Modf expansions,
Closer-Mop is used to examine the data at run time and produce the functional
changes.  For structures we don't even have Closer-Mop to help us and a series
of heuristics are used at run time to try to invert accessor functions (again,
only if no Modf expander has been defined).

If Modf doesn't work for something common out of the box, feel free to post a
bug report.  It would be even better if you can think of a way figure out what
to do.

Modf is tested regularly on the major Libre Software implementations (SBCL,
CMUCL, CCL, CLISP, ECL).

** Defining your own Modf expansions

Modf works my defining various expansion constructs.  These expansion constructs
can be in the form of:

 1. *Rewrite Rules* via =define-modf-rewrite=, a simple macro like facility that
    rewrites the place you want to =modf= into something simpler.  Think =(cadr
    x)= -> =(car (cdr x))=.

 2. *Expanders* via =define-modf-expander=, a more general expansion mechanism
    where you define a function that is given the place to be modded, the
    current value of that place, and the new value it should be modded to.

 3. *Modf functions and Methods* via =define-modf-function= and
    =define-modf-method=, which you should think of as a way to define =(setf
    fn)= like functions for Modf.

In principle, the last construct alone is enough to do anything you want.  The
others are included for your convenience and with thoughts of compiler
optimization on the in place expansions performed by expanders.

For expanders and Modf functions/methods, you need to specify which argument
actually holds the data that is being modified.  This is given as an extra
argument after the name.

** Known issues

 1. Tons of stuff with ABCL.  It actually works for most things in ABCL, but I
    don't have the patience to get the test suite running.

 2. Perhaps issues with order of evaluation.  I haven't gone through a thorough
    audit of this yet.

** Documentation

Working on it.  This is supposed to be a literate program, but the comments in
the source are chicken scratch.

** Author

Zach Kost-Smith


** License

3-Clause BSD.  See file COPYING.

本源码包内暂不包含可直接显示的源代码文件,请下载源码包。