From: Andy Chambers
Subject: How does the compiler decide that its ok to delete unused functions?
Date: 
Message-ID: <4a4e710d-fa5f-499b-a5d2-9d9c0670aadd@b29g2000hsa.googlegroups.com>
Hi folks,

(defmethod refs ((odm odm))
  (with-accessors ((doc doc)) odm
    (?let ((items `(// :|ItemRef|))
           (codelists `(// :|CodeListRef|))
           (groups `(// :|ItemGroupRef|))
           (forms `(// :|FormRef|))
           (events `(// :|StudyEventRef|)))
      (reduce (lambda (l1 l2)
                (union l1 l2))
              (mapcar (lambda (f)
                        (funcall f doc))
                      '(items codelists groups forms events))))))

I've created a macro that makes the ?let form above expand into a
labels form making items, codelists etc available as functions of one
arg.  A note from the compiler says that it deleted them during
macroexpansion, presumably because it thinks they're not being used.
This means that when funcall tries to call them, they don't exist.  I
can work around this but I'm interested in how the compiler decides
its ok to delete them.

--
Andy

From: Maciej Katafiasz
Subject: Re: How does the compiler decide that its ok to delete unused functions?
Date: 
Message-ID: <fpmgor$ktl$1@news.net.uni-c.dk>
Den Fri, 22 Feb 2008 03:16:07 -0800 skrev Andy Chambers:

> (defmethod refs ((odm odm))
>   (with-accessors ((doc doc)) odm
>     (?let ((items `(// :|ItemRef|))
>            (codelists `(// :|CodeListRef|))
>            (groups `(// :|ItemGroupRef|))
>            (forms `(// :|FormRef|))
>            (events `(// :|StudyEventRef|)))
>       (reduce (lambda (l1 l2)
>                 (union l1 l2))
>               (mapcar (lambda (f)
>                         (funcall f doc)))))))
> 
> I've created a macro that makes the ?let form above expand into a labels
> form making items, codelists etc available as functions of one arg.  A
> note from the compiler says that it deleted them during macroexpansion,
> presumably because it thinks they're not being used. This means that
> when funcall tries to call them, they don't exist.  I can work around
> this but I'm interested in how the compiler decides its ok to delete
> them.

The problem is not with the compiler, but with your code. LABELS creates 
local lexical functions, but with the code above, you're FUNCALLing 
symbols, which means accessing the (global) dynamic environment. That 
doesn't work. You can't access the lexical environment other than by 
forms textually enclosed by it. If you want to have function objects to 
call later, you want to expand ?LET to a series of LAMBDAs, not LABELs. 
Note also that in this case you wouldn't map over '(items codelists 
groups forms events) (which is a literal list of symbols), but (list 
items codelists groups forms events), as you're interested in the values 
they represent.

Cheers,
Maciej
From: Andy Chambers
Subject: Re: How does the compiler decide that its ok to delete unused 	functions?
Date: 
Message-ID: <37097077-589d-4693-ac92-e033684919da@j28g2000hsj.googlegroups.com>
On Feb 22, 12:55 pm, Maciej Katafiasz <········@gmail.com> wrote:
> Den Fri, 22 Feb 2008 03:16:07 -0800 skrev Andy Chambers:
>
>
>
> > (defmethod refs ((odm odm))
> >   (with-accessors ((doc doc)) odm
> >     (?let ((items `(// :|ItemRef|))
> >            (codelists `(// :|CodeListRef|))
> >            (groups `(// :|ItemGroupRef|))
> >            (forms `(// :|FormRef|))
> >            (events `(// :|StudyEventRef|)))
> >       (reduce (lambda (l1 l2)
> >                 (union l1 l2))
> >               (mapcar (lambda (f)
> >                         (funcall f doc)))))))
>
> > I've created a macro that makes the ?let form above expand into a labels
> > form making items, codelists etc available as functions of one arg.  A
> > note from the compiler says that it deleted them during macroexpansion,
> > presumably because it thinks they're not being used. This means that
> > when funcall tries to call them, they don't exist.  I can work around
> > this but I'm interested in how the compiler decides its ok to delete
> > them.
>
> The problem is not with the compiler, but with your code.

I didn't mean to imply that the compiler was wrong.  My experience
tells me that when something doesn't work the way I expect, its
because I don't understand it properly.

> You can't access the lexical environment other than by forms textually
> enclosed by it.

So that means if the functions defined by labels don't appear as the
operator in any of its sub-forms, they're safe to be deleted?

Cheers,
Andy
From: Rob Warnock
Subject: Re: How does the compiler decide that its ok to delete unused 	functions?
Date: 
Message-ID: <WYCdnR3IE42bSiPanZ2dnUVZ_ternZ2d@speakeasy.net>
Andy Chambers  <··············@googlemail.com> wrote:
+---------------
| Maciej Katafiasz <········@gmail.com> wrote:
| > skrev Andy Chambers:
| > > (defmethod refs ((odm odm))
| > >   (with-accessors ((doc doc)) odm
| > >     (?let ((items `(// :|ItemRef|))
| > >            (codelists `(// :|CodeListRef|))
| > >            (groups `(// :|ItemGroupRef|))
| > >            (forms `(// :|FormRef|))
| > >            (events `(// :|StudyEventRef|)))
| > >       (reduce (lambda (l1 l2)
| > >                 (union l1 l2))
| > >               (mapcar (lambda (f)
| > >                         (funcall f doc)))))))
| >
| > > I've created a macro that makes the ?let form above expand into a labels
| > > form making items, codelists etc available as functions of one arg. A
| > > note from the compiler says that it deleted them during macroexpansion,
| > > presumably because it thinks they're not being used. This means that
| > > when funcall tries to call them, they don't exist.  I can work around
| > > this but I'm interested in how the compiler decides its ok to delete
| > > them.
| >
| > The problem is not with the compiler, but with your code.
...
| > You can't access the lexical environment other than by forms textually
| > enclosed by it.
| 
| So that means if the functions defined by labels don't appear as the
| operator in any of its sub-forms, they're safe to be deleted?
+---------------

No, you can FUNCALL them, just not as *symbols*, which get the global
values. But you can use the FUNCTION special operator to access the
lexical functional values. That is, instead of (FUNCALL 'ITEMS ...) you
need to use (FUNCALL (FUNCTION ITEMS) ...) a.k.a. (FUNCALL #'ITEMS ...).

And you can even MAPCAR over them if you provide their *lexical* values,
e.g.:

    (mapcar (lambda (f) (funcall f doc))
	    (list #'items #'codelists #'groups #'forms #'events))


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Barry Margolin
Subject: Re: How does the compiler decide that its ok to delete unused functions?
Date: 
Message-ID: <barmar-4DE40C.08584522022008@comcast.dca.giganews.com>
In article 
<····································@j28g2000hsj.googlegroups.com>,
 Andy Chambers <··············@googlemail.com> wrote:

> So that means if the functions defined by labels don't appear as the
> operator in any of its sub-forms, they're safe to be deleted?

Or as the parameter to the FUNCTION special operator.  E.g. change your 
original code to:

              (mapcar (lambda (f)
                        (funcall f doc))
                      (list #'items #'codelists #'groups #'forms 
#'events))))))

and it won't remove the function definitions.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Kaz Kylheku
Subject: Re: How does the compiler decide that its ok to delete unused 	functions?
Date: 
Message-ID: <14d8c9e7-df2f-44c0-8860-e3e92c9c9fbf@z70g2000hsb.googlegroups.com>
On Feb 22, 5:43 am, Andy Chambers <··············@googlemail.com>
wrote:
> On Feb 22, 12:55 pm, Maciej Katafiasz <········@gmail.com> wrote:
>
>
>
> > Den Fri, 22 Feb 2008 03:16:07 -0800 skrev Andy Chambers:
>
> > > (defmethod refs ((odm odm))
> > >   (with-accessors ((doc doc)) odm
> > >     (?let ((items `(// :|ItemRef|))
> > >            (codelists `(// :|CodeListRef|))
> > >            (groups `(// :|ItemGroupRef|))
> > >            (forms `(// :|FormRef|))
> > >            (events `(// :|StudyEventRef|)))
> > >       (reduce (lambda (l1 l2)
> > >                 (union l1 l2))
> > >               (mapcar (lambda (f)
> > >                         (funcall f doc)))))))
>
> > > I've created a macro that makes the ?let form above expand into a labels
> > > form making items, codelists etc available as functions of one arg.  A
> > > note from the compiler says that it deleted them during macroexpansion,
> > > presumably because it thinks they're not being used. This means that
> > > when funcall tries to call them, they don't exist.  I can work around
> > > this but I'm interested in how the compiler decides its ok to delete
> > > them.
>
> > The problem is not with the compiler, but with your code.
>
> I didn't mean to imply that the compiler was wrong.  My experience
> tells me that when something doesn't work the way I expect, its
> because I don't understand it properly.
>
> > You can't access the lexical environment other than by forms textually
> > enclosed by it.
>
> So that means if the functions defined by labels don't appear as the
> operator in any of its sub-forms, they're safe to be deleted?

It's not because your functions are not called directly that they are
not used.  That is to say, it's not the operator application syntax
(FOO ...) which marks the function FOO as being used.

If the compiler can deduce that an object (or function, but I repeat
myself since functions are objects!) is not used, then no code needs
to be emitted which would instantiate that object.

The reason your local functions are not used is that there is no
reference to them whatsoever.

Which FOO is called in the following snippet?

  (defun foo () (format t "global foo~%"))

  (labels ((foo () (format t "local foo~%")))
    (funcall 'foo))

Is the local foo considered used? How about if you change it to:

  (labels ((foo () (format t "local foo~%")))
    (funcall #'foo))

Which one is called now? Is the local foo considered used?