This is an interesting library by @guicho271828, which allows moving some calculations into the compile-time.
Constant folding is a cool thing when smart compiler simplifies expressions in compile-time if some parts of the expression are known.
For example, when you will write (* (+ 1 3) 3600)
, SBCL will simplify it
to a 14400
constant during compilation of the lisp file.
Library constantfold
allows you to define rules for constant folding for
custom data structures:
POFTHEDAY> (defstruct point2d
(x 0)
(y 0))
POFTHEDAY> (defun point2d-add-2 (left right)
(make-point2d
:x (+ (point2d-x left)
(point2d-x right))
:y (+ (point2d-y left)
(point2d-y right))))
POFTHEDAY> (defun point2d-add (&rest args)
(reduce #'point2d-add-2 args))
;; These calls will define macro with same name
;; as functions:
POFTHEDAY> (constantfold:constantfold
make-point2d
:copier copy-point2d)
POFTHEDAY> (constantfold:constantfold
point2d-add
:copier copy-point2d
:commutative t
:associative t)
;; And foldable arguments will be folded into a constant:
POFTHEDAY> (macroexpand-dammit
'(point2d-add (make-point2d :x 1 :y 2)
(make-point2d :x 3 :y 4)))
(COPY-POINT2D '#S(POINT2D :X 4 :Y 6))
When some values are not known at compile-time, they are left unfolded:
POFTHEDAY> (macroexpand-dammit
'(defun add-offset (x y)
(point2d-add (make-point2d :x 1 :y 2)
(make-point2d :x x :y y)
(make-point2d :x 3 :y 4))))
(DEFUN ADD-OFFSET (X Y)
(POINT2D-ADD
;; This is the result of folding two points into one:
(COPY-POINT2D '#S(POINT2D :X 4 :Y 6))
;; And this is the point with unknown X and Y:
(MAKE-POINT2D :X X :Y Y)))
To look at how does it work in the whild, you might write NumCL
’s
code. This library uses constantfold
to mark functions which work with
numbers to make constant folding work for them.