A recent discussion here pointed me to Henry Baker's
paper on the META parser.
http://home.pipeline.com/~hbaker1/Prag-Parse.html
In it, he writes
(defun ctoi (d)
(- (char-code d) #.(char-code #\0)))
I do not understand what the "#." is doing there.
As I read the Hyperspec, (char-code) returns a
character code, which is just an integer. Correct?
Why does it need to be evaluated?
[I don't know if this is relevant, but I notice
that if I ask my Lisp to tell me the (function-lambda-
expression) of #'ctoi, I get
(LAMBDA (D) (BLOCK CTOI (- (CHAR-CODE D) 48)))
If I remove the "#.", the lambda expression is
(LAMBDA (D) (BLOCK CTOI-OTHER (- (CHAR-CODE D) (CHAR-CODE #\0))))
Is this intended as a mini-optimization?]
I'd appreciate any insight you can offer.
--
Mark Jeffcoat
Austin, TX
From: Christopher C. Stacy
Subject: Re: #. read macro in ctoi
Date:
Message-ID: <u8yv27oyy.fsf@dtpq.com>
>>>>> On Wed, 26 Mar 2003 03:50:38 -0000, Mark Jeffcoat ("Mark") writes:
Mark> A recent discussion here pointed me to Henry Baker's
Mark> paper on the META parser.
Mark> http://home.pipeline.com/~hbaker1/Prag-Parse.html
Mark> In it, he writes
Mark> (defun ctoi (d)
Mark> (- (char-code d) #.(char-code #\0)))
Mark> I do not understand what the "#." is doing there.
He wants to subtract a constant, and just writing the call to
CHAR-CODE would mean computing the constant every time the function
was called. Assuming that the compiler was not smart enough to notice
that this was a constant expression, he used the #. macro to ask that
the call be done at compile-time. This would make it obvious to the
compiler that it was a constant, and the compiler would be able to
inline that subtraction (maybe down to a single instruction).
Christopher C. Stacy <······@dtpq.com> wrote:
+---------------
| Mark Jeffcoat ("Mark") writes:
| Mark> (defun ctoi (d)
| Mark> (- (char-code d) #.(char-code #\0)))
| Mark> I do not understand what the "#." is doing there.
|
| He wants to subtract a constant, and just writing the call to
| CHAR-CODE would mean computing the constant every time the function
| was called. Assuming that the compiler was not smart enough to notice
| that this was a constant expression, he used the #. macro to ask that
| the call be done at compile-time.
+---------------
Oops! I'm sure this was just a slip o' the keyboard typo, Christopher,
but for Mark's sake we should be clear that that the evaluation is
occurring not at compile time but at *read* time, and thus is also
available in the REPL (as well as in interpreted code, if such a thing
exists in one's implementation):
> '(- (char-code d) #.(char-code #\0))
(- (CHAR-CODE D) 48)
>
Mark, see CLHS "2.4.8.6 Sharpsign Dot" <URL:http://www.lispworks.com/
reference/HyperSpec/Body/02_dhf.htm>.
-Rob
-----
Rob Warnock, PP-ASEL-IA <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
····@rpw3.org (Rob Warnock) writes:
> Christopher C. Stacy <······@dtpq.com> wrote:
> +---------------
> | Mark Jeffcoat ("Mark") writes:
> | Mark> (defun ctoi (d)
> | Mark> (- (char-code d) #.(char-code #\0)))
> | Mark> I do not understand what the "#." is doing there.
> |
> | He wants to subtract a constant, and just writing the call to
> | CHAR-CODE would mean computing the constant every time the function
> | was called. Assuming that the compiler was not smart enough to notice
> | that this was a constant expression, he used the #. macro to ask that
> | the call be done at compile-time.
> +---------------
>
> I'm sure this was just a slip o' the keyboard typo, Christopher, but
> for Mark's sake we should be clear that that the evaluation is
> occurring not at compile time but at *read* time
And if you REALLY want compile-time evalutation:
(defmacro compile-time-char-code (char)
(char-code char))
(defun ctoi (d)
(- (char-code d) (compile-time-char-code #\0)))
Rob Warnock <····@rpw3.org> wrote:
>
> Oops! I'm sure this was just a slip o' the keyboard typo, Christopher,
> but for Mark's sake we should be clear that that the evaluation is
> occurring not at compile time but at *read* time, and thus is also
> available in the REPL (as well as in interpreted code, if such a thing
> exists in one's implementation):
>
> > '(- (char-code d) #.(char-code #\0))
>
> (- (CHAR-CODE D) 48)
> >
>
> Mark, see CLHS "2.4.8.6 Sharpsign Dot" <URL:http://www.lispworks.com/
> reference/HyperSpec/Body/02_dhf.htm>.
>
I had seen, and went right through me the first time,
without sticking anywhere. I've got it now, though--
I definitely wasn't making a clear distinction between
read time and later execution. Thanks to everyone who
helped.
(Now, on to the next definition from the META paper,
which uses &aux arguments--another item not really
covered in _ANSI Common Lisp_. This is getting to be
more educational all the time. But Hyperspec can
save the day again...)
--
Mark Jeffcoat
Austin, TX
In article <··············@corp.supernews.com>,
Mark Jeffcoat <········@alumni.rice.edu> wrote:
>(Now, on to the next definition from the META paper,
>which uses &aux arguments--another item not really
>covered in _ANSI Common Lisp_. This is getting to be
>more educational all the time. But Hyperspec can
>save the day again...)
&AUX arguments can be considered just a shorthand for a LET* binding around
the body of the function, i.e.
(defun foo (<real args> &aux a (b <expr>) (c (+ b 1)))
<body>)
is equivalent to:
(defun foo (<real args>)
(let* (a
(b <expr>)
(c (+ b 1)))
<body>))
The only real purpose this serves is to save a level of indentation. Since
it doesn't fill an important niche, in my experience they're not heavily
used.
--
Barry Margolin, ··············@level3.com
Genuity Managed Services, 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.
Christopher C. Stacy wrote:
> (- (char-code d) #.(char-code #\0)))
>
> Mark> I do not understand what the "#." is doing there.
>
> He wants to subtract a constant, and just writing the call to
> CHAR-CODE would mean computing the constant every time the function
> was called.
load-time-value is another alternative to evaluation every time the
function is called. Depending on the compiler, it might or might
noe be as efficient as #., but it can handle constants that cannot be
computed until run time (actually, load time).