From: verec
Subject: macrolet abuse?
Date: 
Message-ID: <4786a511$0$509$5a6aecb4@news.aaisp.net.uk>
I'm parsing some html and found myself writing the same "tail"
code at the end of each case, and hence came up with a local
macro: ...

(defun extract-strike (&key (where *http-payload*) (start 0))
  (let ((strike '()))

    (macrolet ((push-result (result)
                 `(if offset
                      (progn
                        (setq start offset)
                        (push ,result strike))
                    (setq start nil))))

      ;; option symbol
      (when start
        (multiple-value-bind (offset symbol)
            (extract-embedded :symbol :where where :start start)
          (push-result symbol))) ;; <= uses/modifies: start, offset & strike

      ;; open-interest
      (when start
        ;; skip extra garbage
        (setq start (search-for "</td>" :where where :start start))
        (when start
          (multiple-value-bind (offset oi)
              (extract-embedded :value :where where :start start)
            (push-result oi)))) ;; <= uses/modifies: start, offset & strike

;;;
;;; 11 similar cases omitted
;;;
      )

    (nreverse strike)))

This works, but I have this strange feeling that I'm abusing
the intent of macrolet in this context, by daring "capturing"
variables from the enclosing lexical scope at the point of
macro instantiation.

What would be an alternate (and better !!) style ?

Many thanks
--
JFB

From: Maciej Katafiasz
Subject: Re: macrolet abuse?
Date: 
Message-ID: <6028b822-aa60-4e51-9c6f-e0a7ab8aba9d@h11g2000prf.googlegroups.com>
Den Thu, 10 Jan 2008 23:06:57 +0000 skrev verec:

> This works, but I have this strange feeling that I'm abusing the intent
> of macrolet in this context, by daring "capturing" variables from the
> enclosing lexical scope at the point of macro instantiation.
>
> What would be an alternate (and better !!) style ?

A closure. That macro doesn't seem to be doing anything impossible to
do with a closure. Just s/macrolet/flet/, and remove the backquote.

Cheers,
Maciej
From: Rainer Joswig
Subject: Re: macrolet abuse?
Date: 
Message-ID: <joswig-82C2E7.01010011012008@news-europe.giganews.com>
In article 
<····································@h11g2000prf.googlegroups.com>,
 Maciej Katafiasz <········@gmail.com> wrote:

> Den Thu, 10 Jan 2008 23:06:57 +0000 skrev verec:
> 
> > This works, but I have this strange feeling that I'm abusing the intent
> > of macrolet in this context, by daring "capturing" variables from the
> > enclosing lexical scope at the point of macro instantiation.
> >
> > What would be an alternate (and better !!) style ?
> 
> A closure. That macro doesn't seem to be doing anything impossible to
> do with a closure. Just s/macrolet/flet/, and remove the backquote.
> 
> Cheers,
> Maciej

A local function? A closure is something different.
From: Kaz Kylheku
Subject: Re: macrolet abuse?
Date: 
Message-ID: <2d28d8c9-af0a-4840-b4fe-f1126c655961@v29g2000hsf.googlegroups.com>
On Jan 10, 3:06 pm, verec <·····@mac.com> wrote:
> I'm parsing some html and found myself writing the same "tail"
> code at the end of each case, and hence came up with a local
> macro: ...
>
> (defun extract-strike (&key (where *http-payload*) (start 0))
>   (let ((strike '()))
>
>     (macrolet ((push-result (result)
>                  `(if offset
>                       (progn
>                         (setq start offset)
>                         (push ,result strike))
>                     (setq start nil))))

Unnecessary local macro. It doesn't evaluate its argument in any
special way, therefore this job can be done by a function:

  (flet ((push-result (result)
           (if offset
             (progn
               (setq start offset)
               (push result strike))
             (setq start nil))))
     ...

> This works, but I have this strange feeling that I'm abusing
> the intent of macrolet in this context, by daring "capturing"
> variables from the enclosing lexical scope at the point of
> macro instantiation.

The macro is indeed not referentially transparent, since the way it
makes references to surrounding lexical material is not immune against
interference.

The macrolet could be expanded in a nested context where there is
another offset, strike or start.

> What would be an alternate (and better !!) style ?

The function doesn't suffer from the problem; it's lexical references
go where they are supposed to.
From: verec
Subject: Re: macrolet abuse?
Date: 
Message-ID: <4786b26d$0$509$5a6aecb4@news.aaisp.net.uk>
On 2008-01-10 23:52:44 +0000, Kaz Kylheku <········@gmail.com> said:

> On Jan 10, 3:06 pm, verec <·····@mac.com> wrote:
>> I'm parsing some html and found myself writing the same "tail"
>> code at the end of each case, and hence came up with a local
>> macro: ...
>> 
>> (defun extract-strike (&key (where *http-payload*) (start 0))
>>   (let ((strike '()))
>> 
>>     (macrolet ((push-result (result)
>>                  `(if offset
>>                       (progn
>>                         (setq start offset)
>>                         (push ,result strike))
>>                     (setq start nil))))
> 
> Unnecessary local macro. It doesn't evaluate its argument in any
> special way, therefore this job can be done by a function:
> 
>   (flet ((push-result (result)
>            (if offset
>              (progn
>                (setq start offset)
>                (push result strike))
>              (setq start nil))))
>      ...

This nearly worked :-(

I must be missing something ... The above generates warnings:

;;;*** Warning in (subfunction push-result extract-strike): offset 
assumed special
;;;*** Warning in (subfunction push-result extract-strike): offset 
assumed special
;;;*** Warning in extract-strike: offset is bound but not referenced
;;;*** Warning in extract-strike: offset is bound but not referenced

[...]

;;;*** Warning in extract-strike: offset is bound but not referenced
;;;*** Warning in extract-strike: offset is bound but not referenced
; extract-strike
;;; Compilation finished with 17 warnings, 0 errors.

Obviously, offset doesn't exist until brought up to existence
by the multiple-value-bind ...

Puzzled again :(
--
JFB
From: Rainer Joswig
Subject: Re: macrolet abuse?
Date: 
Message-ID: <joswig-B8301C.01080311012008@news-europe.giganews.com>
In article <·······················@news.aaisp.net.uk>,
 verec <·····@mac.com> wrote:

> On 2008-01-10 23:52:44 +0000, Kaz Kylheku <········@gmail.com> said:
> 
> > On Jan 10, 3:06 pm, verec <·····@mac.com> wrote:
> >> I'm parsing some html and found myself writing the same "tail"
> >> code at the end of each case, and hence came up with a local
> >> macro: ...
> >> 
> >> (defun extract-strike (&key (where *http-payload*) (start 0))
> >>   (let ((strike '()))
> >> 
> >>     (macrolet ((push-result (result)
> >>                  `(if offset
> >>                       (progn
> >>                         (setq start offset)
> >>                         (push ,result strike))
> >>                     (setq start nil))))
> > 
> > Unnecessary local macro. It doesn't evaluate its argument in any
> > special way, therefore this job can be done by a function:
> > 
> >   (flet ((push-result (result)
> >            (if offset
> >              (progn
> >                (setq start offset)
> >                (push result strike))
> >              (setq start nil))))
> >      ...
> 
> This nearly worked :-(
> 
> I must be missing something ... The above generates warnings:
> 
> ;;;*** Warning in (subfunction push-result extract-strike): offset 
> assumed special
> ;;;*** Warning in (subfunction push-result extract-strike): offset 
> assumed special
> ;;;*** Warning in extract-strike: offset is bound but not referenced
> ;;;*** Warning in extract-strike: offset is bound but not referenced
> 
> [...]
> 
> ;;;*** Warning in extract-strike: offset is bound but not referenced
> ;;;*** Warning in extract-strike: offset is bound but not referenced
> ; extract-strike
> ;;; Compilation finished with 17 warnings, 0 errors.
> 
> Obviously, offset doesn't exist until brought up to existence
> by the multiple-value-bind ...
> 
> Puzzled again :(
> --
> JFB

Sure you need to see which variables are available
in the surrounding context. Those who are not you
need to add the the parameter list of the local
function.

strike comes from the top LET. offset is not there.
start comes from the parameter list of the top-level
function. 

so: (flet ((push-result (result offset) .... )

You need to call PUSH-RESULT then with two arguments.
From: verec
Subject: Re: macrolet abuse?
Date: 
Message-ID: <4786b9a8$0$514$5a6aecb4@news.aaisp.net.uk>
On 2008-01-11 00:08:03 +0000, Rainer Joswig <······@lisp.de> said:

> Sure you need to see which variables are available
> in the surrounding context. Those who are not you
> need to add the the parameter list of the local
> function.
> 
> strike comes from the top LET. offset is not there.
> start comes from the parameter list of the top-level
> function.
> 
> so: (flet ((push-result (result offset) .... )
> 
> You need to call PUSH-RESULT then with two arguments.

Thanks Rainer. Sorry for being so dense tonight. Must
be the end of the week or what? :-)

Now that you said it, this makes perfect sense!

Thanks again
--
JFB