From: Jon Haugsand
Subject: Local macro within a macro?
Date: 
Message-ID: <yzo7lkzqhld.fsf@procyon.nr.no>
I have a macro called DOCHUNK that I use to piece up a sequence in
order to process smaller pieces. I.e. 

(DOCHUNK piece "abcdefgh" 3 (princ piece) (princ " ")))
abc def gh

DOCHUNK is defined as follows:

(defmacro dochunk ((chunk proseq n &key (start 0) end) &body body)
  (let ((low (gensym))
        (hi (gensym))
        (len (gensym))
        (vend (gensym)))
    `(let* ((,len (length ,proseq))
           (,vend (or ,end ,len))
            (,chunk))
       (do ((,low ,start ,hi)
            (,hi (min ,len ,n) (min (+ ,hi ,n) ,len)))
           ((>= ,low ,vend) (- ,vend ,start))
         (setf ,chunk (subseq ,proseq ,low ,hi))
         ,@body))))

However, for large sequences there is unnecessary copying into a new
variable CHUNK. I would like CHUNK to expand into (SUBSEQ ,PROSEQ ,LOW
,HI) within ,@BODY. Is this possible? Other comments on concept and
code are also welcoming.

-- 
Jon Haugsand
  Norwegian Computing Center, <http://www.nr.no/engelsk/> 
  <···············@nr.no>  Pho: +47 22852608 / +47 22852500, 
  Fax: +47 22697660, Pb 114 Blindern, N-0314 OSLO, Norway

From: Lieven Marchand
Subject: Re: Local macro within a macro?
Date: 
Message-ID: <m34sg3t6ch.fsf@localhost.localdomain>
Jon Haugsand <········@procyon.nr.no> writes:

> However, for large sequences there is unnecessary copying into a new
> variable CHUNK. I would like CHUNK to expand into (SUBSEQ ,PROSEQ ,LOW
> ,HI) within ,@BODY. Is this possible? Other comments on concept and
> code are also welcoming.

You could use SYMBOL-MACROLET. 

This has been tested with Allegro/Linux 5.0

(defmacro do-chunk ((chunk sequence step &key (start 0) end) &body body)
  (let ((low (gensym))
	(high (gensym))
	(length (gensym))
	(vend (gensym)))
    `(let* ((,length (length ,sequence))
	    (,vend (or ,end ,length)))
       (symbol-macrolet ((,chunk (subseq ,sequence ,low ,high)))
	 (do ((,low ,start ,high)
	      (,high (min ,length ,step) (min (+ ,high ,step) ,length)))
	     ((>= ,low ,vend) (- ,vend ,start))
	   ,@body)))))

-- 
Lieven Marchand <···@bewoner.dma.be>
If there are aliens, they play Go. -- Lasker
From: Arthur Lemmens
Subject: Re: Local macro within a macro?
Date: 
Message-ID: <37FCF9D7.C245E28A@simplex.nl>
Jon Haugsand wrote:
> 
> I have a macro called DOCHUNK that I use to piece up a sequence in
> order to process smaller pieces. I.e.
> 
> (DOCHUNK piece "abcdefgh" 3 (princ piece) (princ " ")))
> abc def gh

I suppose you mean
  (DOCHUNK (piece "abcdefgh" 3) (princ piece) (princ " "))

> (defmacro dochunk ((chunk proseq n &key (start 0) end) &body body)
>   (let ((low (gensym))
>         (hi (gensym))
>         (len (gensym))
>         (vend (gensym)))
>     `(let* ((,len (length ,proseq))
>            (,vend (or ,end ,len))
>             (,chunk))
>        (do ((,low ,start ,hi)
>             (,hi (min ,len ,n) (min (+ ,hi ,n) ,len)))
>            ((>= ,low ,vend) (- ,vend ,start))
>          (setf ,chunk (subseq ,proseq ,low ,hi))
>          ,@body))))
> 
> However, for large sequences there is unnecessary copying into a new
> variable CHUNK. 

Actually, the copying is being done by SUBSEQ, not by the SETF.
The SETF in your macro just copies a pointer (crudely speaking).
So I don't really think there's any "unnecessary copying" going on
(as long as you consider the calls to SUBSEQ to be necessary).

> I would like CHUNK to expand into (SUBSEQ ,PROSEQ ,LOW ,HI) within ,@BODY. 
> Is this possible? 

If you really wanted to, I suppose you could use SYMBOL-MACROLET. But you 
wouldn't avoid any copying that way; in fact, you may even introduce some 
extra unnecessary copying. Consider what would happen in code like this:
(DOCHUNK (piece "abcdefghi" 3)
  (concatenate 'string piece "=" piece))
With the 'improvement' you have in mind, SUBSEQ would get called 6 times 
here, not 3.

--
Arthur Lemmens
From: Barry Margolin
Subject: Re: Local macro within a macro?
Date: 
Message-ID: <gU6L3.617$854.25035@burlma1-snr2>
In article <···············@procyon.nr.no>,
Jon Haugsand  <········@procyon.nr.no> wrote:
>However, for large sequences there is unnecessary copying into a new
>variable CHUNK. I would like CHUNK to expand into (SUBSEQ ,PROSEQ ,LOW
>,HI) within ,@BODY. Is this possible? Other comments on concept and
>code are also welcoming.

SETF doesn't do any copying.  Everything in Lisp is references to objects,
there's no copying unless you use a function that explicitly does so.
E.g. if your code contained:

(setf ,chunk (copy-seq (subseq ,proseq ,low ,hi)))

then you would get a copy of the subsequence.

Note that SUBSEQ itself makes a copy; this will happen whether or not you
assign it to a variable or pass it as an argument.  So if you make ,CHUNK
expand into that, then every time ,CHUNK appears in @BODY you will get a
*new* subsequence.  So what you're doing will result in more copies, not
fewer.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: David D. Smith
Subject: Re: Local macro within a macro?
Date: 
Message-ID: <dds-0810990314310001@p051.bit-net.com>
In article <···············@procyon.nr.no>, Jon Haugsand
<········@procyon.nr.no> wrote:

> I have a macro called DOCHUNK that I use to piece up a sequence in
> order to process smaller pieces. I.e. 
> 
> (DOCHUNK piece "abcdefgh" 3 (princ piece) (princ " ")))
> abc def gh
> 
> DOCHUNK is defined as follows:
> 
> (defmacro dochunk ((chunk proseq n &key (start 0) end) &body body)
>   (let ((low (gensym))
>         (hi (gensym))
>         (len (gensym))
>         (vend (gensym)))
>     `(let* ((,len (length ,proseq))
>            (,vend (or ,end ,len))
>             (,chunk))
>        (do ((,low ,start ,hi)
>             (,hi (min ,len ,n) (min (+ ,hi ,n) ,len)))
>            ((>= ,low ,vend) (- ,vend ,start))
>          (setf ,chunk (subseq ,proseq ,low ,hi))
>          ,@body))))
> 
> However, for large sequences there is unnecessary copying into a new
> variable CHUNK. I would like CHUNK to expand into (SUBSEQ ,PROSEQ ,LOW
> ,HI) within ,@BODY. Is this possible? Other comments on concept and
> code are also welcoming.

If you have multiple references then each inlined subseq will make a new
copy, and be even less efficient.  You could allocate a single N sized
"chunk" sequenece and move the elements with presumed efficiency, instead
of using SUBSEQ.

If you are using arrays you may be able to use a displaced array and
adjust it as necessary.

Here is a version that does what you asked:

;;; This inlines chunk.  It also makes a copy, and possibly many.
;;; P.S. You may want to bind PROSEQ and START to temps.
(defmacro dochunk ((chunk proseq n &key (start 0) end) &body body)
  (let ((low (gensym))
        (hi (gensym))
        (len (gensym))
        (vend (gensym)))
    `(let* ((,len (length ,proseq))
            (,vend (or ,end ,len)))
       (do ((,low ,start ,hi)
            (,hi (min ,len ,n) (min (+ ,hi ,n) ,len)))
           ((>= ,low ,vend) (- ,vend ,start))
         (symbol-macrolet ((,chunk (subseq ,proseq ,low ,hi)))
           ,@body)))))

(DOCHUNK (piece "abcdefgh" 3) (princ piece) (princ " "))
abc def gh


This only makes the loop and bindings.

;;; This eliminates chunk and takes variables for its bounds instead.
;;; and a var for the proseq.
;;; P.S. You may want to bind START to a temp.
(defmacro dochunk ((vseq proseq n vcstart vcend &key (start 0) end) &body body)
  (let ((len (gensym))
        (vend (gensym)))
    `(let* ((,vseq ,proseq)
            (,len (length ,vseq))
            (,vend (or ,end ,len)))
       (do ((,vcstart ,start ,vcend)
            (,vcend (min ,len ,n) (min (+ ,vcend ,n) ,len)))
           ((>= ,vcstart ,vend) (- ,vend ,start))
         ,@body))))

(DOCHUNK
  (str "abcdefgh" 3 start end)
  (princ (subseq str start end)) (princ " "))
? abc def gh 
8
?