💾 Archived View for idiomdrottning.org › call-table-generics captured on 2023-04-26 at 13:46:28. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

call-table-generics

Using call-table* to make the fastest generics of all time in only 14 lines like a boss♥

You don’t even 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

call-table*