mutable-match-lambda
1 mutable-match-lambda-procedure
mutable-match-lambda-procedure
make-mutable-match-lambda
mutable-match-lambda-add-clause-proc!
mutable-match-lambda-add-overriding-clause-proc!
mutable-match-lambda-add-clause!
mutable-match-lambda-add-overriding-clause!
mutable-match-lambda-clause-append
mutable-match-lambda-next
mutable-match-lambda-append
mutable-match-lambda-copy
make-mutable-match-lambda/  infer-name
2 mutable-match-lambda, etc
mutable-case-lambda
mutable-match-lambda
mutable-match-lambda*
3 make-clause-proc and clause->proc
make-clause-proc
clause->proc
clause->proc/  case-lambda
clause->proc/  match-lambda
clause->proc/  match-lambda*
6.12

mutable-match-lambda

source code: https://github.com/AlexKnauth/mutable-match-lambda

These forms and functions allow mutable generic procedures like this:

Examples:
> (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?)
represents a procedure, with a prop:procedure property that allows it to be applied as a procedure. It tries each of its procs in order, using mutable-match-lambda-clause-append. Forms like mutable-case-lambda and mutable-match-lambda all create instances of this. When they do, each clause is converted to a procedure (using clause->proc) and the list of procedures is stored in the procs field.

procedure

(make-mutable-match-lambda proc 
  ... 
  [#:name name]) 
  mutable-match-lambda-procedure?
  proc : procedure?
  name : any/c = #f
equivalent to (mutable-match-lambda-procedure name (list proc ...)).

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?
these functions add clauses to a mutable-match-lambda-procedure. The difference between them is that mutable-match-lambda-add-clause-proc! adds a clause that is only used when no other clause matches, and mutable-match-lambda-add-overriding-clause-proc! adds a clause that overrides the other clauses when it matches.

They are defined like this:
(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))))

Examples:
> (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 ...)
these forms add clauses to a mutable-match-lambda-procedure. The first form (for both) adds the clause-proc-exprs to the list of procs, and is exactly like mutable-match-lambda-add-clause-proc! and mutable-match-lambda-add-overriding-clause-proc!. The second form (for both) converts the clauses to procedures (using (clause->proc kw clause)), and then adds those to the list of procs. The difference between them is the same as the difference between mutable-match-lambda-add-clause-proc! and mutable-match-lambda-add-overriding-clause-proc!.

Examples:
> (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
makes a new procedure that tries all of the procs in order.

This is what mutable-match-lambda-procedure uses to combine its clauses.

if it is called within a mutable-match-lambda-clause procedure, it signals to mutable-match-lambda-clause-append to try the next clause (if there is one). Otherwise it raises an error.

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
makes a new mutable-match-lambda-procedure that tries all of the procs in order.

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.

if proc is a mutable-match-lambda-procedure, it returns a copy of proc. Otherwise it returns a mutable-match-lambda-procedure that has proc as its only clause.

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 ...)

like make-mutable-match-lambda, except that it can infers the name argument from the context. For example, in (define my-proc (make-mutable-match-lambda/infer-name)), it infers the name 'my-proc.

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 ...)

like case-lambda, except makes a mutable-match-lambda-procedure that you can add functionality to with procedures such as mutable-match-lambda-add-clause!. By the way, you can add other types of clauses than case-lambda clauses later.

It is defined like this:

Examples:
> (require mutable-match-lambda)
> (examples)

examples: undefined;

 cannot reference undefined identifier

syntax

(mutable-match-lambda match-lambda-clause ...)

like match-lambda, except makes a mutable-match-lambda-procedure that you can add functionality to with procedures such as mutable-match-lambda-add-clause!. By the way, you can add other types of clauses than match-lambda clauses later.

It is defined like this:

Examples:
> (require mutable-match-lambda)
> (examples)

examples: undefined;

 cannot reference undefined identifier

syntax

(mutable-match-lambda* match-lambda*-clause ...)

like match-lambda*, except makes a mutable-match-lambda-procedure that you can add functionality to with procedures such as mutable-match-lambda-add-clause!. By the way, you can add other types of clauses than match-lambda* clauses later.

It is defined like this:

Examples:
> (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?
makes a procedure that mutable-match-lambda-procedure can use as a clause-proc. When it is called, it calls test-proc with it’s arguments, and if test-proc returns a true value, it then calls then-proc with its arguments. If test-proc returns #false, then it moves on to the next clause (if there is one).

Examples:
> (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)

makes a procedure that mutable-match-lambda-procedure can use as a clause-proc. The keyword specifies what type of clause it is.

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.

Examples:
> (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"

these forms produce procedures that mutable-match-lambda-procedure can use as clause-procs, so you can use #:case-lambda etc. as keywords in clause->proc.