commit bdd98becd6d14c9aae35202ffb92fa927d4c1485
parent c5976a4b6120c1c2e80c263d593d0b4abf5cfa5d
Author: Suzanne Soy <jsmaniac.github@suzanne.soy>
Date: Wed, 28 Jul 2021 19:05:40 +0100
Merge https://github.com/goderich/anaphoric
Diffstat:
5 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/afilter.rkt b/afilter.rkt
@@ -0,0 +1,13 @@
+#lang racket/base
+
+(provide afilter it)
+(require anaphoric/it
+ racket/stxparam
+ (for-syntax racket/base))
+
+(define-syntax-rule (afilter body lst)
+ (let ([func
+ (λ (var)
+ (syntax-parameterize ([it (make-rename-transformer #'var)])
+ body))])
+ (filter func lst)))
diff --git a/amap.rkt b/amap.rkt
@@ -0,0 +1,13 @@
+#lang racket/base
+
+(provide amap it)
+(require anaphoric/it
+ racket/stxparam
+ (for-syntax racket/base))
+
+(define-syntax-rule (amap body lst)
+ (let ([func
+ (λ (var)
+ (syntax-parameterize ([it (make-rename-transformer #'var)])
+ body))])
+ (map func lst)))
diff --git a/scribblings/anaphoric.scrbl b/scribblings/anaphoric.scrbl
@@ -2,7 +2,7 @@
@require[@for-label[anaphoric
racket/base]]
-@title{Anaphoric conditionals}
+@title{Anaphoric macros}
@author[@author+email["Suzanne Soy" "racket@suzanne.soy"]]
@defmodule[anaphoric]
@@ -10,7 +10,7 @@
@section{Overview}
This package provides anaphoric versions of @racket[if],
-@racket[when] and @racket[cond]. These bind the syntax
+@racket[when], @racket[cond], @racket[map], and @racket[filter]. These bind the syntax
parameter @racket[it] to the value produced by the
condition expression.
@@ -155,3 +155,30 @@ using @racket[it].
@racket[conditionᵢ] is successful.
}
+@section{Anaphoric map and filter}
+
+@defform[[(amap body lst)]]{
+ Anaphoric @racket[map]. Binds the syntax parameter @racket[it]
+ in the @racketid[body], and maps it over the list @racketid[lst]. Effectively the same
+ as wrapping the @racketid[body] in a @racket[lambda] with an @racket[it] parameter. Unlike @racket[map], @racket[amap]
+ only works on a single list.
+
+ @racket[amap] works with nested function calls:
+
+ @racketblock[(amap (string-append (string-upcase it) "!")
+ '("apple" "banana"))]
+
+ The syntax parameter @racket[it] may be used multiple times in the procedure:
+
+ @racketblock[(amap (* it it) '(1 2 3))]
+}
+
+@defform[[(afilter body lst)]]{
+ Anaphoric @racket[filter]. Binds the syntax parameter @racket[it]
+ in the @racketid[body], and filters the list @racketid[lst] using it. Effectively the same
+ as wrapping the body in a @racket[lambda] with an @racket[it] parameter.
+
+ @racket[afilter] works with nested function calls:
+
+ @racketblock[(afilter ((* it it) . > . 50) lst)]
+}
diff --git a/test/afilter-test.rkt b/test/afilter-test.rkt
@@ -0,0 +1,21 @@
+#lang racket/base
+
+(require anaphoric/afilter
+ rackunit)
+
+(define lst '(5 6 7 8 9))
+
+(check-equal?
+ '(6 8)
+ (afilter (odd? (add1 it)) lst)
+ "Nested function call.")
+
+(check-equal?
+ '(8 9)
+ (afilter ((* it it) . > . 50) lst)
+ "Multiple 'it' in a nested expression.")
+
+(check-equal?
+ '()
+ (afilter (= it 42) '())
+ "Empty list.")
diff --git a/test/amap-test.rkt b/test/amap-test.rkt
@@ -0,0 +1,19 @@
+#lang racket/base
+
+(require anaphoric/amap
+ rackunit)
+
+(check-equal?
+ '(2 3)
+ (amap (add1 it) '(1 2))
+ "Sanity check.")
+
+(check-equal?
+ '("2" "4")
+ (amap (number->string (+ it it)) '(1 2))
+ "Multiple 'it' in a nested expression.")
+
+(check-equal?
+ '()
+ (amap (/ it 0) '())
+ "Empty list.")