Author Topic: when to defun  (Read 1896 times)

0 Members and 1 Guest are viewing this topic.

curmudgeon

  • Newt
  • Posts: 194
when to defun
« 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.
Never express yourself more clearly than you are able to think.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10401
Re: when to defun
« Reply #1 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>
)
« Last Edit: July 15, 2009, 03:34:07 PM by CAB »
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Lee Mac

  • Seagull
  • Posts: 12912
  • London, England
Re: when to defun
« Reply #2 on: July 15, 2009, 12:23:26 PM »
Great reply Alan, I have learnt a lot from it too  8-)

GDF

  • Water Moccasin
  • Posts: 2081
Re: when to defun
« Reply #3 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"
« Last Edit: July 15, 2009, 12:45:41 PM by GDF »
Why is there never enough time to do it right, but always enough time to do it over?
BricsCAD 2020x64 Windows 10x64

JohnK

  • Administrator
  • Seagull
  • Posts: 10625
Re: when to defun
« Reply #4 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.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

curmudgeon

  • Newt
  • Posts: 194
Re: when to defun
« Reply #5 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.
 :-)
Never express yourself more clearly than you are able to think.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: when to defun
« Reply #6 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 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
« Last Edit: July 15, 2009, 02:15:25 PM by gile »
Speaking English as a French Frog

JohnK

  • Administrator
  • Seagull
  • Posts: 10625
Re: when to defun
« Reply #7 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)
)
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2132
  • class keyThumper<T>:ILazy<T>
Re: when to defun
« Reply #8 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
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.