Here's an example of polymorphism in C++:
int nth ( int a[] , int i ) { return a[i] ; }
double nth ( double a[] , int i ) { return a[i] ; }
One way to think of this is that there are two functions called nth
. One can be called with an int array and the other can be called with a double array. The function that is called is determined at compile time by looking at the type of the expression of the first argument.
Scheme doesn't have such a facility built into it by default. One problem is that variables and expressions aren't usually typed and so it's hard to perform a dispatch based on type at compile time.
Chez Scheme has support for associating arbitrary data with identifiers. So in theory, it's possible to achieve something like C++'s compile time polymorphism.
Let's make a Scheme version of nth which works with vectors or strings:
(define-syntax nth
(lambda (stx)
(lambda (lookup)
(syntax-case stx ()
( (nth seq i)
(let ((seq-type (lookup #'seq #'type)))
(cond ( (eq? seq-type 'vector)
(syntax (vector-ref seq i)) )
( (eq? seq-type 'string)
(syntax (string-ref seq i)) )))) ))))
Now let's test it out. Define abc
to be a vector:
> (define abc '#(a b c))
Declare it to be of type vector
:
> (define-property abc type 'vector)
Call nth
on abc:
> (nth abc 0)
a
Let's try calling nth
on variables which are inside a let
:
> (let ((a '#(1 2 3))
(b "123"))
(define-property a type 'vector)
(define-property b type 'string)
(list (nth a 0)
(nth b 0)))
(1 #\1)