commit ff1ad651f38225c0fe9eb03d0beba69985317dd6
parent c5ef4cc0cfd557027fc343b119a8af56ee5f7667
Author: Georges Dupéron <georges.duperon@gmail.com>
Date: Mon, 8 Aug 2016 12:15:17 +0200
Added if-let when-let and cond-let, as per Alex Knauth's suggestion. Closes issue #1.
Diffstat:
5 files changed, 119 insertions(+), 5 deletions(-)
diff --git a/cond-let.rkt b/cond-let.rkt
@@ -0,0 +1,17 @@
+#lang racket
+
+(provide cond-let)
+
+(define-syntax (cond-let stx)
+ (syntax-case stx (else)
+ [(cond-let [[identifierᵢ conditionᵢ] . bodyᵢ] ... [else . else-body])
+ #'(cond [conditionᵢ => (λ (identifierᵢ) . bodyᵢ)] ...
+ [else . else-body])]
+ [(cond-let [[identifierᵢ conditionᵢ] . bodyᵢ] ...)
+ #'(cond [conditionᵢ => (λ (identifierᵢ) . bodyᵢ)] ...)]
+
+ [(cond-let identifier [conditionᵢ . bodyᵢ] ... [else . else-body])
+ #'(cond [conditionᵢ => (λ (identifier) . bodyᵢ)] ...
+ [else . else-body])]
+ [(cond-let [[identifierᵢ conditionᵢ] . bodyᵢ] ...)
+ #'(cond [conditionᵢ => (λ (identifierᵢ) . bodyᵢ)] ...)]))
+\ No newline at end of file
diff --git a/if-let.rkt b/if-let.rkt
@@ -0,0 +1,10 @@
+#lang racket
+
+(provide if-let)
+
+(define-syntax-rule (if-let [variable condition] true-branch false-branch)
+ (let ([tmp condition])
+ (if tmp
+ (let ([variable tmp])
+ true-branch)
+ false-branch)))
+\ No newline at end of file
diff --git a/info.rkt b/info.rkt
@@ -6,5 +6,5 @@
(define scribblings '(("scribblings/anaphoric.scrbl" ())))
(define compile-omit-paths '("test/"))
(define pkg-desc "Anaphoric versions of `if`, `when` and `cond`. They bind the value of the condition expression to `it`.")
-(define version "0.0")
+(define version "0.1")
(define pkg-authors '(|Georges Dupéron|))
diff --git a/scribblings/anaphoric.scrbl b/scribblings/anaphoric.scrbl
@@ -2,11 +2,13 @@
@require[@for-label[anaphoric
racket/base]]
-@title{anaphoric}
-@author{georges}
+@title{Anaphoric conditionals}
+@author+email["georges.duperon@gmail.com"]{Georges Dupéron}
@defmodule[anaphoric]
+@section{Overview}
+
This package provides anaphoric versions of @racket[if],
@racket[when] and @racket[cond]. These bind the syntax
parameter @racket[if] to the value produced by the
@@ -45,4 +47,78 @@ appears in a sequence of else branches:
'not-executed
(aif (eq? 'second 'no)
'not-executed
- (displayln it)))]
-\ No newline at end of file
+ (displayln it)))]
+
+This package also provides the hygienic versions
+@racket[if-let], @racket[when-let] and @racket[cond-let],
+for which the user needs to specify an identifier instead of
+using @racket[it].
+
+@section{The anaphoric conditionals @racket[aif],
+ @racket[awhen] and @racket[acond]}
+
+@defidform[it]{
+ Syntax parameter which acts as a rename transformer for
+ the result of the condition expression, when bound by
+ @racket[aif], @racket[awhen] or @racket[acond].
+
+ Raises a syntax error when used outside of the
+ @racket[_true-branch] of an @racket[aif] or the body of an
+ @racket[awhen] or the body of a non-@racket[else] case in
+ @racket[acond].}
+
+@defform[(aif condition true-branch false-branch)]{
+ Variant of @racket[if] which binds @racket[it] to the
+ value of @racket[condition] in @racket[true-branch].
+ @racket[condition] is only evaluated once. In the
+ @racket[false-branch], @racket[it] is left unchanged.}
+
+@defform[(awhen condition body ...+)]{
+ Variant of @racket[when] which binds @racket[it] to the
+ value of @racket[condition] in @racket[body ...+].
+ @racket[condition] is only evaluated once.}
+
+@defform*[#:literals (else)
+ [(acond [conditionᵢ bodyᵢ ...+] ...)
+ (acond [conditionᵢ bodyᵢ ...+] ... [else body ...+])]]{
+ Variant of @racket[cond] which binds @racket[it] to the
+ corresponding @racket[conditionᵢ] in the non-@racket[else]
+ cases. More precisely, in each @racket[bodyᵢ ...+],
+ @racket[it] is bound to the value of the corresponding
+ @racket[conditionᵢ]. Each @racket[conditionᵢ] is evaluated
+ at most once (evaluation stops at the first successful
+ @racket[conditionᵢ]).}
+
+@section{The hygienic versions @racket[if-let],
+ @racket[when-let] and @racket[cond-let]}
+
+@defform[(if-let [identifier condition] true-branch false-branch)]{
+ Variant of @racket[if] which binds @racket[identifier] to
+ the value of @racket[condition] in @racket[true-branch].
+ @racket[condition] is only evaluated once. In the
+ @racket[false-branch], @racket[identifier] is left unchanged.}
+
+@defform[(when-let [identifier condition] body ...+)]{
+ Variant of @racket[when] which binds @racket[identifier] to
+ the value of @racket[condition] in @racket[body ...+].
+ @racket[condition] is only evaluated once.}
+
+@defform*[#:literals (else)
+ [(cond-let [[identifierᵢ conditionᵢ] bodyᵢ ...+] ...)
+ (cond-let [[identifierᵢ conditionᵢ] bodyᵢ ...+] ... [else body ...+])
+ (cond-let identifier [conditionᵢ bodyᵢ ...+] ...)
+ (cond-let identifier [conditionᵢ bodyᵢ ...+] ... [else body ...+])]]{
+ Variant of @racket[cond] which binds each
+ @racket[identifierᵢ] to the corresponding
+ @racket[conditionᵢ] in the non-@racket[else] cases. More
+ precisely, in each @racket[bodyᵢ ...+], the corresponding
+ @racket[identifierᵢ] is bound to the value of the
+ corresponding @racket[conditionᵢ].
+
+ The last two variants are shorthands for using the same
+ @racket[identifier] in all cases (except the @racket[else]
+ case)
+
+ Each @racket[conditionᵢ] is evaluated at most once
+ (evaluation stops at the first successful
+ @racket[conditionᵢ]).}
+\ No newline at end of file
diff --git a/when-let.rkt b/when-let.rkt
@@ -0,0 +1,8 @@
+#lang racket
+
+(provide when-let)
+
+(define-syntax-rule (when-let [variable condition] . body)
+ (let ([variable condition])
+ (when variable
+ . body)))
+\ No newline at end of file