Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?

Polymorphism in Scheme via compile time dispatch

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)

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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment