From: David Bakhash
Subject: General Lisp questions...
Date: 
Message-ID: <6id1qg$dee@senator-bedfellow.MIT.EDU>
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

From: Lyman S. Taylor
Subject: Re: General Lisp questions...
Date: 
Message-ID: <6id9nr$nb3@pravda.cc.gatech.edu>
In article <··········@senator-bedfellow.MIT.EDU>,
David Bakhash  <·····@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,
(·····@cc.gatech.edu)           but it is certainly not unidentifiable."
						Fox Mulder - X-Files
From: Rainer Joswig
Subject: Re: General Lisp questions...
Date: 
Message-ID: <6ifmci$jaj@desire.lavielle.com>
>>   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?
From: Rainer Joswig
Subject: Re: General Lisp questions...
Date: 
Message-ID: <6il6ru$2l0@desire.lavielle.com>
>>   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?
From: Erik Naggum
Subject: Re: General Lisp questions...
Date: 
Message-ID: <3103054423888634@naggum.no>
* 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!
From: Paul Dietz
Subject: Re: General Lisp questions...
Date: 
Message-ID: <354A628F.98A154DC@interaccess.com>
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):
From: eric dahlman
Subject: Re: General Lisp questions...
Date: 
Message-ID: <tz4wwc2ey1w.fsf@bbking.cs.colostate.edu>
Sam Steingold <···@usa.net> writes:

> >>>> In message <·················@interaccess.com>
> >>>> Sent on Fri, 01 May 1998 19:02:23 -0500
> >>>> Honorable Paul Dietz <·····@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.
From: Raymond Wiker
Subject: Re: General Lisp questions...
Date: 
Message-ID: <hckg1ispfmy.fsf@eto.ericsson.se>
Sam Steingold <···@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.
From: Lyman S. Taylor
Subject: Re: General Lisp questions...
Date: 
Message-ID: <6igkh3$3ok@pravda.cc.gatech.edu>
In article <···············@eto.ericsson.se>,
Raymond Wiker  <······@eto.ericsson.se> wrote:
>Sam Steingold <···@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" 
(·····@cc.gatech.edu)                     Jarod, "The Pretender" 
From: Kent M Pitman
Subject: Re: General Lisp questions...
Date: 
Message-ID: <sfwbttfkera.fsf@world.std.com>
·····@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.  
From: Lyman S. Taylor
Subject: Re: General Lisp questions...
Date: 
Message-ID: <6ijjnj$bro@pravda.cc.gatech.edu>
In article <···············@world.std.com>,
Kent M Pitman  <······@world.std.com> wrote:
>·····@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                "Twinkie Cream; food of the Gods" 
(·····@cc.gatech.edu)                     Jarod, "The Pretender" 
From: Lyman S. Taylor
Subject: Re: General Lisp questions...
Date: 
Message-ID: <6ijq8g$g25@pravda.cc.gatech.edu>
In article <··········@pravda.cc.gatech.edu>,
Lyman S. Taylor <·····@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.
-- 
					
Lyman S. Taylor                "Twinkie Cream; food of the Gods" 
(·····@cc.gatech.edu)                     Jarod, "The Pretender" 
From: Erik Naggum
Subject: Re: General Lisp questions...
Date: 
Message-ID: <3103263213000288@naggum.no>
* 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
-- 
  Support organized crime: use Microsoft products!