Generics in Scheme

;; As an example of a generic function, `slices-index` takes
;; a list of any type and an element of that type and returns
;; the index of the first occurrence of v in s, or -1 if not present.
;; Note that Scheme doesn't have built-in generics, so we're using
;; a dynamic approach here.

(define (slices-index s v)
  (let loop ((i 0) (lst s))
    (cond
      ((null? lst) -1)
      ((equal? (car lst) v) i)
      (else (loop (+ i 1) (cdr lst))))))

;; As an example of a generic type, `make-list` creates
;; a singly-linked list with values of any type.

(define (make-list)
  (let ((head '()) (tail '()))
    (lambda (msg . args)
      (case msg
        ((push)
         (let ((new-elem (cons (car args) '())))
           (if (null? head)
               (begin
                 (set! head new-elem)
                 (set! tail new-elem))
               (begin
                 (set-cdr! tail new-elem)
                 (set! tail new-elem)))))
        ((all-elements)
         (let loop ((current head) (result '()))
           (if (null? current)
               (reverse result)
               (loop (cdr current) (cons (car current) result)))))))))

(define (main)
  (let ((s '("foo" "bar" "zoo")))
    (display "index of zoo: ")
    (display (slices-index s "zoo"))
    (newline))
  
  (let ((lst (make-list)))
    ((lst 'push) 10)
    ((lst 'push) 13)
    ((lst 'push) 23)
    (display "list: ")
    (display (lst 'all-elements))
    (newline)))

(main)

This Scheme code provides functionality similar to the Go example, with some adjustments due to the differences between the languages:

  1. The slices-index function is implemented as a regular function that works with lists. Scheme doesn’t have static typing or built-in generics, so this function will work with any type of list.

  2. The List type is implemented as a closure that maintains internal state (head and tail of the list) and responds to messages like ‘push’ and ‘all-elements’.

  3. The main function demonstrates the usage of these functions, similar to the Go example.

To run this program, you would typically save it to a file (e.g., generics.scm) and then run it with a Scheme interpreter. For example, if you’re using Guile Scheme:

$ guile generics.scm
index of zoo: 2
list: (10 13 23)

Note that Scheme doesn’t have built-in generics or static typing like Go does. The Scheme version relies on dynamic typing and the ability to work with heterogeneous lists. The concept of generics is approximated by functions that can work with different types of data, which is a natural feature of Scheme’s dynamic nature.