Author Topic: Nested defun's  (Read 9139 times)

0 Members and 1 Guest are viewing this topic.

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Nested defun's
« on: October 29, 2003, 09:00:12 AM »
How does everyone feel about nested defun's? I don't see many hackers using them in their lisp programs. I'm of the opinion that, if you write a program for a client you would want to isolate all your functions. This of course would minimize the chance of conflicts.

Questions:
1. Are there any draw backs to using nested defun's?
2. Are there any benefits to using nested defun's?
TheSwamp.org  (serving the CAD community since 2003)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Nested defun's
« Reply #1 on: October 29, 2003, 09:28:43 AM »
Hi Mark

I use them regularly, and have for ages [literally] ;)

The only percieved drawback I am aware of could be the length of the programme. I sometimes break up longer apps temporarily to handle this.

Benefits.
Keeps code tight.
I use a lot with DCL {or objectDCL} control functions.
Variables can be semi-global ie: declared in the head function only.

There is an issue with the code-check function in the VLide not recognising some of the variables as local/global during the Statistics report in Verbal mode, but this is only cosmetic.

Here is an example from ExpressoCodeCafe Thingies  
http://www.vbdesign.net/expresso/showthread.php?s=&threadid=5225

Regards
Kerry

added: The function name conflict can be an issue. I use registered prefix names which does reduce the risk. I also protect assign my functions.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

JohnK

  • Administrator
  • Seagull
  • Posts: 10626
Nested defun's
« Reply #2 on: October 29, 2003, 09:55:06 AM »
I dont do that normaly. I dont know why, I guess my progns never end up that way.  It would be "neater" though wouldnt it?  Is there any solid reason for using a nested defun?  Would that be the equlivant of making your variables private?
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Nested defun's
« Reply #3 on: October 29, 2003, 10:00:20 AM »
Quote from: Se7en
Would that be the equlivant of making your variables private?

Yes. Your functions would not be visible if the user simply loaded the program file.
TheSwamp.org  (serving the CAD community since 2003)

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Nested defun's
« Reply #4 on: October 29, 2003, 10:06:58 AM »
Here's an example, load this and try to run (fun 3). You'll get "no function definition: FUN"

Code: [Select]
(defun add2 (/ fun rn)
     (defun fun (n) (+ n 100))

     (if
       (setq rn (getreal "\nEnter a number: "))
       (fun rn)
       )
     )
TheSwamp.org  (serving the CAD community since 2003)

daron

  • Guest
Nested defun's
« Reply #5 on: October 29, 2003, 11:20:30 AM »
That was always the way I understood them. I read somewhere, probably the help file that stated the advantages and dis-advantages of nested defuns. This thread was the case in point.

SMadsen

  • Guest
Nested defun's
« Reply #6 on: October 29, 2003, 11:33:17 AM »
Making functions private to a function has the same purpose as using local variables: they don't get to float around in namespaces without reason.

I use many localized functions. Especially for dialogs, as Kerry mentioned. Why have specialized functions that deals with tiles hanging around if there are no tiles to deal with? Also, instead of writing lengthy lambda's in the code, I often use localized functions in mapcar's and apply's.

As Mark points out, the local declaration makes all the difference. Try not to localize it and inspect it after loading first time:

Code: [Select]
(defun add2 (/ rn)
  (defun fun (n) (+ n 100))
  (if
    (setq rn (getreal "\nEnter a number: "))
     (fun rn)
  )
)

_$ fun
nil
_$ add2
#<USUBR @049e2af0 ADD2>

_$ (add2)
103.0
_$ fun
#<USUBR @049e2a14 FUN>


After first execution of ADD2 it gets loaded into the heap and stays there. If it's localized it's put on the stack and gets carried out with the garbage after execution. Clean, easy, effective.

Mark

  • Custom Title
  • Seagull
  • Posts: 28762
Nested defun's
« Reply #7 on: November 04, 2003, 10:54:58 AM »
Is this a good or bad way of writing a function?
Code: [Select]
;;; given a selection set this function will convert it
;;; to an assocation list of vla-objects and layer names
;;; i.e. ((#<VLA-OBJECT IAcadLine 0d0b5fa4> . "BASELINE"))
;;; remove any vla-objects from the list that are on a
;;; locked layer and return the final list
;;;
;;; usage
;;; (setq ss (ssget))
;;; (setq lst (remove-if-locked ss))
(defun remove-if-locked (ss / *activedoc* layersobj parse-ss
                            obj-layer obj-lst rem-locked
                            chg-obj-layer lst-done)

  ;; intialize ActiveX
  (vl-load-com)

  ;; create a list of vla-objects from the selection set
  (defun parse-ss (ss / cntr ent obj-lst)
    (setq cntr 0)
    (while
      (setq ent (ssname ss cntr))
      (setq obj-lst
            (cons (vlax-ename->vla-object ent) obj-lst)
            cntr (1+ cntr)
            )
      ); while
    (obj-layer obj-lst); call obj-layer
    ); defun

  ;; generates an association list of object and layer name
  (defun obj-layer (lst / objlayr)
    (foreach obj lst
             (setq objlayr
                   (cons (cons obj (vla-get-Layer obj)) objlayr)
                   )
             )
    (rem-locked objlayr); call rem-locked
    ); defun

  ;; remove objects on locked layers
  (defun rem-locked (lst)
    (setq lst-done
          (vl-remove-if
            '(lambda (l)
               (= (vla-get-lock (vla-item layersobj (cdr l))) :vlax-true)
               )
            lst
            )
          )
    ; the final list of (<vla-objects> .  "layer names")
    lst-done
    ); defun

  ;; make sure we have a selection set
  (if
    (= (type ss) 'PICKSET)
    (progn
      (setq *activedoc* (vla-get-ActiveDocument (vlax-get-acad-object))
            layersobj (vlax-get-property *activedoc* 'Layers)
            )
      ;; call parse-ss
      (parse-ss ss)
      )
    ); if

  ); defun
TheSwamp.org  (serving the CAD community since 2003)

JohnK

  • Administrator
  • Seagull
  • Posts: 10626
Nested defun's
« Reply #8 on: November 04, 2003, 11:04:27 AM »
Whaaa?!  :shock:  how did you do that?

Alright, im gonna look this over.
TheSwamp.org (serving the CAD community since 2003)
Member location map - Add yourself

Donate to TheSwamp.org

Dave

  • Guest
Nested defun's
« Reply #9 on: November 09, 2003, 12:48:34 AM »
Oh no, who let this guy in here?  :D  Oh well, there goes the neighborhood.

Aside from keeping code tightly bundled and whatnot, there is a small bit of protection by localizing functions within functions.  After all, functions defined with (defun-q) are still list structures.  Those defined with (defun) (at least in Vlisp) are not lists but pointers to objects.  In any case, you can also compile into a separate namespace VLX, which will protect your code and hide the internals.  You have to explicitly define interfaces if you need to get to them though (symbols, functions, etc.).

daron

  • Guest
Nested defun's
« Reply #10 on: November 09, 2003, 01:04:39 AM »
Hi Dave and welcome to the board. It's good to see you here. Thanks for your input.

Dave

  • Guest
Nested defun's
« Reply #11 on: November 10, 2003, 10:15:12 AM »
Thanks for the welcome! I promised John (Se7en) that I'd try to participate as much as I could, but my schedule is really crunched these days.  Things should loosen up by March I think, so I should be able to contribute a bit more then.