Program Style

Program Style

Anonymous
Not applicable
291 Views
12 Replies
Message 1 of 13

Program Style

Anonymous
Not applicable
I use that style all the time when doing dialog boxes, so I can use the
same names for callback functions in different routines without
interference. It does tend to lead to long piles of code inside the
main routine. I believe VL is just warning you in case you've forgotten
that the function name is a local variable. I believe that using that
style does no harm.

I also think it has nothing to do with your other problems, but I have
no idea what's causing your other problems.

jrf
Member of the Autodesk Discussion Forum Moderator Program

In article <387f149b.56973875@adesknews.autodesk.com>, Dave Seibert
wrote:
> When programming I have a certain style I follow, not so much for
> memory reasons, but for clarity. I keep readin warnings against using
> my style and would like to know why it is bad form.
>
> Here is the general form I use:
>
> (defun c:func_name ( / func_main func1 func2 func3)
> (defun func_main ( / )
> (do_something)
> )
> (defun func1 ( / )
> (do_something_else)
> )
> (defun func2 ( / )
> (do_something_else)
> )
> (defun func3 ( / )
> (do_something_else)
> )
> (func_main)
> )
>
> This style has always worked and continues to work well for me. The
> only problem is VLisp keeps warning me not to do it.
>
> I don' know if it's related, but I also have programs that will not
> run when VLisp is loaded. They run fine when it's not loaded.
>
> When doing an animated walkthrough on my programs VLisp will tell me
> I'm crashing in spots that aren't even close to where the problem
> really is.
>
> Any help would be appreciated.
>
0 Likes
292 Views
12 Replies
Replies (12)
Message 2 of 13

Anonymous
Not applicable
When programming I have a certain style I follow, not so much for
memory reasons, but for clarity. I keep readin warnings against using
my style and would like to know why it is bad form.

Here is the general form I use:

(defun c:func_name ( / func_main func1 func2 func3)
(defun func_main ( / )
(do_something)
)
(defun func1 ( / )
(do_something_else)
)
(defun func2 ( / )
(do_something_else)
)
(defun func3 ( / )
(do_something_else)
)
(func_main)
)

This style has always worked and continues to work well for me. The
only problem is VLisp keeps warning me not to do it.

I don' know if it's related, but I also have programs that will not
run when VLisp is loaded. They run fine when it's not loaded.

When doing an animated walkthrough on my programs VLisp will tell me
I'm crashing in spots that aren't even close to where the problem
really is.

Any help would be appreciated.

Have fun,

Dave
Seibertron Engineered Systems
A Virtual company
Virtually a company...
I can dream can't I!
0 Likes
Message 3 of 13

Anonymous
Not applicable
I nest my defuns quite often too. The one twist you are doing that I
haven't tried is to defun the main as well. I tend to have the main part of
the function (your func_main) as code following the last nested defun.

If it helps you with your code, keep it up.

==============================
Michael Weaver
By day: Charles Bettisworth & Co.
mweaver@bettisworth.com
By night: AlasCAD
alascad@go.com
AOL Instant messenger screen name:
AlasCAD
AUGI #w2170
==============================

"Dave Seibert" wrote in message
news:387f149b.56973875@adesknews.autodesk.com...
> When programming I have a certain style I follow, not so much for
> memory reasons, but for clarity. I keep readin warnings against using
> my style and would like to know why it is bad form.
>
> Here is the general form I use:
>
> (defun c:func_name ( / func_main func1 func2 func3)
> (defun func_main ( / )
> (do_something)
> )
> (defun func1 ( / )
> (do_something_else)
> )
> (defun func2 ( / )
> (do_something_else)
> )
> (defun func3 ( / )
> (do_something_else)
> )
> (func_main)
> )
>
> This style has always worked and continues to work well for me. The
> only problem is VLisp keeps warning me not to do it.
>
> I don' know if it's related, but I also have programs that will not
> run when VLisp is loaded. They run fine when it's not loaded.
>
> When doing an animated walkthrough on my programs VLisp will tell me
> I'm crashing in spots that aren't even close to where the problem
> really is.
>
> Any help would be appreciated.
>
> Have fun,
>
> Dave
> Seibertron Engineered Systems
> A Virtual company
> Virtually a company...
> I can dream can't I!
0 Likes
Message 4 of 13

Anonymous
Not applicable
Here is a quote from the Visual LISP help file:

"Note If you check the entire GpDraw.lsp file, you’ll notice two additional
warning messages:
; *** WARNING: local variable used as function: OBJECTCREATIONFUNCTION
; *** WARNING: local variable used as function: OBJECTCREATIONFUNCTION
...
The code will work – it is just Visual LISP’s way of letting you know that
you’re either doing something very clever, or very dangerous. In this case,
it is clever."

So, if it's clever rather than dangerous, go for it.
0 Likes
Message 5 of 13

Anonymous
Not applicable
I've also had programs that won't run in VLisp. In my case, the reason was
that my program was calling functions that were defined by the acad.lsp
file, and this was being automatically loaded in native AutoLISP, but not in
VLisp. I solved this problem with this line:

(if vl-vbaload (load "acad")).

Another reason this has happened to me was that my AutoLISP program runs a
script file that doesn't work well with Visual LISP.
0 Likes
Message 6 of 13

Anonymous
Not applicable
Dave Seibert wrote:
> When programming I have a certain style I follow, not so much for
> memory reasons, but for clarity. I keep readin warnings against using
> my style and would like to know why it is bad form.

> Here is the general form I use:

> (defun c:func_name ( / func_main func1 func2 func3)
> (defun func_main ( / )
> (do_something)
> )

"local variable used as function" says that you assigned a function to a
local variable.
you can get rid of that warning by either:

- use (defun c:func_name () ie omit the funcs from the local param list, or
- make your local funcs global to allow efficient linking

the problem is that VLISP currently doesn't parse function definitions for
nested functions at run-time, only at compile- or check-time and gives you
this warning. (BTW: ACOMP did that. but ACOMP was for experienced users and
optional)
the warning is okay, because when you call your function the functions are
redefined again every time you call the function,
so you need not declare them as local.

functions are special objects now which are compiled. with your syntax you
make a local copy of the name, set it to nil and redefine it.
simple redefinition alone is sufficient.
with old autolisp this was exactly the same (but without warning)

the real problem is that autolisp is still too dynamic.
normal lisps would parse out all local functions and disallow redinitions at
run-time. noone of you evere changed local definitons ever, did someone?
I know only of S::STARTUP redefinitions.
but keeping it backwards compatible forces this antique behaviour.

the warning is for the more experienced users to see bottlenecks in the your
code.
your style is perfect for scheme or common lisp. there they would be even
closures (ie: capture outer variables used inside whcih woudl be fine for
callbacks, action_tiles)

> (defun func1 ( / )
> (do_something_else)
> )
> (defun func2 ( / )
> (do_something_else)
> )
> (defun func3 ( / )
> (do_something_else)
> )
> (func_main)
> )

> This style has always worked and continues to work well for me. The
> only problem is VLisp keeps warning me not to do it.

> I don' know if it's related, but I also have programs that will not
> run when VLisp is loaded. They run fine when it's not loaded.

> When doing an animated walkthrough on my programs VLisp will tell me
> I'm crashing in spots that aren't even close to where the problem
> really is.

> Any help would be appreciated.
0 Likes
Message 7 of 13

Anonymous
Not applicable
The real problem with this is that unlike AutoLISP,
under VLISP now DEFUN is a _heavy_ operation, taking up
much more time then before in ALISP, because it's now
compiling the code also. In ALISP defun was just a little
bit more then a LIST statement, but it is much more now
in VLISP.

It's fine for interface functions which only get called so often
to be written this way, but for a frequently called library
functions it's a no-no. In Common Lisp there's a LABELS form for
defining local functions accessible only within that statement,
but there's nothing for that in VLISP, except for nested defuns,
which are slow since VLISP re-compiles them at run-time every
time the parent function gets called. 😞

So if used in library code that have to be the most efficient,
we must move those nested defun definitions out of the function,
thus polluting the name space with functions we'll never call
from outside.

On Fri, 14 Jan 2000 07:12:59 EST, Jon Fleming
wrote:

>I use that style all the time when doing dialog boxes, so I can use the
>same names for callback functions in different routines without
>interference. It does tend to lead to long piles of code inside the
>main routine. I believe VL is just warning you in case you've forgotten
>that the function name is a local variable. I believe that using that
>style does no harm.
>
>I also think it has nothing to do with your other problems, but I have
>no idea what's causing your other problems.
0 Likes
Message 8 of 13

Anonymous
Not applicable
Good point. I hadn't considered the extra time for vlisp to compile these
nested defuns. What would be the implications of using defun-q, instead?

Mike Weaver

"Vladimir Nesterovsky" wrote in message
news:38822058.6931076@adesknews.autodesk.com...
> The real problem with this is that unlike AutoLISP,
> under VLISP now DEFUN is a _heavy_ operation, taking up
> much more time then before in ALISP, because it's now
> compiling the code also. In ALISP defun was just a little
> bit more then a LIST statement, but it is much more now
> in VLISP.
>
> It's fine for interface functions which only get called so often
> to be written this way, but for a frequently called library
> functions it's a no-no. In Common Lisp there's a LABELS form for
> defining local functions accessible only within that statement,
> but there's nothing for that in VLISP, except for nested defuns,
> which are slow since VLISP re-compiles them at run-time every
> time the parent function gets called. 😞
>
> So if used in library code that have to be the most efficient,
> we must move those nested defun definitions out of the function,
> thus polluting the name space with functions we'll never call
> from outside.
>
>
> On Fri, 14 Jan 2000 07:12:59 EST, Jon Fleming
> wrote:
>
> >I use that style all the time when doing dialog boxes, so I can use the
> >same names for callback functions in different routines without
> >interference. It does tend to lead to long piles of code inside the
> >main routine. I believe VL is just warning you in case you've forgotten
> >that the function name is a local variable. I believe that using that
> >style does no harm.
> >
> >I also think it has nothing to do with your other problems, but I have
> >no idea what's causing your other problems.
>
0 Likes
Message 9 of 13

Anonymous
Not applicable
On Mon, 17 Jan 2000 06:30:34 -0900, "Michael Weaver"
wrote:

>Good point. I hadn't considered the extra time for vlisp to compile these
>nested defuns. What would be the implications of using defun-q, instead?

I don't think it'll change much, since at the execution time the
function definition code list (a.k.a. "lambda list") will still
need to be compiled by VLISP internally.

But I haven't checked this specifically. 🙂

What I did observed, was a case of defining
some POP utility like this:

(defun pop1 (qlst / frst)
(setq frst (car (vl-symbol-value qlst)))
(set qlst (cdr (vl-symbol-value qlst)))
frst)

which worked OK. But then I tried being "smarter" as in

(defun pop2 (qlst)
((list nil
(list 'setq qlst (list 'cdr qlst))
(car (vl-symbol-value qlst)))))

It worked fine too, so I ended up using it as my library routine;
I thought it looked "cleaner". But then I had to port over to
r2000, and suddenly some other program became very slow. Much
to my surprise had I found out after some debugging and
profiling, that it was this version of POP that made it run
very slow. It was never a problem in r14; timings were identical
there for the two versions.

It's clear in what way the second version is different from the first:
it creates function list at run time and then evaluates it, creating
temporary LAMBDA internally (as I saw happening while debugging).

For example,

Command: !a nil
Command: (repeat 1000 (progn (setq a (cons 1 a)) nil)) nil
Command: (length a) 1000
Command: (run-time '(repeat 1000 (pop2 'a) (setq a (cons 1 a)) nil))
1.21001 sec
Command: (run-time '(repeat 1000 (pop1 'a) (setq a (cons 1 a)) nil))
0.0 sec
Command: (run-time '(repeat 10000 (pop1 'a) (setq a (cons 1 a)) nil))
0.270005 sec

So the second version is some _45_ times slower then the regular
one, defined with defun.

The same thing done in r14 (on this particular testing PC)
yields 0.44 and 0.39 sec per 10000 runs for pop1 and pop2
respectively, which is essentially the same. The second
version is actually a little bit faster, which was another
reason I preferred it previously.

Not anymore. 🙂 🙂

But of course it only mattered since it'd been used in a library
routine. Again, would it be in some user-interface module,
I wouldn't worry about it, since it'd be called only once
per user interaction.

>"Vladimir Nesterovsky" wrote in message
>news:38822058.6931076@adesknews.autodesk.com...
>> The real problem with this is that unlike AutoLISP,
>> under VLISP now DEFUN is a _heavy_ operation, taking up
>> much more time then before in ALISP, because it's now
>> compiling the code also. In ALISP defun was just a little
>> bit more then a LIST statement, but it is much more now
>> in VLISP.
>>
>>
>> On Fri, 14 Jan 2000 07:12:59 EST, Jon Fleming
>> wrote:
>>
>> >I use that style all the time when doing dialog boxes, so I can use the
>> >same names for callback functions in different routines without
>> >interference. It does tend to lead to long piles of code inside the
>> >main routine. I believe VL is just warning you in case you've forgotten
>> >that the function name is a local variable. I believe that using that
>> >style does no harm.
0 Likes
Message 10 of 13

Anonymous
Not applicable
Okay, for the sake of performance we shouldn't nest our defun's.

What can we do, short of being very careful, to keep from loading two files
with commonly named defuns that differ? It seems like this kind of problem
may not show itself for days (till the second routine is run and crashes).
With nested defuns I don't need to worry about it, and in fact expect no
problem because of this technique.

Just trying to keep from stepping on my own toes.

Mike Weaver

"Vladimir Nesterovsky" wrote in message
news:388bc68a.35435368@adesknews.autodesk.com...
> On Mon, 17 Jan 2000 06:30:34 -0900, "Michael Weaver"
> wrote:
>
> >Good point. I hadn't considered the extra time for vlisp to compile
these
> >nested defuns. What would be the implications of using defun-q, instead?
>
> I don't think it'll change much, since at the execution time the
> function definition code list (a.k.a. "lambda list") will still
> need to be compiled by VLISP internally.
>
> But I haven't checked this specifically. 🙂
>
> What I did observed, was a case of defining
> some POP utility like this:
>
> (defun pop1 (qlst / frst)
> (setq frst (car (vl-symbol-value qlst)))
> (set qlst (cdr (vl-symbol-value qlst)))
> frst)
>
> which worked OK. But then I tried being "smarter" as in
>
> (defun pop2 (qlst)
> ((list nil
> (list 'setq qlst (list 'cdr qlst))
> (car (vl-symbol-value qlst)))))
>
> It worked fine too, so I ended up using it as my library routine;
> I thought it looked "cleaner". But then I had to port over to
> r2000, and suddenly some other program became very slow. Much
> to my surprise had I found out after some debugging and
> profiling, that it was this version of POP that made it run
> very slow. It was never a problem in r14; timings were identical
> there for the two versions.
>
> It's clear in what way the second version is different from the first:
> it creates function list at run time and then evaluates it, creating
> temporary LAMBDA internally (as I saw happening while debugging).
>
> For example,
>
> Command: !a nil
> Command: (repeat 1000 (progn (setq a (cons 1 a)) nil)) nil
> Command: (length a) 1000
> Command: (run-time '(repeat 1000 (pop2 'a) (setq a (cons 1 a)) nil))
> 1.21001 sec
> Command: (run-time '(repeat 1000 (pop1 'a) (setq a (cons 1 a)) nil))
> 0.0 sec
> Command: (run-time '(repeat 10000 (pop1 'a) (setq a (cons 1 a)) nil))
> 0.270005 sec
>
> So the second version is some _45_ times slower then the regular
> one, defined with defun.
>
> The same thing done in r14 (on this particular testing PC)
> yields 0.44 and 0.39 sec per 10000 runs for pop1 and pop2
> respectively, which is essentially the same. The second
> version is actually a little bit faster, which was another
> reason I preferred it previously.
>
> Not anymore. 🙂 🙂
>
> But of course it only mattered since it'd been used in a library
> routine. Again, would it be in some user-interface module,
> I wouldn't worry about it, since it'd be called only once
> per user interaction.
>
>
> >"Vladimir Nesterovsky" wrote in message
> >news:38822058.6931076@adesknews.autodesk.com...
> >> The real problem with this is that unlike AutoLISP,
> >> under VLISP now DEFUN is a _heavy_ operation, taking up
> >> much more time then before in ALISP, because it's now
> >> compiling the code also. In ALISP defun was just a little
> >> bit more then a LIST statement, but it is much more now
> >> in VLISP.
> >>
> >>
> >> On Fri, 14 Jan 2000 07:12:59 EST, Jon Fleming
> >> wrote:
> >>
> >> >I use that style all the time when doing dialog boxes, so I can use
the
> >> >same names for callback functions in different routines without
> >> >interference. It does tend to lead to long piles of code inside the
> >> >main routine. I believe VL is just warning you in case you've
forgotten
> >> >that the function name is a local variable. I believe that using that

> >> >style does no harm.
>
0 Likes
Message 11 of 13

Anonymous
Not applicable
Keeping in mind that these defuns was actually
ment to be internal for the main function, we
should do the same thing we ought to do for
each its internal symbol ---- prefix it with
a function's name:

(defun mainfunc%nestedf1 (...) ... )
....
(defun mainfunc ( mainfunc%arg1 ... / .... )
....
(mainfunc%nested1 mainfunc%arg1)
....
)

thus ensuring there will be no name conflicts.

HTH

On Mon, 17 Jan 2000 21:23:53 -0900, "Michael Weaver"
wrote:

>Okay, for the sake of performance we shouldn't nest our defun's.
>
>What can we do, short of being very careful, to keep from loading two files
>with commonly named defuns that differ? It seems like this kind of problem
>may not show itself for days (till the second routine is run and crashes).
>With nested defuns I don't need to worry about it, and in fact expect no
>problem because of this technique.

---
Vlad http://vnestr.tripod.com/
0 Likes
Message 12 of 13

Anonymous
Not applicable
That makes sense.

I've been doing nested defuns for something over six years. It's going to
take getting used not doing them nested. I guess I'll have to be more
careful now with the scope of the variables in my subroutines:-)

Thanks for the pointers,
Mike Weaver

"Vladimir Nesterovsky" wrote in message
news:38860c48.522767@adesknews.autodesk.com...
> Keeping in mind that these defuns was actually
> ment to be internal for the main function, we
> should do the same thing we ought to do for
> each its internal symbol ---- prefix it with
> a function's name:
>
> (defun mainfunc%nestedf1 (...) ... )
> ....
> (defun mainfunc ( mainfunc%arg1 ... / .... )
> ....
> (mainfunc%nested1 mainfunc%arg1)
> ....
> )
>
> thus ensuring there will be no name conflicts.
>
> HTH
>
>
> On Mon, 17 Jan 2000 21:23:53 -0900, "Michael Weaver"
> wrote:
>
> >Okay, for the sake of performance we shouldn't nest our defun's.
> >
> >What can we do, short of being very careful, to keep from loading two
files
> >with commonly named defuns that differ? It seems like this kind of
problem
> >may not show itself for days (till the second routine is run and
crashes).
> >With nested defuns I don't need to worry about it, and in fact expect no
> >problem because of this technique.
>
> ---
> Vlad http://vnestr.tripod.com/
0 Likes
Message 13 of 13

Anonymous
Not applicable
On Tue, 18 Jan 2000 16:45:16 -0900, "Michael Weaver"
wrote:

>That makes sense.
>
>I've been doing nested defuns for something over six years. It's going to
>take getting used not doing them nested.

Unfortunately so. 😞

> I guess I'll have to be more
>careful now with the scope of the variables in my subroutines:-)
>
>Thanks for the pointers,

You're welcome. 🙂 Thanks for the interesting discussion.
---
Vlad http://vnestr.tripod.com/
0 Likes