From ec77a48d2355d0315f5476ad4d89a72ed696acf6 Mon Sep 17 00:00:00 2001 From: Sam Tobin-Hochstadt Date: Mon, 21 Oct 2013 16:46:59 -0400 Subject: [PATCH] Add access to the failure continuation in `match`. --- .../racket-doc/scribblings/reference/match.scrbl | 10 +++++++++- pkgs/racket-pkgs/racket-test/tests/match/examples.rkt | 8 +++++++- racket/collects/racket/match.rkt | 7 ++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/pkgs/racket-pkgs/racket-doc/scribblings/reference/match.scrbl b/pkgs/racket-pkgs/racket-doc/scribblings/reference/match.scrbl index dfc8aace34..e265a54e1c 100644 --- a/pkgs/racket-pkgs/racket-doc/scribblings/reference/match.scrbl +++ b/pkgs/racket-pkgs/racket-doc/scribblings/reference/match.scrbl @@ -34,7 +34,8 @@ arguments. If this procedure is invoked, it escapes back to the pattern matching expression, and resumes the matching process as if the pattern had failed to match. The @racket[body]s must not mutate the object being matched before calling the failure procedure, -otherwise the behavior of matching is unpredictable. +otherwise the behavior of matching is unpredictable. See also +@racket[failure-cont]. The grammar of @racket[pat] is as follows, where non-italicized identifiers are recognized symbolically (i.e., not by binding). @@ -518,6 +519,13 @@ b A predicate for the exception raised in the case of a match failure. } +@defform[(failure-cont)]{ +Continues matching as if the current pattern failed. Note that unlike +use of the @racket[=>] form, this does @emph{not} escape the current +context, and thus should only be used in tail position with respect to +the @racket[match] form. +} + @; ---------------------------------------- diff --git a/pkgs/racket-pkgs/racket-test/tests/match/examples.rkt b/pkgs/racket-pkgs/racket-test/tests/match/examples.rkt index 42646e5bcc..b1723ad7ce 100644 --- a/pkgs/racket-pkgs/racket-test/tests/match/examples.rkt +++ b/pkgs/racket-pkgs/racket-test/tests/match/examples.rkt @@ -710,5 +710,11 @@ (match-let ([(list x y) (list 1 22)] [(list y z) '(2 3)]) (list x y z)))) - + (comp 1 + (match (cons 1 2) + [(cons a b) + (if (< a b) + (failure-cont) + 0)] + [_ 1])) )) diff --git a/racket/collects/racket/match.rkt b/racket/collects/racket/match.rkt index 60c4122df7..d181e5ee31 100644 --- a/racket/collects/racket/match.rkt +++ b/racket/collects/racket/match.rkt @@ -1,16 +1,21 @@ #lang racket/base -(require racket/match/match +(require racket/match/match "match/runtime.rkt" (for-syntax racket/base)) (provide (except-out (all-from-out racket/match/match) define-match-expander) + failure-cont (rename-out [define-match-expander* define-match-expander])) + (define-for-syntax (no-old-match-form stx) (raise-syntax-error #f "works only for constructor-based `match' form" stx)) +(define-syntax-rule (failure-cont) (fail)) + + (define-syntax define-match-expander* (syntax-rules () [(_ id expr) (define-match-expander id expr)]