Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Criticize my code

Name: Anonymous 2011-11-09 9:25

I'm trying to do perl-style string formating:

(let ([a 1] [b 2])
  (say "a=$a, b=$b"))


Here is what I wrote so far:

(module snv mzscheme
(require (lib "defmacro.ss"))
(require (lib "list.ss"))
(require (lib "string.ss"))
(require-for-syntax (lib "string.ss"))
(require (only (lib "../srfi/13.ss")
               string-null?))

(require snv-hlp)
(require-for-syntax snv-hlp)

(provide (all-from snv-hlp))
(provide (all-from (lib "string.ss")))

(provide-define-macro (fmt xs)
  (let ([r '()]
        [s 0]
        [l (string-length xs)])
    (times i l
      (let ([x (string-ref xs i)])
        (when (char=? x #\$)
          (when (> (- i s) 0) (push (substring xs s i) r))
          (push #\$ r)
          (set! s (+ 1 i)))))
    (push (substring xs s l) r)
    (set! r (reverse! r))
    (letrec
        ((fold-fmt
          (lambda (xs)
            (if (null? xs)
                null
                (let ([x (car xs)])
                  (set! xs (cdr xs))
                  (cons
                   (cond [(eq? x #\$)
                          (when (null? xs)
                            (error "missing argument to $"))
                          (set! x  (car xs))
                          (set! xs (cdr xs))
                          (cond [(eq? x #\$) "$"]
                                [else
                                 (let ([l (string-length x)])
                                   (if (or (< l 3) (not (char=? (string-ref x 0) #\{)))
                                       (let* ([s (read-from-string x)]
                                              [sl (string-length (symbol->string s))])
                                         (set! x (substring x sl l))
                                         (if (not (string=? x "")) (push x xs))
                                         `(expr->string ,s))
                                       (read-from-string (substring x 1 (- l 1)))))])]
                         [else x])
                   (fold-fmt xs)))))))
      `(string-append ,@(fold-fmt r)))
    ))

(provide-define-macro (say x)
  `(printf "~a~n" (fmt ,x)))
 
) ;; module snv

Name: Anonymous 2011-11-09 10:54

>>4

Does it only support single character symbols? I don't see anything for scanning variable length symbols, and checking for delimiters like spaces. But anyways, if you wanted to, you could write some functional tail cally helper functions. A function that would be nice for scanning through the words and stepping over them, would be a function that when given an index into the string, finds the index of the first delimiter character (like a space I guess. scheme supports a lot of characters in symbols) after that index.


(define (index-of-word-ending str start)
  (letrec ([helper (lambda (end)
            (if (is (string-ref str end) a delimiter character? Use a hash set of delimiter characters for great [i]success![/i])
              end
              (helper (+ 1 end))))])
    (helper start)))


When you know the location of the delimiter character, you have enough information to both generate the substring representing the word you scanned, and to continue the scanning from the end of the word.

(define (scan-string str)
  (letrec ([scanner (lambda (s i l r)
                      (cond [(>= s l)
                             (reverse r)]
                            [(eq? (string-ref str s) #\$)
                             (let ([end (index-of-word-ending str s)])
                               (scanner end end l (cons (substring str s end)
                                                        (cons #\$ r))))]
                            [else (put some code here that scans from s to the index of the next dollar sign, and then push that onto r using tail call)]))])
    (scanner 0 0 (string-length str) '())))

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List