21296e2bf834

Add `when-let*`
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Thu, 17 Nov 2016 12:44:46 +0000
parents 0e60bff93317
children 344ee2fa239e
branches/tags (none)
files DOCUMENTATION.markdown losh.lisp package.lisp

Changes

--- a/DOCUMENTATION.markdown	Tue Nov 15 17:30:45 2016 +0000
+++ b/DOCUMENTATION.markdown	Thu Nov 17 12:44:46 2016 +0000
@@ -214,6 +214,41 @@
 
   
 
+### `WHEN-LET*` (macro)
+
+    (WHEN-LET* BINDING-FORMS
+      &BODY
+      BODY)
+
+Bind the forms in `binding-forms` in order, short-circuiting on `nil`.
+
+  This is like Clojure's `when-let`.  It takes a list of binding and binds them
+  like `let*`, but if any of the expressions evaluate to `nil` the process stops
+  there and `nil` is immediately returned.
+
+  Examples:
+
+    (when-let* ((a (progn (print :a) 1))
+                (b (progn (print :b) 2))
+                (c (progn (print :c) 3)))
+      (list a b c))
+    ; =>
+    :A
+    :B
+    :C
+    (1 2 3)
+
+    (when-let* ((a (progn (print :a) 1))
+                (b (progn (print :b) nil))
+                (c (progn (print :c) 3)))
+      (list a b c))
+    ; =>
+    :A
+    :B
+    NIL
+
+  
+
 ## Package `LOSH.DEBUGGING`
 
 Utilities for figuring out what the hell is going on.
--- a/losh.lisp	Tue Nov 15 17:30:45 2016 +0000
+++ b/losh.lisp	Thu Nov 17 12:44:46 2016 +0000
@@ -412,6 +412,43 @@
         ,@body)
       (queue-contents ,result))))
 
+(defmacro when-let* (binding-forms &body body)
+  "Bind the forms in `binding-forms` in order, short-circuiting on `nil`.
+
+  This is like Clojure's `when-let`.  It takes a list of binding and binds them
+  like `let*`, but if any of the expressions evaluate to `nil` the process stops
+  there and `nil` is immediately returned.
+
+  Examples:
+
+    (when-let* ((a (progn (print :a) 1))
+                (b (progn (print :b) 2))
+                (c (progn (print :c) 3)))
+      (list a b c))
+    ; =>
+    :A
+    :B
+    :C
+    (1 2 3)
+
+    (when-let* ((a (progn (print :a) 1))
+                (b (progn (print :b) nil))
+                (c (progn (print :c) 3)))
+      (list a b c))
+    ; =>
+    :A
+    :B
+    NIL
+
+  "
+  (if (null binding-forms)
+    `(progn ,@body)
+    (destructuring-bind ((symbol expr) . remaining-bindings)
+      binding-forms
+      `(let ((,symbol ,expr))
+         (when ,symbol
+           (when-let* ,remaining-bindings ,@body))))))
+
 
 ;;;; Mutation -----------------------------------------------------------------
 (defun build-zap (place expr env)
@@ -1416,7 +1453,6 @@
   (values))
 
 
-
 #+sbcl
 (defun dump-profile (filename)
   (with-open-file (*standard-output* filename
--- a/package.lisp	Tue Nov 15 17:30:45 2016 +0000
+++ b/package.lisp	Thu Nov 17 12:44:46 2016 +0000
@@ -75,7 +75,8 @@
     :when-found
     :if-found
     :gathering
-    :gather))
+    :gather
+    :when-let*))
 
 (defpackage :losh.mutation
   (:documentation "Utilities for mutating places in-place.")