-- Leo's gemini proxy

-- Connecting to idiomdrottning.org:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini; lang=en

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*

-- Response ended

-- Page fetched on Fri Jul 23 16:29:38 2021