TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: AWW on December 02, 2011, 01:38:41 PM

Title: Function
Post by: AWW on December 02, 2011, 01:38:41 PM
Code: [Select]
I've been analyzing code and putting comments on it but am stuck on the "function". I can't seem to grasp what it actually does. Here is the code with comments:

[code]  (cond (  (< (length pts) 2))
;if the # of elements in the list is less than 2
       
        (  (vlax-invoke-method spc 'AddLeader
     ;then draw leader in active space using addleader method

     (vlax-make-variant
       ;and create a variant data type

       (vlax-safearray-fill
;and store data in the elements of a safearrya

(vlax-make-safearray vlax-vbDouble
   ;and create a single-dimension safearray consisting of doubles

   (cons 0 (1- (* 3 (length pts)))))
;and return # of elements in list (integer). multiply by 3.
                                  decrement by 1. add 0 to beginning of list.

(apply (function append) pts)))

From the help files:

Function - Tells the Visual LISP compiler to link and optimize an argument as if it were a built-in function

What exactly does this mean? Thanks for any elaboration.
Title: Re: Function
Post by: Lee Mac on December 02, 2011, 01:52:09 PM
The function function tells the AutoLISP interpreter that the supplied symbol is to be interpreted as a functional argument (rather than a quoted symbol). This improves performance when the code is 'compiled' (to a .fas file for example) since the functional argument can be optimised like a standard built-in function.

Performance aside, it will achieve the same results as supplying a quoted symbol:

Code: [Select]
(mapcar '+ '(1 2 3) '(4 5 6))
==> (5 7 9)

(mapcar (function +) '(1 2 3) '(4 5 6))
==> (5 7 9)

(mapcar (function +) (quote (1 2 3)) (quote (4 5 6)))
==> (5 7 9)

All of the above are equivalent.
Title: Re: Function
Post by: gile on December 02, 2011, 02:10:19 PM
Hi,

From thes tests I did (but I don't do so much), I didn't notice any optimisation while using function with built-in functions nor with 'defun' functions.
I only noticed an optimisation with 'lambda' function.
Title: Re: Function
Post by: Lee Mac on December 02, 2011, 02:37:20 PM
From thes tests I did (but I don't do so much), I didn't notice any optimisation while using function with built-in functions nor with 'defun' functions.
I only noticed an optimisation with 'lambda' function.

Here is a quick test I threw together, though perhaps not too conclusive with such a simple lambda function being tested...


Phase 1: Testing Lambda Function:

The Functions:
Code: [Select]
(defun UncompiledQuoted ( lst )
    (mapcar '(lambda ( x ) (+ x 5)) lst)
)

(defun UncompiledFunction ( lst )
    (mapcar (function (lambda ( x ) (+ x 5))) lst)
)

(defun CompiledQuoted ( lst )
    (mapcar '(lambda ( x ) (+ x 5)) lst)
)

(defun CompiledFunction ( lst )
    (mapcar (function (lambda ( x ) (+ x 5))) lst)
)

[ The 'CompiledQuoted' and 'CompiledFunction' functions were compiled to an Optimised & Linked .fas file ]

Constructing a test list:
Code: [Select]
_$ (setq lst '(0 1 2 3 4 5))
(0 1 2 3 4 5)
_$ (repeat 5 (setq lst (append lst lst)))
(0 1 2 3 4 5 0 1 2 3 4 5 ... 0 1 2 3 4 5)
_$

The Results:
Code: [Select]
_$ (Benchmark '((UncompiledQuoted lst) (UncompiledFunction lst) (CompiledQuoted lst) (CompiledFunction lst)))
Benchmarking .................Elapsed milliseconds / relative speed for 16384 iteration(s):

    (COMPILEDFUNCTION LST).......1482 / 1.72 <fastest>
    (UNCOMPILEDFUNCTION LST).....1841 / 1.38
    (UNCOMPILEDQUOTED LST).......1887 / 1.35
    (COMPILEDQUOTED LST).........2543 / 1 <slowest>


Phase 2: Testing In-Built Function:

The Functions:
Code: [Select]
(defun UncompiledQuoted ( lst )
    (mapcar '1+ lst)
)

(defun UncompiledFunction ( lst )
    (mapcar (function 1+) lst)
)

(defun CompiledQuoted ( lst )
    (mapcar '1+ lst)
)

(defun CompiledFunction ( lst )
    (mapcar (function 1+) lst)
)

[ The 'CompiledQuoted' and 'CompiledFunction' functions were compiled to an Optimised & Linked .fas file ]

The Results (Using the same test list):
Code: [Select]
_$ (Benchmark '((UncompiledQuoted lst) (UncompiledFunction lst) (CompiledQuoted lst) (CompiledFunction lst)))
Benchmarking ..................Elapsed milliseconds / relative speed for 32768 iteration(s):

    (COMPILEDQUOTED LST).........1794 / 1.05 <fastest>
    (COMPILEDFUNCTION LST).......1810 / 1.04
    (UNCOMPILEDFUNCTION LST).....1840 / 1.03
    (UNCOMPILEDQUOTED LST).......1888 / 1 <slowest>
Title: Re: Function
Post by: AWW on December 02, 2011, 02:58:48 PM
Quote
The function function tells the AutoLISP interpreter that the supplied symbol is to be interpreted as a functional argument (rather than a quoted symbol).

What I gather is that "+" (your example) and "append" (my example) are functions, but can also be symbols as well.

I tried coding (my example) the other ways that you had listed and I always got "pts bad argument type". Am I missing something there?

Is function used more for performance reasons then?

Code: [Select]
(apply (function append) pts)))
What happens here is the list of arguments is passed and appended together, I think
Title: Re: Function
Post by: Lee Mac on December 02, 2011, 03:31:37 PM
What I gather is that "+" (your example) and "append" (my example) are functions, but can also be symbols as well.

Perhaps bad way of phrasing on my part, 'append' and '+' are [protected] symbols and also functions.

I tried coding (my example) the other ways that you had listed and I always got "pts bad argument type". Am I missing something there?

You could code your example in one of two ways:

Code: [Select]
(apply 'append pts)

(apply (function append) pts)

Is function used more for performance reasons then?

Other than aesthetics, yes, function is used for performance in compiled code.

Code: [Select]
(apply (function append) pts)))What happens here is the list of arguments is passed and appended together, I think

Code: [Select]
(apply '<function> (<arg1> <arg2> ... <argN>)
Is equivalent to:

Code: [Select]
(<function> <arg1> <arg2> ... <argN>)
As an example:

Code: [Select]
(apply 'append ((1 2 3) (4 5 6) (7 8 9)))  <==>  (1 2 3 4 5 6 7 8 9)  <==>  (append (1 2 3) (4 5 6) (7 8 9))
Title: Re: Function
Post by: VovKa on December 02, 2011, 03:47:44 PM
Hi,

From thes tests I did (but I don't do so much), I didn't notice any optimisation while using function with built-in functions nor with 'defun' functions.
I only noticed an optimisation with 'lambda' function.
+1
function cannot compile what is already compiled and thus there's no speed optimization.
Title: Re: Function
Post by: AWW on December 02, 2011, 03:51:54 PM
Seems to be one of those preference situations. As they say, more than one way to get things done. Thanks for the clarifications Lee. Much appreciated!
Title: Re: Function
Post by: Lee Mac on December 02, 2011, 04:07:43 PM
Seems to be one of those preference situations. As they say, more than one way to get things done. Thanks for the clarifications Lee. Much appreciated!

You're welcome, I'm glad my explanations were somewhat comprehensible  :-)
Title: Re: Function
Post by: thuphong on December 02, 2011, 07:14:53 PM
Thanks Lee Mac :ugly:
Title: Re: Function
Post by: BlackBox on December 03, 2011, 02:20:49 PM
I'm glad my explanations were somewhat comprehensible  :-)

*Still processing*... Cheers, mate! :beer: 
Title: Re: Function
Post by: Lee Mac on December 03, 2011, 08:27:28 PM
I'm glad my explanations were somewhat comprehensible  :-)

*Still processing*... Cheers, mate! :beer:

lol cheers dude  8-)
Title: Re: Function
Post by: dgorsman on December 05, 2011, 10:39:54 AM
I've used (function...) once or twice when creating LISP code on-the-fly where the single-quote was giving the parser fits.  Might also work the same for those using in-line LISP in command macros in the CUIx.
Title: Re: Function
Post by: BlackBox on December 05, 2011, 12:44:09 PM
I've used (function...) once or twice when creating LISP code on-the-fly where the single-quote was giving the parser fits.  Might also work the same for those using in-line LISP in command macros in the CUIx.

Interesting point; I've honestly never considered putting a good Mapcar + Lambda combo inside a macro before... Not that I will now, but I've always simply added an If Statement to my Macros to load the LISP (if unavailable), then call the function.