TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: curmudgeon on July 15, 2009, 11:49:05 AM

Title: when to defun
Post by: curmudgeon on July 15, 2009, 11:49:05 AM
this is REAL basic, but I don't know that I ever really thought about it.

I have a routine I am writing brute force, it runs.
now I come to the place where I want to do some defun ing for economy, and just nicer code.

I have, in the past, placed my defuns at the beginning of the file, and I have at other times put them at the end. I don't see why they couldn't be in the middle, if there were a reason. like maybe they are only needed in response to a particular condition.

I think I will end up putting them at the beginning, but that is likely just habit.
is it a good habit?

thanks

by the by, gile....

I downloaded your routine that does total areas - because I was betting I would learn something.
I REALLY appreciate the way you did your DCL coding in line - in the lsp file. dialog boxes and I have not gotten on so very well in the past, but I have my first one written. not in line yet,
but running thanks.
Title: Re: when to defun
Post by: CAB on July 15, 2009, 12:20:53 PM
The short answer.

Code: [Select]
;;  Global Sub Functions loaded when you load the Main LIsp
;;  Example One
(defun subFunction()
)
(defun c:MainRoutine()
  <code to acomplish the task>
)

Code: [Select]
;;  Global Sub Functions
;;  Example Two
(defun c:MainRoutine()
  <code to acomplish the task>
)
(defun subFunction()
)

Code: [Select]
;;  Global Sub Functions
;;  Example Three   **
;;  Note that the subFunctions are not defined until the lisp is run
(defun c:MainRoutine()
  (defun subFunction()
  )
  <code to acomplish the task>
)

Code: [Select]
;;  Global Sub Functions
;;  Example Four   **
;;  Note that the subFunctions will not be found as they are not loaded in time
(defun c:MainRoutine()
  <code to acomplish the task>
  (defun subFunction()
  )
)


Code: [Select]
;;  Local Sub Functions
;;  Example Five   **
;;  Note that the subFunctions must be before the Main Code
(defun c:MainRoutine( / subFunction)
  (defun subFunction()
  )
  <code to acomplish the task>
)
Title: Re: when to defun
Post by: Lee Mac on July 15, 2009, 12:23:26 PM
Great reply Alan, I have learnt a lot from it too  8-)
Title: Re: when to defun
Post by: GDF on July 15, 2009, 12:42:00 PM
I use subfunctions loaded at startup so that different routines can share. This way I can keep up with only one set of subfunctions. The draw back is that this collections of subfunctions always has to be loaded for the main routine to work.

I also do the same with my dialog box routines, by using AutoCAD's @include that way I only have one set of widgets to edit that multiple dialog boxes use.

//To load master widgets used by Arch Program© for AutoCAD®
@include "..\\ARCH.dcl"
Title: Re: when to defun
Post by: JohnK on July 15, 2009, 12:47:01 PM
The long answer:
There is a lot more to consider then just the position in the lisp file.

Yes placing them outside the main function and atop the file is a good habit 90% of the time. The other 10% that method will still be a good-enough method anyways (most likely only 10% of the lispers out there will be able to recognize when you `could have used an alternate method' to help optimize etc. instead anyways so...).

If you want to read up on this (I recommend you do) do a post search for "Refine your methods; Building named abstractions" by me.
Title: Re: when to defun
Post by: curmudgeon on July 15, 2009, 01:54:50 PM
thanks Alan.
I will get to that post 7.

Example 3 is my usual method, but I really like Example 1.

but I cannot play further until I crank out a roof plan - includes a couple of nasty 10 sided "towers" that intersect several different adjacent roof planes in a most inconvenient way. time for a little primitive 3d.

cheers.
 :-)
Title: Re: when to defun
Post by: gile on July 15, 2009, 01:57:58 PM
by the by, gile....

I downloaded your routine that does total areas - because I was betting I would learn something.
I REALLY appreciate the way you did your DCL coding in line - in the lsp file. dialog boxes and I have not gotten on so very well in the past, but I have my first one written. not in line yet,
but running thanks.

Thanks.

Writing DCL 'on the fly' may be a nice way for small dialog boxes because it avoid having two or more files to load.
But I think the most intersting is that you can build differently the dialog box according to datas got whithin the LISP file.
In this routine (http://www.theswamp.org/index.php?topic=23944.0) the dialog box is written after the user have selected a dynamic bloc, so that, it displays only the selected bloc dynamic properties.

About sub routines, the first choice I do is: external or internal defun ?
While sub routines are specific to the main one I use internal defun an always put the defun in the begining (before it's called in the main function) and declare them local (example 5).
For other sub routines which may be used by others functions, on my own, I keep them in libraries automaticaly loaded, and when I post them in forums I add them indiferently at them begining or at the end (examples 1 and 2)...

...when I don't forget to join them  :-D
Title: Re: when to defun
Post by: JohnK on July 15, 2009, 10:11:29 PM
the practice of nesting functions has more to it then where you place the `defun' or if you localize the function or not. to give one example, you can follow several different models for accessing and altering data (the use of free or bound variables) --i discuss this example in my write up i talked about-.

Code: [Select]
;;  local sub functions
;;  example five a   **
;;  note that the subfunctions must be before the main code

(defun c:mainroutine ( /
                       ;; function localization
                       subfunction

                       ;; varialbe localization
                       e
                     )
  (defun subfunction( a / )
      (dosomething a)
  )

  (setq e (dosomething))
  (subfunction e)
 )


;;  local sub functions using free variables
;;  example five b   **
;;  note no arguments passed to the subfunctions yet
;;       the variable was still redefined
;;       look up lexical scope
(defun c:mainroutine ( /
                        ;; function localization
                        subfunction
                       
                        ;; variable localization
                        a
                        )
  (defun subfunction ( / )
       (setq a "1"))

  (setq a "0")
  (princ (strcat "\n`a' is set to: " a))
  (subfunction)
  (princ (strcat "\n`a' is set to: " a))
  (princ)
)
Title: Re: when to defun
Post by: kdub_nz on July 16, 2009, 01:36:12 AM

just so you know, you pay a premium for having local methods in a function ..

Code: [Select]
(defun Plus1 (i /) (+ 1 i))
(defun Plus2 (i /) (+ 2 i))
(defun Plus3 (i /) (+ 3 i))
(defun Plus4 (i /) (+ 4 i))
(defun Plus5 (i /) (+ 5 i))
(defun Plus6 (i /) (+ 6 i))

(defun doit1 (/ result)
  (setq result 1)
  (setq result (+ result (plus1 result)))
  (setq result (+ result (plus2 result)))
  (setq result (+ result (plus3 result)))
  (setq result (+ result (plus4 result)))
  (setq result (+ result (plus5 result)))
  (setq result (+ result (plus6 result)))
  (setq result1 result)
)
Code: [Select]
(defun doit2 (/
                result
                ;;
                Plus1
                Plus2
                Plus3
                Plus4
                Plus5
                Plus6
               )
  (defun Plus1 (i /) (+ 1 i))
  (defun Plus2 (i /) (+ 2 i))
  (defun Plus3 (i /) (+ 3 i))
  (defun Plus4 (i /) (+ 4 i))
  (defun Plus5 (i /) (+ 5 i))
  (defun Plus6 (i /) (+ 6 i))
  ;;--
  (setq result 1)
  (setq result (+ result (plus1 result)))
  (setq result (+ result (plus2 result)))
  (setq result (+ result (plus3 result)))
  (setq result (+ result (plus4 result)))
  (setq result (+ result (plus5 result)))
  (setq result (+ result (plus6 result)))
  (setq result2 result)
)

Quote
(benchmark '( (doit1) (doit2)))



Benchmarking [M.P. 2005] .................Elapsed milliseconds for 16384 iteration(s)/ relative Timing :

    (DOIT2).....656 / 1.1652 <slowest>
    (DOIT1).....563 / 1.0000 <fastest>
 

Benchmarking [M.P. 2005] .................Elapsed milliseconds for 16384 iteration(s)/ relative Timing :

    (DOIT2).....672 / 1.1626 <slowest>
    (DOIT1).....578 / 1.0000 <fastest>

Benchmarking [M.P. 2005] .................Elapsed milliseconds for 16384 iteration(s)/ relative Timing :

    (DOIT2).....672 / 1.1957 <slowest>
    (DOIT1).....562 / 1.0000 <fastest>

 Benchmarking [M.P. 2005] .................Elapsed milliseconds for 16384 iteration(s)/ relative Timing :

    (DOIT2).....672 / 1.1936 <slowest>
    (DOIT1).....563 / 1.0000 <fastest>

Regards
Kerry