call-table-generics

  1. call-table-generics

This is a generics library implemented with call-table* from brev-separate.

With this take on generics, you don't need to declare any types, just use predicates.

(define-generic (plus (list? a) (list? b)) (append a b))

(define-generic (plus (string? a) (string? b)) (string-append a b))

(define-generic (plus (number? a) (number? b)) (+ a b))

(list
 (plus "13" "14")
 (plus 7 22)
 (plus 13 19)
 (plus '(a b c) '(1 2 3)))

⇒ ("1314" 29 32 (a b c 1 2 3))

You need to define them in order from least specific to most specific. This doesn't matter in the above example, but it does matter when you have, for example, something that works on number? and then something more specific that works on odd?.

Also, each version needs to have the same amount of arguments with the same names. Only the types can differ.

Here is the entire implementation♥

(define-for-syntax gentable (call-table*))
(define-ir-syntax*
  (define-generic (name . preds+bindings) . body)
  (gentable (strip-syntax name) (cons preds+bindings body))
  (let ((bindings (map (lambda (a) (if (pair? a) (cadr a) a)) preds+bindings)))
    `(define (,name ,@bindings)
   (cond ,@(map (lambda (el)
                  (cons
                   (let ((clause (car el)))
                     (if (< 1 (length clause))
                         (cons 'and clause)
                         (car clause)))
                   (cdr el)))
                (gentable (strip-syntax name)))))))))

Or for a repo,

git clone https://idiomdrottning.org/call-table-generics