x.let-star
2020-03-25
value binder
X.LET-STAR is a binding/destructuring utility for Common Lisp which currently combines:
a) let*
b) destructuring-bind
c) :mval - multiple-value-bind
d) :slot - with-slots
e) :slotval - "projection" of slot values of structure/object to local variables,
avoiding slot lookup every time the slot value is used in the scope
of let*
f) :accessor - with-accessors
g) :accessorval - "projection" of values retrieved by accessor function to local variables (same concept as e) )
h) :all - binding of a group of variables to one initialization value
i) destructuring of arrays
j) :complex - destructuring of complex numbers
Destructuring of lists, arrays and multiple values can contain
nested other binders, and also recognizes "don't care" variable _.
A small example of nested sequences destructuring:
(defstruct xxx a b)
(let* (((:mval #(x
(y (:complex r i) &rest rest)
(:slotval a b))
(f g))
(values (vector 10
(list 20 (complex 30 40) 50 60)
(make-xxx :a 70 :b 80))
(list 90 100))))
(values x y r i rest a b f g))
It's trivially extendible with DEFINE-BINDER macro, and supports adding
of customized declarations via DEFINE-DECLARATION-PROCESSING macro.
It's designed as drop-in replacement of common-list:let* (without any changes
in sources needed) and as almost drop-in replacement for metabang-bind.
X.LET-START shadows common-lisp:let* (since it's completely compatible with common-lisp:let*)
To use the X.LET-STAR library, your defpackage should roughly look as:
(defpackage :your-lib
(:use :common-lisp :x.let-star ...)
(:shadowing-import-from x.let-star let*) ;; the important line
...)
Example of other features:
(defstruct xxx a b c)
(let* (((_ (e . _) &key (g :xxx)) '(:sdfg (:wert :dfg :tyu) :g 100)) ;; b
((:mval h _) (rem 1234 34)) ;; c
((:slot a (b-first b)) (make-xxx :a 123)) ;; d
((:slotval (b-second b) c) (make-xxx :b 3245 :c 3456)) ;; e
((:all x y z) :init)) ;; f
(values e g h a b-first b-second c x y z))
==>
:WERT
100
10
123
NIL
3245
3456
:INIT
:INIT
:INIT
expansion:
(DESTRUCTURING-BIND ;; b
(#:IGNORE-1021 (E . #:IGNORE-1022) &KEY (G :XXX)) ;; b
'(:SDFG (:WERT :DFG :TYU) :G 100) ;; b
(DECLARE (IGNORE #:IGNORE-1021) (IGNORE #:IGNORE-1022)) ;; b
(MULTIPLE-VALUE-BIND ;; c
(H #:IGNORE-1020) ;; c
(REM 1234 34) ;; c
(DECLARE (IGNORE #:IGNORE-1020)) ;; c
(WITH-SLOTS (A (B-FIRST B)) (MAKE-XXX :A 123) ;; d
(LET ((#:VAL1019 (MAKE-XXX :B 3245 :C 3456))) ;; e
(LET ((B-SECOND (SLOT-VALUE #:VAL1019 'B))) ;; e
(LET ((C (SLOT-VALUE #:VAL1019 'C))) ;; e
(LET ((#:VAL1139 :INIT)) ;; f
(LET ((X #:VAL1139) (Y #:VAL1139) (Z #:VAL1139)) ;; f
(VALUES E G H A B-FIRST B-SECOND C X Y Z)))))))))
More binders will be added in future as the need arises.