Just wrote this
(define-macro (dostring of . body)
(case (length of)
((2) (if (list? (car of))
`(dostring (,@of (values)) ,@body)
`(dostring ((,(car of) ,(symbolicate (car of) '-index))
,(cadr of) (values)) ,@body)))
((3) (if (list? (car of))
`(reverse-args begin ,(caddr of)
(reverse-args string-for-each-index ,(cadr of)
(lambda (,(cadar of))
(let ((,(caar of) (string-ref ,(cadr of) ,(cadar of)))) ,@body))))
`(dostring ((,(car of) ,(symbolicate (car of) '-index))
,(cadr of) ,(caddr of)) ,@body)))))
an example
(dostring (char "apple")
(format #t "~a : ~a~%" char char-index)) ; keeps track of index