mirror of
https://github.com/ashinn/chibi-scheme.git
synced 2025-07-06 20:56:38 +02:00
parent
a62d82e048
commit
19e5398b92
2 changed files with 52 additions and 5 deletions
|
@ -17,22 +17,34 @@
|
|||
. 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
|
||||
;;> applies when the given param types all match.
|
||||
;;> If multiple methods satisfy the arguments, the most recent method
|
||||
;;> 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
|
||||
(er-macro-transformer
|
||||
(lambda (e r c)
|
||||
(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)))
|
||||
`(,(r 'generic-add!) ,name
|
||||
(,(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 'syntax-rules) ()
|
||||
((_) (next)))))
|
||||
((_) (,(r 'next))))))
|
||||
,@body)))))))
|
||||
|
||||
(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