9

I can't seem to use a rule to index a vector.

x = Range[10];
{ i, x[[i]] } /. i -> 5

I get the following error when evaluating the above code, even if the next cell shows the correct result:

Part::pspec: Part specification i is neither an integer nor a list of integers.
Meh
  • 1,637
  • 2
  • 13
  • 17

4 Answers4

13

Using Trace,

Trace[x = Range[10]; { i, x[[i]] } /. i -> 5]

we will see that the error comes from Mathematica trying to evaluate

{1,2,3,4,5,6,7,8,9,10}[[i]]

As you pointed out, the error message is harmless in this case. If you want Mathematica to substitute first, you can use Hold and ReleaseHold:

x = Range[10];
ReleaseHold[Hold[{i, x[[i]]}] /. i -> 5]

which prevents the evaluation of {i, x[[i]]} until the Hold is released. The output is the same, but now without the error message:

{5,5}

Michael Wijaya
  • 2,197
  • 16
  • 29
11

The existing answers explain why you are getting this error and how to get around it, and along the way explain something very useful about how evaluation works in Mathematica.

I would like to suggest some alternatives to get the output you want. Assume x=Range[10] as in your question.

Firstly, you could try setting i to be a local constant using With:

With[{i = 5}, {i, x[[i]]}]

{5, 5}

Secondly, you could try using a pure function:

{#, x[[#]]} &@ 5

{5, 5}

Whether you would prefer to use one of these alternative methods depends on the nature of the larger problem you are working on.

Verbeia
  • 34,233
  • 9
  • 109
  • 224
5

Since this gives the correct answer in spite of the message, you could just use Quiet:

x = Range[10];
Quiet[{i, x[[i]]} /. i -> 5]
 {5, 5}
Brett Champion
  • 20,779
  • 2
  • 64
  • 121
4

As stated several times this is the result of Mathematica evaluating x[[i]], just as the error message told you. Also, you can click the >> at the end of the message to get some more information.

You can do this operation in a number of ways, one of the best being With as Verbeia shows.
With only allows you to replace symbols however. If you need to match patterns I suggest that you use Unevaluated:

x = Range[7, 11];

Unevaluated[ {3 + 3, x[[1]]} ] /. _Integer -> 5
{10, 11}

Here both 3 and 1 were replaced with 5 because they match the pattern _Integer and this was done before evaluation (or you would get {6, 7}).

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371