mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-07-07 05:06:37 +02:00
parent
a62d82e048
commit
19e5398b92
2 changed files with 52 additions and 5 deletions
|
@ -17,22 +17,34 @@
|
||||||
. body))))))
|
. body))))))
|
||||||
|
|
||||||
;;> \subsubsubsection{(define-method (name (param type) ...) body ...)}
|
;;> \subsubsubsection{(define-method (name (param type) ...) body ...)}
|
||||||
|
;;> \subsubsubsection{\scheme{(define-method (name params ...) body ...)}}
|
||||||
|
|
||||||
|
;;> Each parameter should be either a single identifier or a list of the form
|
||||||
|
;;> \scheme{(param type)} where \var{param} is the parameter name and
|
||||||
|
;;> \var{type} is a predicate which returns true if it's argument is of the
|
||||||
|
;;> correct type.
|
||||||
|
;;> Parameters without a predicate will always match.
|
||||||
|
|
||||||
;;> Extends the generic function \var{name} with a new method that
|
;;> If multiple methods satisfy the arguments, the most recent method
|
||||||
;;> applies when the given param types all match.
|
;;> will be used. The special form \scheme{(call-next-method)} can be
|
||||||
|
;;> invoked to call the next most recent method with the same arguments.
|
||||||
|
|
||||||
(define-syntax define-method
|
(define-syntax define-method
|
||||||
(er-macro-transformer
|
(er-macro-transformer
|
||||||
(lambda (e r c)
|
(lambda (e r c)
|
||||||
(let ((name (car (cadr e)))
|
(let ((name (car (cadr e)))
|
||||||
(params (cdr (cadr e)))
|
(params (map (lambda (param)
|
||||||
|
(if (identifier? param)
|
||||||
|
`(,param (lambda _ #t))
|
||||||
|
param))
|
||||||
|
(cdr (cadr e))))
|
||||||
(body (cddr e)))
|
(body (cddr e)))
|
||||||
`(,(r 'generic-add!) ,name
|
`(,(r 'generic-add!) ,name
|
||||||
(,(r 'list) ,@(map cadr params))
|
(,(r 'list) ,@(map cadr params))
|
||||||
(,(r 'lambda) (next ,@(map car params))
|
(,(r 'lambda) (,(r 'next) ,@(map car params))
|
||||||
(,(r 'let-syntax) ((call-next-method
|
(,(r 'let-syntax) ((call-next-method
|
||||||
(,(r 'syntax-rules) ()
|
(,(r 'syntax-rules) ()
|
||||||
((_) (next)))))
|
((_) (,(r 'next))))))
|
||||||
,@body)))))))
|
,@body)))))))
|
||||||
|
|
||||||
(define (no-applicable-method-error name args)
|
(define (no-applicable-method-error name args)
|
||||||
|
|
35
tests/generic-tests.scm
Normal file
35
tests/generic-tests.scm
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
(import (chibi) (chibi generic) (chibi test))
|
||||||
|
|
||||||
|
(test-begin "generics")
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-generic add)
|
||||||
|
(define-method (add (x number?) (y number?))
|
||||||
|
(+ x y))
|
||||||
|
(define-method (add (x string?) (y string?))
|
||||||
|
(string-append x y))
|
||||||
|
(define-method (add x (y list?))
|
||||||
|
(append x y))
|
||||||
|
(test 4 (add 2 2))
|
||||||
|
(test "22" (add "2" "2"))
|
||||||
|
(test '(2 2) (add '() '(2 2)))
|
||||||
|
(test '(2 2) (add '(2) '(2)))
|
||||||
|
(test '(2 2) (add '(2 2) '()))
|
||||||
|
(test '(2) (add #f '(2)))
|
||||||
|
(test-error (add #(2) #(2))))
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-generic mul)
|
||||||
|
(define-method (mul (x number?) (y number?))
|
||||||
|
(* x y))
|
||||||
|
(define-method (mul (x inexact?) (y inexact?))
|
||||||
|
(+ (* x y) 0.1))
|
||||||
|
(define-method (mul (x exact?) (y exact?))
|
||||||
|
(inexact->exact (call-next-method)))
|
||||||
|
(test 21 (mul 3 7))
|
||||||
|
(test 21.0 (mul 3.0 7))
|
||||||
|
(test 21.0 (mul 3 7.0))
|
||||||
|
(test 21.1 (mul 3.0 7.0)))
|
||||||
|
|
||||||
|
(test-end)
|
Loading…
Add table
Reference in a new issue