# How to pass a list as function argument?

I have the following function

lFreqPhylo[a_, Q_, b_, p_] :=  Sum[Log[freqFunction[r[[p]][[i]], L[[p]][[i]], a, Q, b, {i, 1, nbranches[[p]]}];


The objects L, r and nbranches are simply lists of data, and the argument p tells the function which dataset to refer to.

I'd like to define a function which sums all of the datasets (here n=2) and uses a different argument a and b for each dataset, so to write it our by hand,

lFreqPhylo[a1, Q, b1, 1] + lFreqPhylo[a2, Q, b2, 2]


To this end, I defined two lists,

A = {a1,a2}


and

B = {b1,b2}


(This list has more elements but I'm giving the example of 2 elements to keep it simple.) What this means is that I'd need to pass the lists A, B and the index to each list (p in lFreqPhylo) to a new function lFreq. The following approach however failed:

lFreq[A__, B__, Q_] := Sum[lFreqPhylo[A[[p]], Q, B[[p]], p], {p, 1, 2}]; (*Doesn't work!*)


How can I pass the two lists, A and B, to the function lFreqPhylo such that I can (a) use the 'Sum[...]' expression on the right hand side, (b) use the list elements, a1, a2, b1 and b2, as arguments of the function?

-
Kuba, Well, problem is I have two lists and need to pass an index of the list as an argument. So following your advice, having defined two lists, A = {a1,a2}; B = {b1,b2}; I did f1[a_, b_, Q_] := (a b)^2/Q; f2[Q_, a__, b__] := Total[MapThread[f1[#1, #2, Q] &, {A, B}]]; and now it works. But what if I have f1[a_, b_, Q_,i_] := (a b)^2/Q i where i is the index of the element of the list (1 or 2)? How do I define f2 then? – Rafal May 27 '14 at 13:36
You're absolutely right, I've now edited it. – Rafal May 27 '14 at 14:09
Change the LHS of your definition to lFreq[A_, B_, Q_] and it works as expected; no? – kglr May 27 '14 at 22:10

Edit

The definition you make

lFreq[A__, B__, Q_] := [...]


is not very nice. There is an ambiguity here and Mathematica will not know how many elements to match to A and how many to match to B. We can check this by defining

lFreqTest[A__,B__]:= {A}


Then

lFreqTest[1, 2, 3, 4]


gives

{1}


So that we see that Mathematica tries to make B__ as long as possible. There is a terrible way around this

Clear@tester
tester[PatternSequence[a__, b__] /; (Length@{a} == Length@{b})] := "ok"


which gives

tester[1,2]

"ok"

tester[1,2,3]

tester[1,2,3]


But this will be very slow. You should look to alternatives.

Original

A = {1, 2};
B = {2, 3};
Q = 6;


The actual functions

f1[a_, b_, Q_, i_] := (a b)^2/Q;

lFreq[listA_, listB_, Q_] :=

lFreq[listA_, listB_, Q_] :=
Total@
f1[#1, #2, Q, #3] &
,
{listA, listB, Range[Length@listA]}
]


Now we have

lFreq[A, B, Q]

20/3

-
Jacob, I have now changed the original question such that it contains all the sub-questions I had. Sorry for the confusion. – Rafal May 27 '14 at 14:10
Thanks Jacob. I've written the following and it seems to work. Do you think this is better or do you think it will be slow too and should I find another way? lFreqPhylo[a_, Q_, b_, p_] := Sum[Log[freqFunction[r[[p]][[i]], L[[p]][[i]], a, Q, b]], {i, 1, nbranches[[p]]}]; lFreqPhylo2[listA_, listB_, Q_] := Total@MapThread[ lFreqPhylo[#1, Q, #2, #3] &, {listA, listB, Range[Length@listA]}]; lFreq[A_, B_, Q_] := Evaluate[lFreqPhylo2[A, B, Q]]; – Rafal May 27 '14 at 15:26
@Rafal that looks quite reasonable. Just so you know, you can write r[[p]][[i]] as r[[p, i]]. Furthermore your definition for lFreq may be a bit tricky. Either Q A and B are already set, and it is misleading to have them as function arguments. Or they are not set, and MapThread will probably fail. Maybe it works if you define this function before you define lFreqPhylo2, A, B and Q. – Jacob Akkerboom May 27 '14 at 15:44
Longest can help here. – Alexey Popkov May 27 '14 at 16:49

lFreq[A_List, B_List, Q_]:=Sum[Function[i, lFreqPhylo[A[[i]], Q, B[[i]], i][j], {j, 1, 2}]

lFreqPhylo[a1, Q, b1, 1] + lFreqPhylo[a2, Q, b2, 2]