-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeneric-coercion-multi.rkt
40 lines (37 loc) · 1.69 KB
/
generic-coercion-multi.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#lang racket
(require "tagged-obj.rkt")
(require "getput.rkt")
(require "coercion-table.rkt")
(require "list-util.rkt")
(require racket/trace)
(provide apply-generic)
(define (apply-generic op . args)
(define (find-first p l)
(if (null? l)
false
(if (p (car l))
(car l)
(find-first p (cdr l)))))
(let ((type-tags (map type-tag args)))
(let ((proc (get op type-tags)))
(if proc
(apply proc (map contents args))
(if (> (length args) 1)
(let ((types (map type-tags args)))
(if (list-identical? types)
(error "No method for these types" (list op type-tags))
; find a type for which we can coerce all other types into
; coerce to that type and call apply-generic
(let ((generic-type
(find-first (lambda (t)
(and-list (map (lambda (s)
(if (eq? s t)
true
(get-coercion s t))) types))) types)))
(if generic-type
(apply-generic op (map (lambda (s)
(if (eq? (type-tag s) generic-type)
s
((get-coercion (type-tag s) generic-type) s))) args))
(error "No method for these types" (list op type-tags))))))
(error "No method for these types" (list op type-tags)))))))