[GAP Forum] List passing and access

Alexander Konovalov alexander.konovalov at gmail.com
Tue Apr 27 22:58:40 BST 2010


Dear Sandeep, dear Forum,

On 1 Apr 2010, at 23:36, Sandeep Murthy wrote:

> Hi.
> 
> I have a question: is it better / quicker to pass a set of arguments to
> a GAP function as a list, or as individual objects?
> 
> Sincerely, S. Murthy.

It may depend on several factors, maybe you can try to investigate 
and optimise your particular example, using the approach shown below.

In the first example, initially individual arguments seem to work faster:

gap> f1:=function(x) return; end;                            
function( x ) ... end
gap> f2:=function(a,b,c) return; end;          
function( a, b, c ) ... end
gap> for i in [1..10000000] do f1([1,2,3]);od;time;          
2163
gap> for i in [1..10000000] do f1([1,2,3]);od;time;
2172
gap> for i in [1..10000000] do f1([1,2,3]);od;time;
2172
gap> for i in [1..10000000] do f2(1,2,3);od;time;          
1506
gap> for i in [1..10000000] do f2(1,2,3);od;time;
1556
gap> for i in [1..10000000] do f2(1,2,3);od;time;
1519

However, observe that the list [1,2,3] is calculated each time 'f1' is called.
If we will create this list before the loop, then it becomes slightly faster 
than 'f2', since, clearly, GAP parser will parse f1(x) faster than f1(1,2,3):

gap> x:=[1,2,3];
[ 1, 2, 3 ]
gap> for i in [1..10000000] do f1(x);od;time;      
1349
gap> for i in [1..10000000] do f1(x);od;time;
1336
gap> for i in [1..10000000] do f1(x);od;time;
1343

In the second example, we increased the length of the list
and the number of arguments to 8: 

gap> f1:=function(x) return; end;                                   
function( x ) ... end
gap> f2:=function(a,b,c,d,e,f,g,h) return; end;      
function( a, b, c, d, e, f, g, h ) ... end
gap> for i in [1..10000000] do f1([1,2,3,4,5,6,7,8]);od;time;      
2737
gap> for i in [1..10000000] do f1([1,2,3,4,5,6,7,8]);od;time;
2737
gap> for i in [1..10000000] do f1([1,2,3,4,5,6,7,8]);od;time;
2757
gap> for i in [1..10000000] do f2(1,2,3,4,5,6,7,8);od;time;        
3149
gap> for i in [1..10000000] do f2(1,2,3,4,5,6,7,8);od;time;
3152
gap> for i in [1..10000000] do f2(1,2,3,4,5,6,7,8);od;time;
3142

Now the list approach works faster. Moreover, if the list to pass 
to 'f1' will be precomputed in advance, then the timing will be 
comparable with the one demonstrated in the previous example:

gap> t:=[1,2,3,4,5,6,7,8];
[ 1, 2, 3, 4, 5, 6, 7, 8 ]
gap> for i in [1..10000000] do f1(t);od;time;                 
1342
gap> for i in [1..10000000] do f1(t);od;time;
1343
gap> for i in [1..10000000] do f1(t);od;time;
1342

For practical applications, I would say that the overhead is
so small (10^7 loop iterations in the examples above to see the
difference), that you may select either approach that makes your
code easier to read, understand and maintain. Passing arguments
in a list, you may need to create this list in advance, and then
perform indexation in the function body, and the overhead of these
operations may be bigger than passing each argument individually.

Note that thinking of arguments as a list may be useful if you
need to define a function with a variable number of arguments. GAP
allows to to this, if a function is defined with exactly one formal 
argument with the special name 'arg': the values of all the actual 
arguments are stored in a list assigned to the new variable 
corresponding to the formal argument 'arg'. There are two typical 
scenarios for wanting such a possibility: having optional arguments 
and having any number of arguments.

Hope this helps,
Alexander


More information about the Forum mailing list