views:

128

answers:

5

Hi,

In Scheme, procedures like +, -, *, / works on different types of numbers, but we don't much see any other generic procedures.

For example, length works only on list so that vector-length and string-length are needed.

I guess it comes from the fact that the language doesn't really offer any mechanism for defining generic procedure (except cond of course) like "type classes" in Haskell or a standardized object system.

Is there an idiomatic scheme way to handle generic procedures that I'm not aware of ?

+1  A: 

No, but you can build your own. Welcome to Scheme!

In the past I've used Swindle to provide generic functions. It's bundled with PLT Scheme. It worked well for me, but it's been a few years. There may be other alternatives out there now.

Nathan Sanders
+2  A: 

Keeping in mind that all "different types of numbers" are all scheme numbers (i.e. (number? n) equals #t) - this behavior actually makes sense. +, -, *, / and all other arithmetic operators operate on numbers only (even though in other languages they would be classified as different number types int, long, float, etc...) This is due to the fact that you can't explicitly declare number types in scheme.

If you really need a generic solution, besides using external libraries, the easiest way is to roll your own:

(define org-length length)
(define (length x)
  (cond
    ((string? x) (string-length x))
    ((vector? x) (vector-length x))
    ; keep going ...
    (else (org-length x))))
Yuval A
Wouldn't that last call to length cause infinite recursion? Or is there a trick that I'm missing?
jakebman
Yeah, he forgot to keep a reference to the original length.
Skeptic
indeed, fixed...
Yuval A
+1  A: 

Read SICP, sections 2.4 and 2.5, which cover the implementation of procedures that can operate on generic data types by means of attaching "tags" to data objects. It's also in lecture 4-B of that MIT video series.

Cirno de Bergerac
Yeah, I should have mentioned "tagged list" in my question. However, it's not a very convenient way of handling generic procedures on primitive types.
Skeptic
+1  A: 

You really want to have an object system for that. You may want to have a look at Tiny CLOS, for instance, which is the de-facto standard object system for Chicken Scheme (see the reference manual), but seems to be available for most Scheme implementations.

Matthias Benkard
A: 

Finally, I found out a very neat solution in PLT Scheme :

(require (rename-in scheme [length list-length]))

(define length
 (λ (x)
  ((cond [(list? x) list-length]
         [(string? x) string-length]
         [(vector? x) vector-length]
         [else (error "whatever")]) x)))

(length '(a b c))
(length "abc")
(length #(1 2 3))  
Skeptic