From fda29e26edd09ed6fecfbfc67e9365d08b2cf203 Mon Sep 17 00:00:00 2001 From: vindarel Date: Mon, 7 Dec 2020 11:57:40 +0100 Subject: [PATCH] add bind from metabang-bind fixes #11 --- ciel.asd | 57 ++++++++++++-------- docs/language-extensions.md | 104 ++++++++++++++++++++++++++++++++++++ src/ciel.lisp | 3 ++ 3 files changed, 143 insertions(+), 21 deletions(-) create mode 100644 docs/language-extensions.md diff --git a/ciel.asd b/ciel.asd index f4afbe3..0d417b8 100644 --- a/ciel.asd +++ b/ciel.asd @@ -47,24 +47,6 @@ :parse-float :parse-number - :cl-ppcre - :pythonic-string-reader - :str - :trivia ;; pattern matching - :trivial-arguments - :trivial-package-local-nicknames - :trivial-types - - ;; iteration - :iterate - :for - :trivial-do - - ;; lambda shorthands - ;; xxx: or rutils - :fn - :cl-punch - ;; database :mito :sxql @@ -72,7 +54,36 @@ ;; numerical :vgplot - ;; :rutils ;; yes? + ;; regexp + :cl-ppcre + + ;; string manipulation + :str + + ;;; + ;;; Language extensions. + ;;; + ;; triple quotes + :pythonic-string-reader + + ;; pattern matching + :trivia + :trivial-arguments + :trivial-package-local-nicknames + :trivial-types + + ;; extended let + :metabang-bind + + ;; iteration + :iterate + :for + :trivial-do + + ;; lambda shorthands + :fn + :cl-punch + :serapeum ;; tests @@ -80,12 +91,16 @@ :which - ;; debugging, developer utilities + ;;; + ;;; Debugging, developer utilities. + ;;; :log4cl :printv :repl-utilities ;; see readme, summary, doc, package-apropos, trace-package etc - ;; user helpers + ;;; + ;;; User helpers. + ;;; :lisp-critic :named-readtables :clesh diff --git a/docs/language-extensions.md b/docs/language-extensions.md new file mode 100644 index 0000000..0bd9a5f --- /dev/null +++ b/docs/language-extensions.md @@ -0,0 +1,104 @@ + +## Bind, more destructuring in `let` (metabang-bind) + +We import the `bind` macro from [metabang-bind](https://common-lisp.net/project/metabang-bind/user-guide.html) ([GitHub](https://github.com/gwkkwg/metabang-bind)). + +The idiomatic way to declare local variables is `let`. Use it if it is fine for you. + +However, if you ever noticed to write convoluted `let` forms, adding +list destructuring, multiple values or slot access into the mix, then +read on. + +`bind` integrates more variable binding and list destructuring idioms. It has two goals. Quoting: + +> 1. reduce the number of nesting levels + +> 2. make it easier to understand all of the different forms of destructuring and variable binding by unifying the multiple forms of syntax and reducing special cases. + +### Bind in CIEL + +We import the `bind` macro. However, the package has more external +symbols that we don't import, such as its error type (`bind-erro`) and +its extension mechanism. + + +### Bind is a replacement for `let` and `let*`. + +You can use `bind` in lieue of `let*`. + +So, its simpler form is: + +~~~lisp +(bind (a) + (do-something a)) +~~~ + +`a` is initialized to `nil`. + +To give it a default value, use a pair, as in `(a 1)` below: + +~~~lisp +(bind ((a 1) + (b 2)) + ...) +~~~ + +Below, we'll use indicators for `a`, the binding on the left-hand +side, so we can have a `bind` form that starts with three +parenthesis. But it's OK, you know how to read them. + +~~~lisp +(bind (((:values a b c) (a-function))) + ...) +~~~ + + +### Bind with multiple-values: `(:values ...)` + +Use `(:values ...)` in the left-hand side of the binding: + +~~~lisp +(bind (((:values a b) (truncate 4.5)) + ... +~~~ + +In pure CL, you'd use `multiple-value-bind` (aka mvb for completion). + + +### Ignore values: the `_` placeholder + +As in: + +~~~lisp +(bind (((_ value-1 value-2) (some-function-returning-3-values))) + ...) +~~~ + +### Destructuring lists + +Use a list in the left-hand side: + +~~~lisp +(defun return-list (a b) (list a b)) + +(bind (((a b) (return-list 3 4))) + (list a b)) +;; => (3 4) +~~~ + +You can use usual lambda parameters for more destructuring: + +~~~lisp +(bind ((a 2) + ((b &rest args &key (c 2) &allow-other-keys) '(:a :c 5 :d 10 :e 54)) + ((:values d e) (truncate 4.5))) + (list a b c d e args)) +~~~ + +### Bind with plists, arrays, classes, structures, regular expressions, flet and labels + +It's all well explained [in the documentation](https://common-lisp.net/project/metabang-bind/user-guide.html)! + +### See also: Trivia pattern matching + +If you like object destructuring in general, you'll like pattern matching with [Trivia](https://github.com/guicho271828/trivia/) (also available in CIEL). diff --git a/src/ciel.lisp b/src/ciel.lisp index 815634d..d847a4a 100644 --- a/src/ciel.lisp +++ b/src/ciel.lisp @@ -184,6 +184,7 @@ We currently only try this with serapeum. See *deps/serapeum/sequences-hashtable :trivial-types *deps/trivial-types*) *doc-pages*) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defun symbol-documentation (symbol &key (stream t)) @@ -238,6 +239,8 @@ We currently only try this with serapeum. See *deps/serapeum/sequences-hashtable (defpackage ciel-user (:use :cl :ciel) + (:import-from :metabang-bind + :bind) (:local-nicknames (:match :trivia) (:csv :cl-csv) (:http :dexador)))