Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

General Lisp questions...

17 views
Skip to first unread message

David Bakhash

unread,
May 1, 1998, 3:00:00 AM5/1/98
to

here are some things that I couldn't gather from Steele's book:

1) temporarily, let's forget about macrolet. Suppose I have a function
in which I'd like to define a local function (with `flet' or with
`labels'). And also, suppose that I want that function to be inlined
inside the main function. So it looks like this:


(defun test ()
(declaim (inline f)) ;; #### does the declaim line belong here??? ####
(flet ((f (x)
(declaim (inline f) ;; #### or does it belong here??? ####
(* x x))))
(blah...)
(+ (f 2) (f 3))))

so I want to know where the declaration *should* go so that the function
is inlined.

2) can someone explain the difference between `labels' and `flet' ? I
can't understand it :-(

3) in Allegro CL, after you've verified that your program is really
clean and bug-free, you compile it with all the best compiler
options. then you get a .fasl file which you can load at an time,
and you can run a program that way. But is that the fastest way? is
there a way to turn your program into a binary executable that will
run even faster?

dave

Lyman S. Taylor

unread,
May 1, 1998, 3:00:00 AM5/1/98
to

In article <6id1qg$d...@senator-bedfellow.MIT.EDU>,

David Bakhash <ca...@mit.edu> wrote:
>here are some things that I couldn't gather from Steele's book:
>
>1) temporarily, let's forget about macrolet. Suppose I have a function
...

>(defun test ()
> (declaim (inline f)) ;; #### does the declaim line belong here??? ####
^^^^^^^^^^^^^^^^^^^
How about
(declare (inline f))

A declare at the beginning of a body effects that body. So to inline
into the body of test you'd wish to say it here.
Not that Lisp really "has to" do it. The environment can ignore
you at its discretion.

However, F hasn't been defined yet..... so this probably isn't a
good place to put this declaration...

> (flet ((f (x)
> (declaim (inline f) ;; #### or does it belong here??? ####

^^^^^^^^^^^^^^^^^^^

Again DECLARE. DECLAIM/PROCLAIM to effect the global environment
(and generally used outside the body of functions et. al. ).
DECLARE to effect the body of a function/let/etc.
The declaration would only effect the body of F. Not where F is
utilized.


The closest body to the place where you wish to inline is that of the
FLET. That would be where you would want to put the inline declaration.

(flet ( (f ()
... ) )
(declare (inline f ))
..... )

As mentioned above... the environment doesn't "have to" inline.

However, .....

>
>2) can someone explain the difference between `labels' and `flet' ? I
> can't understand it :-(

You can't write recursive FLET's. The functions defined by the
beginning of an FLET can only be seen in the body of the FLET

(flet ( ... fcn defs .... )
... flet's body.. )

Whereas the functions defined by the beginning of a LABELS can be
seen both in the body and in definitions part...

Examples:

(flet ( (f (x) (g (1+ x )) )
(g (x) (* x 10)) )

(f 10))

Or even

(flet ( (f (x) (cond ((= x 0 ) 'all-done)
( t (f (1- x ))))) )
(f 10 ) )

Will "die" a horrible death. The function F knows nothing of the
function g or of itself. Where:

(labels ( (f (x) (g (1+ x )) )
(g (x) (* x 10)) )

(f 10))

works.


In some sense, FLET and LABELS are to functions what LET and LET*
are to local variables. It isn't a precise analogy but close.


>3) in Allegro CL, after you've verified that your program is really
> clean and bug-free, you compile it with all the best compiler

....


> there a way to turn your program into a binary executable that will
> run even faster?

Compiling turns your Lisp code into "native binary". Things don't
get any faster than that. :-) It is just as "native" as the output
of a C/C++ compiler.

You can peek under the hood...

(disassemble #'car ) ;; or one of your compiled functions...

should reveal the associated opcodes for your processor if compiled.


Somewhat related to the above question...
You can develop (with the proper tools) as standalone application that
doesn't return you to "start up" the lisp environment to run. You can
forego the startup overhead of the development environment and it would
be faster from start to finish ( for instance, if you developed some filter
that read some data, transformed it, and then quit). But besides the
development environment start up /close down overhead.... your code would
execute no faster.




--

Lyman S. Taylor "There is something unexplainable here, Scully,
(ly...@cc.gatech.edu) but it is certainly not unidentifiable."
Fox Mulder - X-Files


Erik Naggum

unread,
May 1, 1998, 3:00:00 AM5/1/98
to

* David Bakhash

| here are some things that I couldn't gather from Steele's book:

you'll doubtless get numerous answers, so I'll try a shot, too...

| 1) temporarily, let's forget about macrolet. Suppose I have a function

| in which I'd like to define a local function (with `flet' or with
| `labels'). And also, suppose that I want that function to be inlined
| inside the main function. So it looks like this:

the first question that occurs to me is "why do you want to inline it?"
the second question is "why do you think you have tell the compiler so
explicitly?"

| so I want to know where the declaration *should* go so that the function
| is inlined.

evaluate (EXPLAIN-COMPILER-SETTINGS), as suggested when you start Allegro
and in the User Guide. the optimization setting affecting whether to try
and _automatically_ inline function calls is

;; COMPILER:GENERATE-INLINE-CALL-TESTS-SWITCH T

this is actually a variable, whose values is

#<Function SPEED >= SPACE @ #x2683e2>

indicating that if your optimization declarations satisfy this condition,
the compiler will try to inline calls. you can learn more about this:

(DECLAIM (:EXPLAIN :CALLS))

will tell you about each call the compiler has to generate code for.
(note: it quickly gets verbose.)

| 2) can someone explain the difference between `labels' and `flet' ? I
| can't understand it :-(

the scope of an FLET function binding is the _body_ of the FLET form.
the scope of a LABELS function binding is the _whole_ LABELS form.

| 3) in Allegro CL, after you've verified that your program is really
| clean and bug-free, you compile it with all the best compiler

| options. then you get a .fasl file which you can load at an time,
| and you can run a program that way. But is that the fastest way? is

| there a way to turn your program into a binary executable that will
| run even faster?

when finalizing some software for packaging as a product, you build an
image that is essentially a stand-alone program just like the Allegro CL
image is. you will replace the top-level loop with your own, and will
probably not have the editor interface and all that included. building
such images can save you a lot of size, but probably not much in speed.

#:Erik
--
Support organized crime: use Microsoft products!

Paul Dietz

unread,
May 1, 1998, 3:00:00 AM5/1/98
to

Sam Steingold wrote:

> >> there a way to turn your program into a binary executable that will
> >> run even faster?
>

> Only if you purchased a full commercial version (the free Linux version
> doesn't do that, unfortunately).

Sure it does. Perhaps you are confusing it with Allegro CL for Windows?

Paul
(eagerly awaiting ACL 5.0, and hoping they'll
release it for Linux as well)

---

;; Here's an example, using this file:

(defun counter (n)
(declare (fixnum n))
(let ((x 0))
(declare (fixnum x))
(loop
for i from 1 to n do
(incf x i))
x))

USER(7): :ld test.lsp
; Loading ./test.lsp
USER(8): (time (counter 10000))
; cpu time (non-gc) 3,080 msec user, 30 msec system
; cpu time (gc) 320 msec user, 20 msec system
; cpu time (total) 3,400 msec user, 50 msec system
; real time 3,760 msec
; space allocation:
; 320,163 cons cells, 1 symbol, 880,168 other bytes
50005000
USER(9): :cf test.lsp
;;; Compiling file test.lsp
; Compiling COUNTER
Warning: COUNTER, :OPERATOR was defined in ./test.lsp and is now being
defined
in test.lsp
;;; Writing fasl file test.fasl
Warning: No IN-PACKAGE form seen in test.lsp. (Allegro Presto will be
ineffective when loading a file having no IN-PACKAGE form.)
;;; Fasl write complete
USER(10): :ld test.fasl
; Fast loading ./test.fasl
Warning: COUNTER, :OPERATOR was defined in ./test.lsp and is now being
defined
in test.lsp
USER(11): (time (counter 10000))
; cpu time (non-gc) 10 msec user, 0 msec system
; cpu time (gc) 0 msec user, 0 msec system
; cpu time (total) 10 msec user, 0 msec system
; real time 4 msec
; space allocation:
; 1 cons cell, 0 symbols, 32 other bytes
50005000
USER(12):

Rainer Joswig

unread,
May 2, 1998, 3:00:00 AM5/2/98
to

>> there a way to turn your program into a binary executable that will
>> run even faster?
>

> Compiling turns your Lisp code into "native binary". Things don't
> get any faster than that. :-) It is just as "native" as the output
> of a C/C++ compiler.


Some compilers can do more if they are compiling one or more modules
as a whole. I think CMU CL has such a mode. Lucid CL maybe?


Raymond Wiker

unread,
May 2, 1998, 3:00:00 AM5/2/98
to

Sam Steingold <s...@usa.net> writes:
> 3. I use
>
> (defmacro sqr (xx)
> "Compute the square of a number, taking care to eval only once."
> (if (atom xx) `(* ,xx ,xx)
> (let ((var (gensym "SQR"))) `(let ((,var ,xx)) (* ,var ,var)))))

Ummm. Doesn't this evaluate xx twice for the case when xx is
not an atom?

//Raymond.

Lyman S. Taylor

unread,
May 2, 1998, 3:00:00 AM5/2/98
to

In article <hckg1is...@eto.ericsson.se>,

Raymond Wiker <eto...@eto.ericsson.se> wrote:
>Sam Steingold <s...@usa.net> writes:
>> 3. I use
...
>> (defmacro sqr (xx)
....

> Ummm. Doesn't this evaluate xx twice for the case when xx is
> not an atom?

No.

> (defmacro sqr (xx)

(if (atom xx) `(* ,xx ,xx )
(let ((var (gensym "SQR"))) `(let ((,var ,xx)) (* ,var ,var)))))

SQR

> (pprint (macroexpand-1 '(sqr (foo (/ 3 2 )))))

(LET ((#:SQR1 (FOO (/ 3 2)))) (* #:SQR1 #:SQR1))


The temporary variable will be evaluated twice when this LET is
evaluated. But that isn't the original expression (which may
have associated side effects, which is evaluated once).
Evaluating a variable has no side effects.


--

Lyman S. Taylor "Twinkie Cream; food of the Gods"
(ly...@cc.gatech.edu) Jarod, "The Pretender"


Rainer Joswig

unread,
May 2, 1998, 3:00:00 AM5/2/98
to

Kent M Pitman

unread,
May 3, 1998, 3:00:00 AM5/3/98
to

ly...@cc.gatech.edu (Lyman S. Taylor) writes:

> > (defmacro sqr (xx)
> (if (atom xx) `(* ,xx ,xx )
> (let ((var (gensym "SQR"))) `(let ((,var ,xx)) (* ,var ,var)))))
> SQR
>
> > (pprint (macroexpand-1 '(sqr (foo (/ 3 2 )))))
>
> (LET ((#:SQR1 (FOO (/ 3 2)))) (* #:SQR1 #:SQR1))
>
>
> The temporary variable will be evaluated twice when this LET is
> evaluated. But that isn't the original expression (which may
> have associated side effects, which is evaluated once).
> Evaluating a variable has no side effects.
>

Although I've used this trick myself from time to time out of
laziness, it's worth noting (just so you know) this is not correct
and should not be used in code you export to other people who might
not have the same understanding of "typical CL code" as you. In
particular, if you personally never use symbol macros, you personally
won't be harmed (much) by the atom test.

But it is in principle possible for (atom x) to be true of a symbol-macro
x and it is (though I think very bad style) in principle possible for
such a symbol-macro to have a side-effect, or at least to create a difference
in value. e.g., consider a variable TEMPERATURE which literally reads the
outdoor temperature and note that
(SQR TEMPERATURE)
might actually return a number that is not a perfect square as the
temperature changes from 30 to 31 and the result is 930. This could
be confusing at least.

Lyman S. Taylor

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

In article <sfwbttf...@world.std.com>,

Kent M Pitman <pit...@world.std.com> wrote:
>ly...@cc.gatech.edu (Lyman S. Taylor) writes:
>
>> > (defmacro sqr (xx)
>> (if (atom xx) `(* ,xx ,xx )
>> (let ((var (gensym "SQR"))) `(let ((,var ,xx)) (* ,var ,var)))))
....

>
>Although I've used this trick myself from time to time out of
>laziness,

Personally, I rarely use macros to do inlining. That's what the
inlining directives are for. :-)

It would seem that a reasonable compiler would manage not to add
too much overhead if the LET was always used. That renders the
symbol macro "problem" moot. [ Not that I'd ever seen one before...***]

What's that Knuth quote... :-)

"Premature optimization is the root of all evil ... "

*** Are symbol macros new to ANSI CL?? I can't seem to find anything in
CLtL2. Of course it could be in there somewhere... just hard to
find. Seems like a weird concept to bind general expressions
to a symbol... which makes landmines like the one mentioned
here...

Lyman S. Taylor

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

In article <6ijjnj$b...@pravda.cc.gatech.edu>,

Lyman S. Taylor <ly...@cc.gatech.edu> wrote:
...
>*** Are symbol macros new to ANSI CL?? I can't seem to find anything in
> CLtL2. Of course it could be in there somewhere...

Ooops, I was looking for DEFINE-SYMBOL-MACRO which seems to postdate
CLtL2. Eventually, I found my copy of "On Lisp" which put me onto the right
track of SYMBOL-MACROLET.

Erik Naggum

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

* Lyman S. Taylor

| Are symbol macros new to ANSI CL?? I can't seem to find anything in
| CLtL2.

why look in CLtL2 if you want to find out about ANSI X3.226-1994?
see http://www.harlequin.com/books/HyperSpec/ for the Real Thingน.

#:Erik
-------
น modulo the ability to use it as a legal reference document

eric dahlman

unread,
May 4, 1998, 3:00:00 AM5/4/98
to

Sam Steingold <s...@usa.net> writes:

> >>>> In message <354A628F...@interaccess.com>
> >>>> Sent on Fri, 01 May 1998 19:02:23 -0500
> >>>> Honorable Paul Dietz <di...@interaccess.com> writes
> >>>> on the subject of "Re: General Lisp questions...":


> >> Sam Steingold wrote:
> >>
> >> > >> there a way to turn your program into a binary executable that will
> >> > >> run even faster?
> >> >

> >> > Only if you purchased a full commercial version (the free Linux version
> >> > doesn't do that, unfortunately).
> >>
> >> Sure it does. Perhaps you are confusing it with Allegro CL for Windows?
>

> please re-read my message.
> I was talking about **stand-alone executables**, **NOT** compilation.

Well it can do this because excl:dumplisp is there and works
fine. This results is a stand alone binary executable. If you don't
want it to look like lisp to your users then just make sure that your
application's top level is started. The gory details of this are
described in section 8.3 of the manual.

Have fun,

-Eric "Don't tell the EPA I've dumped lisp in the past." Dahlman

>
> --
> Sam Steingold, running RedHat5 GNU/Linux (http://www.linux.org)
> Micros**t is not the answer. Micros**t is a question, and the answer is Linux,
> the choice of the GNU (http://www.gnu.org) generation.
> Only a fool has no doubts.

0 new messages