(Need to go deeper!) macroexpansion confusion

Discussion of Common Lisp
Post Reply
wvxvw
Posts: 127
Joined: Sat Mar 26, 2011 6:23 am

(Need to go deeper!) macroexpansion confusion

Post by wvxvw » Thu May 10, 2012 2:00 am

I think I mostly avoided using macros until now, but here's something I tried and it doesn't look good to me, particularly the '(,@whites) part - that shouldn't need so much of ASCII art, must be a better way to handle it!

Code: Select all

(defmacro with-words-in-string
    ((word start end
           &aux (whites '(#\Space #\Tab #\Newline #\Rubout)))
     s
     &body body)
  `(do ((,end 0 (1+ ,end))
        (,start 0)
        (,word)
        (len 0))
       ((= ,end (1+ (length ,s))))
     (if (or (= ,end (length ,s)) (find (aref ,s ,end) '(,@whites)))
         (if (> len 0)
             (progn
               (setf ,word (subseq ,s ,start ,end))
               ,@body
               (setf len 0 ,start (1+ ,end)))
             (incf ,start))
         (incf len))))

(with-words-in-string (word start end)
    "Quick brown fox jumped over the lazy dog"
    (format t "word: ~s, start: ~s, end: ~s~&" word start end))

Kalimehtar
Posts: 1
Joined: Thu May 10, 2012 3:11 am

Re: (Need to go deeper!) macroexpansion confusion

Post by Kalimehtar » Thu May 10, 2012 4:14 am

Also works:

Code: Select all

(defmacro with-words-in-string
    ((word start end
           &aux (whites '(#\Space #\Tab #\Newline #\Rubout)))
     s
     &body body)
  `(do ((,end 0 (1+ ,end))
        (,start 0)
        (,word)
        (len 0))
       ((= ,end (1+ (length ,s))))
     (if (or (= ,end (length ,s)) (find (aref ,s ,end) ',whites))
         (if (> len 0)
             (progn
               (setf ,word (subseq ,s ,start ,end))
               ,@body
               (setf len 0 ,start (1+ ,end)))
             (incf ,start))
         (incf len))))

(with-words-in-string (word start end)
    "Quick brown fox jumped over the lazy dog"
    (format t "word: ~s, start: ~s, end: ~s~&" word start end))

ramarren
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland
Contact:

Re: (Need to go deeper!) macroexpansion confusion

Post by ramarren » Thu May 10, 2012 12:25 pm

If you have a large quasiquoted block in the macro often you can extract it into a function, and then use a macro to just wrap a body with a lambda like this:

Code: Select all

(defun call-with-words-in-string (s whites thunk)
  (do ((end 0 (1+ end))
       (start 0)
       (word)
       (len 0))
      ((= end (1+ (length s))))
    (if (or (= end (length s)) (find (aref s end) whites))
        (if (> len 0)
            (progn
              (setf word (subseq s start end))
              (funcall thunk word start end)
              (setf len 0 start (1+ end)))
            (incf start))
        (incf len))))

(defmacro with-words-in-string
    ((word start end
      &aux (whites '(#\Space #\Tab #\Newline #\Rubout)))
     s
     &body body)
  `(call-with-words-in-string ,s ',whites
                              #'(lambda (,word ,start ,end)
                                  ,@body)))

wvxvw
Posts: 127
Joined: Sat Mar 26, 2011 6:23 am

Re: (Need to go deeper!) macroexpansion confusion

Post by wvxvw » Thu May 10, 2012 1:30 pm

Oh, OK, good to know, thanks both of you!

Post Reply