Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Momchil Ivanov
alexandria
Commits
d670d4fb
Commit
d670d4fb
authored
Nov 07, 2006
by
Nikodemus Siivola
Browse files
IF-LET, IF-LET*, WHEN-LET, and WHEN-LET*
parent
d3989d23
Changes
4
Hide whitespace changes
Inline
Side-by-side
alexandria.asd
View file @
d670d4fb
...
...
@@ -10,6 +10,7 @@
(
:file
"symbols"
:depends-on
(
"package"
))
(
:file
"arrays"
:depends-on
(
"package"
))
(
:file
"types"
:depends-on
(
"package"
))
(
:file
"binding"
:depends-on
(
"package"
))
(
:file
"functions"
:depends-on
(
"package"
"symbols"
))
(
:file
"lists"
:depends-on
(
"package"
"functions"
))
(
:file
"sequences"
:depends-on
(
"package"
"lists"
))
...
...
binding.lisp
0 → 100644
View file @
d670d4fb
(
in-package
:alexandria
)
(
defmacro
if-let
(
bindings
then-form
&optional
else-form
)
"Creates new variable bindings, and conditionally executes either
THEN-FORM or ELSE-FORM (defaulting to NIL).
BINDINGS must be either single binding of the form:
(variable initial-form)
or a list of bindings of the form:
((variable-1 initial-form-1)
(variable-2 initial-form-2)
...
(variable-n initial-form-n))
All initial-forms are executed sequentially in the specified order. Then all
the variables are bound to the corresponding values.
If all variables were bound to true values, the THEN-FORM is executed with the
bindings in effect, otherwise the ELSE-FORM is executed with the bindings in
effect."
(
let*
((
binding-list
(
if
(
and
(
consp
bindings
)
(
symbolp
(
car
bindings
)))
(
list
bindings
)
bindings
))
(
variables
(
mapcar
#'
car
binding-list
)))
`
(
let
,
binding-list
(
if
(
and
,@
variables
)
,
then-form
,
else-form
))))
(
defmacro
if-let*
(
bindings
then-form
&optional
else-form
)
"Creates new variable bindings, and conditionally executes either THEN-FORM
or ELSE-FORM (defaulting to NIL).
BINDINGS must be either single binding of the form:
(variable initial-form)
or a list of bindings of the form:
((variable-1 initial-form-1)
(variable-2 initial-form-2)
...
(variable-n initial-form-n))
Each initial-form is executed in turn, and the variable bound to the
corresponding value. Initial-form expressions can refer to variables
previously bound by the IF-LET*.
If all variables are true after the bindings are complete, the THEN-FORM is
executed with the bindings in effect, otherwise the ELSE-FORM is executed with
the bindings in effect."
(
let*
((
binding-list
(
if
(
and
(
consp
bindings
)
(
symbolp
(
car
bindings
)))
(
list
bindings
)
bindings
))
(
variables
(
mapcar
#'
car
binding-list
)))
`
(
let*
,
binding-list
(
if
(
and
,@
variables
)
,
then-form
,
else-form
))))
(
defmacro
when-let
(
bindings
&body
forms
)
"Creates new variable bindings, and conditionally executes either
THEN-FORM or ELSE-FORM (defaulting to NIL).
BINDINGS must be either single binding of the form:
(variable initial-form)
or a list of bindings of the form:
((variable-1 initial-form-1)
(variable-2 initial-form-2)
...
(variable-n initial-form-n))
All initial-forms are executed sequentially in the specified order. Then all
the variables are bound to the corresponding values.
If all variables were bound to true values, then FORMS are executed as an
implicit PROGN."
(
let*
((
binding-list
(
if
(
and
(
consp
bindings
)
(
symbolp
(
car
bindings
)))
(
list
bindings
)
bindings
))
(
variables
(
mapcar
#'
car
binding-list
)))
`
(
let
,
binding-list
(
when
(
and
,@
variables
)
,@
forms
))))
(
defmacro
when-let*
(
bindings
&body
forms
)
"Creates new variable bindings, and conditionally executes either THEN-FORM
or ELSE-FORM (defaulting to NIL).
BINDINGS must be either single binding of the form:
(variable initial-form)
or a list of bindings of the form:
((variable-1 initial-form-1)
(variable-2 initial-form-2)
...
(variable-n initial-form-n))
Each initial-form is executed in turn, and the variable bound to the
corresponding value. Initial-form expressions can refer to variables
previously bound by the IF-LET*.
If all variables are true after the bindings are complete, then FORMS are
executed as an implicit PROGN."
(
let*
((
binding-list
(
if
(
and
(
consp
bindings
)
(
symbolp
(
car
bindings
)))
(
list
bindings
)
bindings
))
(
variables
(
mapcar
#'
car
binding-list
)))
`
(
let*
,
binding-list
(
when
(
and
,@
variables
)
,@
forms
))))
package.lisp
View file @
d670d4fb
...
...
@@ -2,6 +2,11 @@
(
:nicknames
:alexandria
)
(
:use
:cl
)
(
:export
;; Binding constructs
#:if-let
#:if-let*
#:when-let
#:when-let*
;; Hash tables
#:copy-hash-table
#:hash-table-keys
...
...
@@ -65,6 +70,7 @@
#:suffle
;; Macros
#:with-unique-names
#:with-gensyms
#:once-only
#:parse-body
;; Symbols
...
...
tests.lisp
View file @
d670d4fb
...
...
@@ -962,3 +962,78 @@
(
type=
'string
'list
)
nil
t
)
;;;; Bindings
(
declaim
(
notinline
opaque
))
(
defun
opaque
(
x
)
x
)
(
deftest
if-let.1
(
if-let
(
x
(
opaque
:ok
))
x
:bad
)
:ok
)
(
deftest
if-let.2
(
if-let
(
x
(
opaque
nil
))
:bad
(
and
(
not
x
)
:ok
))
:ok
)
(
deftest
if-let.3
(
let
((
x
1
))
(
if-let
((
x
2
)
(
y
x
))
(
+
x
y
)
:oops
))
3
)
(
deftest
if-let.4
(
if-let
((
x
1
)
(
y
nil
))
:oops
(
and
(
not
y
)
x
))
1
)
(
deftest
if-let*.1
(
let
((
x
1
))
(
if-let*
((
x
2
)
(
y
x
))
(
+
x
y
)
:oops
))
4
)
(
deftest
if-let*.2
(
if-let*
((
x
2
)
(
y
(
prog1
x
(
setf
x
nil
))))
:oops
(
and
(
not
x
)
y
))
2
)
(
deftest
when-let.1
(
when-let
(
x
(
opaque
:ok
))
(
setf
x
(
cons
x
x
))
x
)
(
:ok
.
:ok
))
(
deftest
when-let.2
(
when-let
((
x
1
)
(
y
nil
)
(
z
3
))
:oops
)
nil
)
(
deftest
when-let.3
(
let
((
x
1
))
(
when-let
((
x
2
)
(
y
x
))
(
+
x
y
)))
3
)
(
deftest
when-let*.1
(
let
((
x
1
))
(
when-let*
((
x
2
)
(
y
x
))
(
+
x
y
)))
4
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment