Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm trying to define a function which modifies and sums over the elements of an array. Here is a very simplified version.

myF[kmax_] = Sum[v[[k]]/k, {k, 1, kmax}]

As you can see, each element between 1 and the function argument (kmax) is divided by its index and then summed with the others.

The problem is that mathematica isn't accepting that v[[k]] and complains that k isn't an integer.

Part::pspec: Part specification k is neither an integer nor a list of integers.

I tried replacing k with Round[k], but the problem remains. I even tried redefining the vector, where the elements are already divided by k, and then just summing over the first kmax elements:

myF[kmax_] = Total[Take[v, kmax]]

And I'm still getting error messages about the argument not being of the right type

Take::seqs: Sequence specification (+n, -n, {+n}, {-n}, {m, n}, or {m, n, s}) expected at position 2 in Take

So, am I doing something wrong? Is there any way to access array elements within a function definition?

share|improve this question
    
Try with myF[kmax_] := ... . –  b.gatessucks Dec 4 '12 at 14:51
    
Also myF[kmax_Integer] := ... will give you some defence against real values creeping into your function. –  image_doctor Dec 4 '12 at 15:01
1  
You should generaly avoid using Set (=) for function definitions, and you should avoid defining functions which depend on variables implicitly (like on your v here). For the latter, you can read some relevant discussion here. –  Leonid Shifrin Dec 4 '12 at 15:17

3 Answers 3

up vote 9 down vote accepted

The problem is that when Mathematica processes

myF[kmax_] = Sum[v[[k]]/k, {k, 1, kmax}]

it will immediately evaluate the right-hand side. And since it doesn't have a numeric value for kmax yet, it can't evaluate the Sum yet, which leads it to tell you that in v[[k]], k is not an integer, because it's still a symbol!

If you instead use a delayed set :=, the right-hand side will not be evaluated until the function is called where kmax has been given a value, so

 myF[kmax_] := Sum[v[[k]]/k, {k, 1, kmax}]

Then when you call myF[10] Mathematica evaluates Sum[v[[k]]/k, {k, 1, 10}], which means k gets an integer value before it evaluates v[[k]].

share|improve this answer

In addition to the distinction between = and := shown by jVincent, you can prevent Part from receiving a bad argument by introducing an auxiliary function with a restrictive pattern. This is most commonly done with the pattern _?NumericQ and you will see many examples if you search this site for NumericQ. Here I will use _Integer as that is more appropriate as an argument for Part.

v = {9, 7, 5, 3, 1};

part[x_, n_Integer] := x[[n]]

Sum[part[v, k]/k, {k, 1, kmax}]
Sum[part[{9, 7, 5, 3, 1}, k]/k, {k, 1, kmax}]

This expression is returned without errors.

share|improve this answer

While you said your example was a simplified version, if the full form is similar, I would consider using vector processing:

myF[kmax_] := Total[v[[;;kmax]]/Range[kmax]]

where v[[;;kmax]]/Range[kmax] is evaluated term wise, i.e. it gives $\frac{v_i}{i}$. There are a number of optimizations internally that make this faster than Sum.

Note, the use of SetDelayed (:=), like in jVincent's answer.

Edit: Additionally, I would consider using a Dot product instead:

myF[kmax_] := v[[;;kmax]].(1/Range[kmax])

which incorporates the vector processing from before, and improves readability.

share|improve this answer
1  
Or he could define myF = v.(1/Range[Length[v]]) and call myF[[i]] instead of myF[i]. –  Jens Dec 4 '12 at 17:59
    
@Jens, good point. I think programatically and conceptually that is superior. –  rcollyer Dec 4 '12 at 21:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.