From: Kenny Tilton
Subject: why am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <3F2FD238.2040709@nyc.rr.com>
Okay, I got started on tossing in the octothorpe because I simply did 
not know I could get away with just 'string=.

But now that I know, is there any reason to use #'string=? As in 
performance or other?

-- 

  kenny tilton
  clinisys, inc
  http://www.tilton-technology.com/
  ---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
                                                  -- Bob Uecker

From: JP Massar
Subject: Re: why am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <3f2fea22.165088059@netnews.comcast.net>
On Tue, 05 Aug 2003 15:52:48 GMT, Kenny Tilton <·······@nyc.rr.com>
wrote:

>Okay, I got started on tossing in the octothorpe because I simply did 
>not know I could get away with just 'string=.
>
>But now that I know, is there any reason to use #'string=? As in 
>performance or other?
>
 
Two reasons.

1.  Performance.  You save a dereference through the symbol's function
slot.

2.  Meaning.

(defun foo (x) (1- x))

(flet ((foo (x) (1+ x))) (funcall #'foo 5)) --> 6
(flet ((foo (x) (1- x))) (funcall 'foo 5)) --> 4
From: Scott L. Burson
Subject: Re: why am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <vivsc9pcpe8k45@news.supernews.com>
JP Massar wrote:

> Two reasons.
> 
> 1.  Performance.  You save a dereference through the symbol's function
> slot.
> 
> 2.  Meaning.
> 
> (defun foo (x) (1- x))
> 
> (flet ((foo (x) (1+ x))) (funcall #'foo 5)) --> 6
> (flet ((foo (x) (1- x))) (funcall 'foo 5)) --> 4

Agreed on both counts, but sometimes you want to dereference through the
function slot to see (global) redefinitions:

(defun foo (x) (1- x))

(defvar *foo* #'foo)

(defun foo (x) (1+ x))

(funcall *foo* 3) --> 2
(funcall 'foo 3) --> 4

The `defvar' has captured the definition of `foo' that existed at the time
it was evaluated.

-- Scott

-- 
To send email, remove uppercase characters from address in header.
From: Barry Margolin
Subject: Re: why am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <UzSXa.38$Mg5.31@news.level3.com>
In article <··············@news.supernews.com>,
Scott L. Burson <········@AsMympoiesis.com> wrote:
>Agreed on both counts, but sometimes you want to dereference through the
>function slot to see (global) redefinitions:

In fact, that's the very reason why we decided that FUNCALL and APPLY
must accept symbols as well as functions.

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, 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: Steven M. Haflich
Subject: Re: why am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <3F31379E.4000807@alum.mit.edu>
JP Massar wrote:

> 1.  Performance.  You save a dereference through the symbol's function
> slot.

This seems obvious but unfortunately happens to be wrong.

There is no reason that funcall of a symbol should be slower than funcall
of a function, if the implementation is clever about how it does things.
In fact, funcall of a symbol may be faster, since funcall can assume (at
compile time) that the object stored in the symbol-function slot is a
real function (although it may often be some particular "not-fbound"
signalling function) whereas (funcall (function foo) ...) may impose
some amount of error checking in the execution of the funcall special
operator.  Even if the compiler can assume that foo is fboundp (because
it was defined in the same file at compile time -- ANS 3.2.2.3) there
are still ways to predigest funcall through a symbol to make it
essentially equivalent to funcall of a function.  Lastly, the compiler
can often infer whether a particular call to funcall will receive a
function of a symbol, as the type can be inferred from the code.

> 2.  Meaning.
> 
> (defun foo (x) (1- x))
> 
> (flet ((foo (x) (1+ x))) (funcall #'foo 5)) --> 6
> (flet ((foo (x) (1- x))) (funcall 'foo 5)) --> 4

But remember that the original question concerned #'string.  Since
string is a fbound symbol in the cl package, it is not permitted to
establish any lexical function binding on it (ANS 11.1.2.1.2).  Of
course, the non-CL-package situation remains interesting.
From: Barry Margolin
Subject: Re: why am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <X0bYa.60$Mg5.25@news.level3.com>
In article <················@alum.mit.edu>,
Steven M. Haflich <·················@alum.mit.edu> wrote:
>JP Massar wrote:
>
>> 1.  Performance.  You save a dereference through the symbol's function
>> slot.
>
>This seems obvious but unfortunately happens to be wrong.
>
>There is no reason that funcall of a symbol should be slower than funcall
>of a function, if the implementation is clever about how it does things.
>In fact, funcall of a symbol may be faster, since funcall can assume (at
>compile time) that the object stored in the symbol-function slot is a
>real function (although it may often be some particular "not-fbound"
>signalling function) whereas (funcall (function foo) ...) may impose
>some amount of error checking in the execution of the funcall special
>operator.

I don't think there should be any performance difference between

(funcall 'foo ...)

and

(funcall #'foo ...)

They both have to indirect through the FOO symbol at run time.  (An
exception might be made if FOO is defined in the same compilation unit as
the call and it's not declared NOTINLINE -- the compiler could then resolve
the link at compilation time.)

But there would probably be a difference between

(setq *foo* 'foo)
...
(funcall *foo* ...)

and

(setq *foo* #'foo)
...
(funcall *foo* ...)

where the FUNCALL is done multiple times (e.g. in an inner loop).  The
first form has to indirect through the symbol every time, the second form
goes directly to the function.

I think we had a discussion about something related to this a while back.
Is it OK for the mapping functions to cache the function object, e.g.

(defun mapcar (function list1 &rest lists)
  (when (symbolp function)
    (setq function (symbol-function function)))
  ...)

This would affect the semantics if you pass a symbol as the function
argument and the function redefines itself.

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, 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: Paul Dietz
Subject: Re: why am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <3F314F61.8446459@motorola.com>
Barry Margolin wrote:

> I think we had a discussion about something related to this a while back.
> Is it OK for the mapping functions to cache the function object, e.g.
> 
> (defun mapcar (function list1 &rest lists)
>   (when (symbolp function)
>     (setq function (symbol-function function)))
>   ...)


Yes (see section 1.4.1.5).

	Paul
From: Steven M. Haflich
Subject: Re: |é±am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <3F314F2E.8090901@alum.mit.edu>
Barry Margolin wrote:

> where the FUNCALL is done multiple times (e.g. in an inner loop).  The
> first form has to indirect through the symbol every time, the second form
> goes directly to the function.

As before, we have a statement that makes intuitive sense, but is wrong.

In particular, it does not follow that to "indirect through the symbol"
must be added to the cost of "go[ing] directly to the function."  If an
implementation chooses, it could lay out symbol and function objects such
that funcalling would operate with the same instruction sequence (perhaps
at the cost of making setf symbol-function slightly more expensive) although
I suspect few implementations do this because of potential costs elsewhere
in the tagging design.

A more practical argument, then, is to consider that funcall probably must
discriminate on the type of argument, and that discrimination could code be
organized and optimized an any number of ways so as to be more or less
efficient for particular types, according to what the implementor believes
or determines are the more commonly occurring types.

It is tricky to measure these very-low-level things, by the way, because
cache issues and cache collision may make results unreliable.  Study by
disassembly and theoretical code analysis is much more tedious, but
might or might not be more reliable.
From: Barry Margolin
Subject: Re: |é±am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <DgcYa.70$Mg5.18@news.level3.com>
In article <················@alum.mit.edu>,
Steven M. Haflich <·················@alum.mit.edu> wrote:
>A more practical argument, then, is to consider that funcall probably must
>discriminate on the type of argument, and that discrimination could code be
>organized and optimized an any number of ways so as to be more or less
>efficient for particular types, according to what the implementor believes
>or determines are the more commonly occurring types.

Since recommended practice is to pass function objects whenever
appropriate, I'd expect implementors to optimize for that common case.

So while I agree that it's *possible* for funcalling symbols to be as fast
or faster than funcalling functions, I wouldn't expect it to be likely.  It
would require a convoluted design for little practical benefit.

-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, 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: Steven M. Haflich
Subject: Re: |é±am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <3F33C2E3.5070507@alum.mit.edu>
Barry Margolin wrote:

> Since recommended practice is to pass function objects whenever
> appropriate, I'd expect implementors to optimize for that common case.

Whose recommendations?  Surely there is no such recommendation in the ANS?

> So while I agree that it's *possible* for funcalling symbols to be as fast
> or faster than funcalling functions, I wouldn't expect it to be likely.  It
> would require a convoluted design for little practical benefit.

Your expectations are understandable but might not agree with experience based
on years and years of performance tuning with real implementations.  Here is
an actual test with a real implementation.  As I posted earlier, interpreting
timing results is tricky and unreliable, and further, requires knowledge about
what the compiler might or might not be optimizing away.  But in this case I
am confident that neither the call to indentity not the implied symbol-function
calls are being optimize away.

<6> (compile
      (defun test (x y)
        (declare (optimize (speed 3) (safety 0)))
        (time
	(dotimes (i 10000000)
	  (funcall x y)))))
test
nil
nil
<7> (test 'identity 'foo)
; cpu time (non-gc) 980 msec user, 0 msec system
; cpu time (gc)     0 msec user, 0 msec system
; cpu time (total)  980 msec user, 0 msec system
; real time  1,701 msec
; space allocation:
;  0 cons cells, 0 other bytes, 0 static bytes
nil
<8> (test #'identity 'foo)
; cpu time (non-gc) 1,200 msec user, 0 msec system
; cpu time (gc)     0 msec user, 0 msec system
; cpu time (total)  1,200 msec user, 0 msec system
; real time  2,154 msec
; space allocation:
;  0 cons cells, 0 other bytes, 0 static bytes
nil
From: Paul Dietz
Subject: Re: |é±am i always typing #'string= instead of 	'string=?
Date: 
Message-ID: <3F33D216.CE7841DB@motorola.com>
"Steven M. Haflich" wrote:

> <6> (compile
>       (defun test (x y)
>         (declare (optimize (speed 3) (safety 0)))
>         (time
>         (dotimes (i 10000000)
>           (funcall x y)))))
> test
> nil
> nil
> <7> (test 'identity 'foo)
> ; cpu time (non-gc) 980 msec user, 0 msec system
> ; cpu time (gc)     0 msec user, 0 msec system
> ; cpu time (total)  980 msec user, 0 msec system
> ; real time  1,701 msec
> ; space allocation:
> ;  0 cons cells, 0 other bytes, 0 static bytes
> nil
> <8> (test #'identity 'foo)
> ; cpu time (non-gc) 1,200 msec user, 0 msec system
> ; cpu time (gc)     0 msec user, 0 msec system
> ; cpu time (total)  1,200 msec user, 0 msec system
> ; real time  2,154 msec
> ; space allocation:
> ;  0 cons cells, 0 other bytes, 0 static bytes
> nil


Also try with (declare (type function x))
(or (declare (type excl::known-function x) in ACL).

	Paul
From: Barry Margolin
Subject: Re: |é±am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <gXPYa.47$7R.42@news.level3.com>
In article <················@alum.mit.edu>,
Steven M. Haflich <·················@alum.mit.edu> wrote:
>Barry Margolin wrote:
>
>> Since recommended practice is to pass function objects whenever
>> appropriate, I'd expect implementors to optimize for that common case.
>
>Whose recommendations?  Surely there is no such recommendation in the ANS?

Recommendations of experienced Lisp programmers -- that's how new
programmers learn common idioms.  E.g. most of us, in our example code in
the newsgroup, use #' when appropriate.

>> So while I agree that it's *possible* for funcalling symbols to be as fast
>> or faster than funcalling functions, I wouldn't expect it to be likely.  It
>> would require a convoluted design for little practical benefit.
>
>Your expectations are understandable but might not agree with experience based
>on years and years of performance tuning with real implementations.  Here is
>an actual test with a real implementation.  As I posted earlier, interpreting
>timing results is tricky and unreliable, and further, requires knowledge about
>what the compiler might or might not be optimizing away.  But in this case I
>am confident that neither the call to indentity not the implied symbol-function
>calls are being optimize away.

Is this an implementation whose internals you're familiar with, so you can
explain why and how it's optimized this way?

>
><6> (compile
>      (defun test (x y)
>        (declare (optimize (speed 3) (safety 0)))
>        (time
>	(dotimes (i 10000000)
>	  (funcall x y)))))
>test
>nil
>nil
><7> (test 'identity 'foo)
>; cpu time (non-gc) 980 msec user, 0 msec system
>; cpu time (gc)     0 msec user, 0 msec system
>; cpu time (total)  980 msec user, 0 msec system
>; real time  1,701 msec
>; space allocation:
>;  0 cons cells, 0 other bytes, 0 static bytes
>nil
><8> (test #'identity 'foo)
>; cpu time (non-gc) 1,200 msec user, 0 msec system
>; cpu time (gc)     0 msec user, 0 msec system
>; cpu time (total)  1,200 msec user, 0 msec system
>; real time  2,154 msec
>; space allocation:
>;  0 cons cells, 0 other bytes, 0 static bytes
>nil
>
>


-- 
Barry Margolin, ··············@level3.com
Level(3), Woburn, 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: Duane Rettig
Subject: Re: |é±am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <4y8y42app.fsf@beta.franz.com>
Barry Margolin <··············@level3.com> writes:

> In article <················@alum.mit.edu>,
> Steven M. Haflich <·················@alum.mit.edu> wrote:
> >Barry Margolin wrote:
> >
> >> Since recommended practice is to pass function objects whenever
> >> appropriate, I'd expect implementors to optimize for that common case.
> >
> >Whose recommendations?  Surely there is no such recommendation in the ANS?
> 
> Recommendations of experienced Lisp programmers -- that's how new
> programmers learn common idioms.  E.g. most of us, in our example code in
> the newsgroup, use #' when appropriate.

When appropriate.  That means also, subtlely, that the global definition might
be desired, and that would lead to usage of the symbol rather than the function
form.

> >> So while I agree that it's *possible* for funcalling symbols to be as fast
> >> or faster than funcalling functions, I wouldn't expect it to be likely.  It
> >> would require a convoluted design for little practical benefit.

This is not necessarily true.  See below.

> >Your expectations are understandable but might not agree with experience based
> >on years and years of performance tuning with real implementations.  Here is
> >an actual test with a real implementation.  As I posted earlier, interpreting
> >timing results is tricky and unreliable, and further, requires knowledge about
> >what the compiler might or might not be optimizing away.  But in this case I
> >am confident that neither the call to indentity not the implied symbol-function
> >calls are being optimize away.
> 
> Is this an implementation whose internals you're familiar with, so you can
> explain why and how it's optimized this way?

The example Steve showed is simply an artifact of decision-making order in
a medium-optimization setting (yes, he did set speed to 3 and safety to 0,
but he didn't also mention whether the function called was a known-function,
as Paul Dietz mentioned in another response, or in fact a symbol, either of
which would yield more highly optiomized code to start with).  Incidentally,
I had switched this to yield more intuitive timings a while ago in my
development version of Allegro CL.  If you really want speed, though, the
way to go is to state your intentions with declarations.

It is important, however, not to lose sight of Steve's point; which is
that you can't necessarily make the assumption that calling through the
symbol is going to be slower than calling through the function object.
As an example, when I did the Cray X-MP port in the late 1980s, the steadfast
rule of programming on the Cray was "never read from memory and never jump".
This rule was obviously a joke, but much less so than one might think;
reads from memory took on the order of 15 insruction cycles, and jumps took
23 (these numbers are probably wrong they are from memory - the Y-MP and the
Cray-2 were even worse; one operation was somewhere in the neighborhood
of 57 cycles to complete).

So the design of getting the symbol out of a context, accessing it for
the function object, and then accessing the function object for the
code start, was ludicrous, because it was at least three, perhaps four,
interlocking memory reads.  This was death on the Cray.

To fix this, I designed symbols so that they could be held to a
specific address (a real trick on a generational gc) and in addition
added a copy of the start address in the symbol itself.  Thus, the
address of the symbol could be built with an immediate constant in the
instruction stream, and the start address and the function object could
be loaded into their respective registers in parallel (the Cray did things
well in parallel, including at least two noninterlocking reads at a time).
So the only interlock was between the time of the read form the symbol to
the time the jump address could be jumped to.  This in contrast to funcalling
a function object, whose address had to be obtained from somewhere.  If that
address generation was from an actual function call, no temporary storage
into memory was needed, but if the address had to be saved, as in:

 (let ((x #'foo))
   (bar)
   (funcall x))

then the funcall would have been _slower_ than if the symbol had
simply been funcalled:

 (let ()
   (bar)
   (funcall 'foo))

The point is precisely that benchmarking is truly a black art, and
the most experienced of us (including me, on my own product) are
sometimes surprised by results that are not intuitive at first.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Nils Goesche
Subject: Re: why am i always typing #'string= instead of 'string=?
Date: 
Message-ID: <lyznioay36.fsf@cartan.de>
Kenny Tilton <·······@nyc.rr.com> writes:

> Okay, I got started on tossing in the octothorpe because I simply did
> not know I could get away with just 'string=.
> 
> But now that I know, is there any reason to use #'string=? As in
> performance or other?

#'foo is the natural thing to use.  You normally want to pass a
function object, not a function name.  #'foo also works in

(defun bar (x)
  (flet ((foo (y)
           (baz y x)))
    (blark #'foo)))

(blark 'foo) would refer to the /global/ FOO, if there is one.

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0