[plt-scheme] iterate over characters in string

From: Chris Uzdavinis (chris at atdesk.com)
Date: Tue Aug 13 09:45:24 EDT 2002

I need to implement a simple checksum of a string.  The specifications
are for the sum of the ASCII values modulo 256.  Below is my first
implementation.  I am not a student (even though this sounds like
homework, it's actually for the FIX specification -- a standard format
used to represent stock transactions, and it really does specify this
for the checksum.)  However, I am learning Scheme on my own (I always
like learning new things) but all I have are books with no practical
guidance except for lurking on these groups.

A few questions:

  * is string->list O(n)?  (I think it is, but maybe some internal
    magic makes it constant?)

  * is there any kind of for-each function that works on a string at
    the byte level?

In Ruby (another language) iteration is as easy as this:

  def calc-checksum(msg)
      c = 0
      msg.each_byte { |b| c += b }
      return c % 256

In DrScheme, this is the best I have come up with yet:

  (define (calc-checksum line)
    (let loop ([checksum 0]
               [chars (string->list line)])
      (cond [(null? chars) (modulo checksum 256)]
            [else (loop (+ checksum 
                           (char->integer (car chars)))
                        (cdr chars))]))))

It seems a bit verbose (for my taste) and possibly inefficient due to
calling string->list if it really is O(n).  Does anyone have
suggestions for how to improve this code?  I feel the above is a bit
naive, but I don't know what the "best" way is, and usually there
really is a better way.

I'm hoping some mechanism does exist that I just overlooked.  Ideally
I'd do something like this: 

  (define (calc-checksum line)
    (let ([ck 0])
      (for-each-char (lambda (c) 
                       (set! ck (+ ck (char->integer c))))
This is called frequently enough to justify performance
considerations.  Thanks for any advice.


Posted on the users mailing list.