[racket] About genericity...

From: Alexander D. Knauth (alexander at knauth.org)
Date: Thu Apr 3 21:12:38 EDT 2014

Is this sort of like what you mean?:

(define dup (my-match-lambda*))

(my-match-lambda-add-clause! dup [(list (? string? s)) (string-append s s)])
(my-match-lambda-add-clause! dup [(list (? integer? n)) (list n n)])

(check-equal? (dup "Hello") "HelloHello")
(check-equal? (dup 10) '(10 10))

Here’s the code:

#lang racket

(provide my-match-lambda*
         (struct-out my-match-lambda-procedure)
         (struct-out exn:fail:my-match-lambda:no-match)
         (struct-out exn:fail:my-match-lambda:no-match:next-clause)

(module+ test
  (require rackunit)
  (define dup (my-match-lambda*))
  (my-match-lambda-add-clause! dup [(list (? string? s)) (string-append s s)])
  (my-match-lambda-add-clause! dup [(list (? integer? n)) (list n n)])
  (check-equal? (dup "Hello") "HelloHello")
  (check-equal? (dup 10) '(10 10))

(define-syntax-rule (my-match-lambda* clause ...)
   (list (clause->proc clause) ...)))

(define-syntax-rule (clause->proc clause)
  (match-lambda* clause [args (raise-my-match-lambda:no-match-error args)]))

(struct my-match-lambda-procedure (procs)
  #:transparent #:mutable
  #:property prop:procedure
  (lambda (this . args)
    (let ([procs (my-match-lambda-procedure-procs this)])
      (define proc (apply my-match-lambda-append procs))
      (apply proc args))))

(define within-my-match-lambda-append?
  (make-parameter #f))

(define my-match-lambda-append
    [() (case-lambda)]
    [(f) f]
    [(f1 f2) (lambda args
               (with-handlers ([exn:fail:my-match-lambda:no-match:next-clause?
                                (λ (e) (apply f2 args))])
                 (parameterize ([within-my-match-lambda-append? #t])
                   (apply f1 args))))]))

(define-syntax-rule (my-match-lambda-add-clause! proc clause ...)
  (set-my-match-lambda-procedure-procs! proc
                                        (append (my-match-lambda-procedure-procs proc)
                                                (list (clause->proc clause) ...))))

(define-syntax-rule (my-match-lambda-add-overriding-clause! proc clause ...)
  (set-my-match-lambda-procedure-procs! proc
                                        (append (list (clause->proc clause) ...)
                                                (my-match-lambda-procedure-procs proc))))

(struct exn:fail:my-match-lambda:no-match exn:fail (args) #:transparent)
(struct exn:fail:my-match-lambda:no-match:next-clause exn:fail:my-match-lambda:no-match () #:transparent)

(define (raise-my-match-lambda:no-match-error args)
  (define message
     "my-match-lambda: no clause matches" "\n"
     "  args: "(~v args)""))
  (define error-exn
    (with-handlers ([exn:fail? identity])
      (error message)))
  (define exn
    (cond [(within-my-match-lambda-append?)
            message (exn-continuation-marks error-exn) args)]
            message (exn-continuation-marks error-exn) args)]))
  (raise exn))


On Apr 3, 2014, at 5:43 AM, Roman Klochkov <kalimehtar at mail.ru> wrote:

> Or even simpler 
> (define (dup a)
>   (cond
>     [(string? a) (string-append a a)]
>     [(integer? a) (list a a)])
> :-)
> I think, Alejandro wanted to add clauses in different places (generic in one module, added method in another, for example).
> Thu, 3 Apr 2014 20:11:36 +1100 от Daniel Prager <daniel.a.prager at gmail.com>:
> Here's an out-of-the-box option, using Racket's pattern matching with the (? predicate) form:
> (define/match (dup a)
>   [((? string?)) (string-append a a)]
>   [((? integer?)) (list a a)])
> Dan
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users
> -- 
> Roman Klochkov
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20140403/e1e60463/attachment.html>

Posted on the users mailing list.