From a3a35ab083a269c2feea6f3da18885e3ccae29c6 Mon Sep 17 00:00:00 2001 From: Siddhartha Date: Tue, 22 Sep 2020 21:17:40 -0700 Subject: [PATCH] Use functor map implementation for lone sequences --- functional-lib/data/functor.rkt | 3 ++- functional-test/tests/data/functor.rkt | 32 ++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/functional-lib/data/functor.rkt b/functional-lib/data/functor.rkt index 8d253f8..c864f45 100644 --- a/functional-lib/data/functor.rkt +++ b/functional-lib/data/functor.rkt @@ -14,6 +14,7 @@ ([c:sequence? (define map c:map)])) (define/renamed map (variadic-map f . args) - (if (c:sequence? (first args)) + (if (and (c:sequence? (first args)) + (not (empty? (rest args)))) (apply c:map f args) (apply map f args))) diff --git a/functional-test/tests/data/functor.rkt b/functional-test/tests/data/functor.rkt index 2e26488..a18b71d 100644 --- a/functional-test/tests/data/functor.rkt +++ b/functional-test/tests/data/functor.rkt @@ -1,7 +1,9 @@ #lang racket/base (require (except-in data/collection map) + (prefix-in b: racket/base) data/functor + racket/generic rackunit rackunit/spec) @@ -15,7 +17,33 @@ (describe "map" (it "applies a function to the values inside a context" (check-equal? (map add1 (identity 25)) - (identity 26))) + (identity 26)) + (check-equal? (sequence->list (map add1 (list 1 2 3))) + (list 2 3 4))) (it "works like zip when applied to sequences" - (check-equal? (sequence->list (map + '(1 2 3) '(10 20 30))) '(11 22 33))))) + (check-equal? (sequence->list (map + '(1 2 3) '(10 20 30))) '(11 22 33))) + + (it "uses a functor map specification, if available, when applied to a sequence" + (struct bag (items) + #:transparent + + #:methods gen:functor + [(define (map f x) + ;; exclude numbers too big to fit in the bag + (bag (b:filter (lambda (v) + (< v 10)) + (b:map f (bag-items x)))))] + + #:methods gen:sequence + [(define/generic -empty? empty?) + (define/generic -first first) + (define/generic -rest rest) + (define (empty? x) + (-empty? (bag-items x))) + (define (first x) + (-first (bag-items x))) + (define (rest x) + (bag (-rest (bag-items x))))]) + + (check-equal? (map add1 (bag (list 7 8 9))) (bag (list 8 9))))))