mutable-match-lambda
source code: https://github.com/AlexKnauth/mutable-match-lambda
(require mutable-match-lambda) | |
package: mutable-match-lambda |
> (require mutable-match-lambda racket/vector)
> (define my+ (mutable-match-lambda))
> my+ #<procedure:my+>
> (mutable-match-lambda-add-clause! my+ #:match-lambda* [(list (? number? ns) ...) (apply + ns)])
> (my+ 1 2) 3
> (mutable-match-lambda-add-clause! my+ #:match-lambda* [(list (? vector? vs) ...) (apply vector-map + vs)])
> (my+ #(1 2) #(3 4)) '#(4 6)
1 mutable-match-lambda-procedure
struct
(struct mutable-match-lambda-procedure (name procs) #:mutable #:transparent) name : any/c procs : (listof procedure?)
procedure
(make-mutable-match-lambda proc ... [ #:name name]) → mutable-match-lambda-procedure? proc : procedure? name : any/c = #f
procedure
(mutable-match-lambda-add-clause-proc! proc clause-proc ...) → void? proc : mutable-match-lambda-procedure? clause-proc : procedure?
procedure
(mutable-match-lambda-add-overriding-clause-proc! proc clause-proc ...) → void? proc : mutable-match-lambda-procedure? clause-proc : procedure?
(define (mutable-match-lambda-add-clause-proc! proc . clause-procs) (set-mutable-match-lambda-procedure-procs! proc (append (mutable-match-lambda-procedure-procs proc) clause-procs))) (define (mutable-match-lambda-add-overriding-clause-proc! proc . clause-procs) (set-mutable-match-lambda-procedure-procs! proc (append clause-procs (mutable-match-lambda-procedure-procs proc))))
> (require mutable-match-lambda racket/vector)
> (define my+ (make-mutable-match-lambda))
> (mutable-match-lambda-add-clause-proc! my+ (clause->proc #:match-lambda* [(list (? number? ns) ...) (apply + ns)]))
> (my+ 1 2) 3
> (mutable-match-lambda-add-clause-proc! my+ (clause->proc #:match-lambda* [(list (? vector? vs) ...) (apply vector-map + vs)]))
> (my+ #(1 2) #(3 4)) '#(4 6)
> (mutable-match-lambda-add-clause-proc! my+ (lambda args 7))
> (my+ 1 2) 3
> (my+ #(1 2) #(3 4)) '#(4 6)
> (my+ "not a number or a vector") 7
> (mutable-match-lambda-add-overriding-clause-proc! my+ (lambda args 42))
> (my+ 1 2) 42
syntax
(mutable-match-lambda-add-clause! proc-expr clause-proc-expr ...)
(mutable-match-lambda-add-clause! proc-expr kw clause ...)
syntax
(mutable-match-lambda-add-overriding-clause! proc-expr clause-proc-expr ...)
(mutable-match-lambda-add-overriding-clause! proc-expr kw clause ...)
> (require mutable-match-lambda racket/vector)
> (define my+ (make-mutable-match-lambda))
> (mutable-match-lambda-add-clause! my+ #:match-lambda* [(list (? number? ns) ...) (apply + ns)])
> (my+ 1 2) 3
> (mutable-match-lambda-add-clause! my+ #:match-lambda* [(list (? vector? vs) ...) (apply vector-map + vs)])
> (my+ #(1 2) #(3 4)) '#(4 6)
> (mutable-match-lambda-add-clause! my+ (lambda args 7))
> (my+ 1 2) 3
> (my+ #(1 2) #(3 4)) '#(4 6)
> (my+ "not a number or a vector") 7
> (mutable-match-lambda-add-overriding-clause! my+ (lambda args 42))
> (my+ 1 2) 42
procedure
(mutable-match-lambda-clause-append proc ... [ #:name name]) → procedure? proc : procedure? name : any/c = 'mutable-match-lambda
This is what mutable-match-lambda-procedure uses to combine its clauses.
procedure
It is similar in spirit to match’s failure-cont, except that it does escape the current context, and it cares about the dynamic extent, not syntactic scope.
procedure
(mutable-match-lambda-append proc ... [ #:name name]) → mutable-match-lambda-procedure? proc : procedure? name : any/c = #f
The difference between this and make-mutable-match-lambda is that if a proc is a mutable-match-lambda-procedure, then its procs are spliced into the resulting list. As a result the mutable-match-lambda-procedures are effectively copied (and in fact mutable-match-lambda-copy is defined with mutable-match-lambda-append).
If you don’t want this copying behavior, you can use make-mutable-match-lambda to achieve that.
procedure
(mutable-match-lambda-copy proc)
→ mutable-match-lambda-procedure? proc : procedure?
It is equivalent to (mutable-match-lambda-append proc #:name (mutable-match-lambda-procedure-name proc)).
syntax
(make-mutable-match-lambda/infer-name proc-expr ...)
It is used to infer the names for forms like mutable-case-lambda and mutable-match-lambda.
2 mutable-match-lambda, etc
syntax
(mutable-case-lambda case-lambda-clause ...)
(define-syntax-rule (mutable-case-lambda clause ...) (make-mutable-match-lambda/infer-name (clause->proc #:case-lambda clause) ...))
> (require mutable-match-lambda)
> (examples) examples: undefined;
cannot reference undefined identifier
syntax
(mutable-match-lambda match-lambda-clause ...)
(define-syntax-rule (mutable-match-lambda clause ...) (make-mutable-match-lambda/infer-name (clause->proc #:match-lambda clause) ...))
> (require mutable-match-lambda)
> (examples) examples: undefined;
cannot reference undefined identifier
syntax
(mutable-match-lambda* match-lambda*-clause ...)
(define-syntax-rule (mutable-match-lambda* clause ...) (make-mutable-match-lambda/infer-name (clause->proc #:match-lambda* clause) ...))
> (require mutable-match-lambda)
> (examples) examples: undefined;
cannot reference undefined identifier
3 make-clause-proc and clause->proc
procedure
(make-clause-proc test-proc then-proc) → procedure?
test-proc : procedure? then-proc : procedure?
> (require mutable-match-lambda racket/vector)
> (define clause-1 (make-clause-proc (λ args (andmap number? args)) (λ args (apply + args))))
> (define clause-2 (make-clause-proc (λ args (andmap vector? args)) (λ args (apply vector-map + args))))
> (define my+ (make-mutable-match-lambda clause-1 clause-2))
> (my+ 1 2) 3
> (clause-1 1 2) 3
> (my+ #(1 2) #(3 4)) '#(4 6)
> (clause-2 #(1 2) #(3 4)) '#(4 6)
syntax
(clause->proc kw clause)
For example (clause->proc #:match-lambda* match-lambda*-clause) creates a clause-proc that acts like a match-lambda* clause. It actually expands to (clause->proc/match-lambda* match-lambda*-clause), and then clause->proc/match-lambda* does the rest.
(clause->proc #:whatever clause) expands to (clause->proc/whatever clause), so if you define a macro with the name clause->proc/whatever, then you can use (clause->proc #:whatever clause).
When defining a new clause->proc/whatever macro, it should call mutable-match-lambda-next if it doesn’t match.
clause->proc/case-lambda, clause->proc/match-lambda, and clause->proc/match-lambda* are already defined, so to start with clause->proc supports #:case-lambda, #:match-lambda, and #:match-lambda* as keywords.
> (require mutable-match-lambda)
> (clause->proc #:case-lambda [(x y) (list x y)]) #<procedure:|(clause->proc #:case-lambda ((x y) (list x y)))|>
> (define-syntax-rule (clause->proc/bool->ans ans) (lambda (x) (if x ans (mutable-match-lambda-next))))
> (define f (make-mutable-match-lambda (clause->proc #:bool->ans 42) (lambda _ "didn't match")))
> (f #t) 42
> (f #f) "didn't match"
syntax
(clause->proc/case-lambda clause)
syntax
(clause->proc/match-lambda clause)
syntax
(clause->proc/match-lambda* clause)