How much can hard-coded indexing be avoided in Julia?

I’ve noticed a trend toward Julia’s new keywords trending towards using keywords and functions instead of integer indexing in Julia. For example, first(array) instead of array[1], or eachindex(array) instead of 1:length(array).

Is this an intended aim for Julia style-- to avoid integer indexes in code that can avoid it? How likely is it that in the future Julia code will not need to show its 1-based integer heritage in common written code?

3 Likes

I don’t understand what is being asked exactly.

Not relying on hard-coded indexing makes code more general (can handle non 1-based index array) while improving the readability, so, win-win? (third win: sometimes this helps compiler to optimize bound check away too)

not sure why this needs to be achieved. Again, people should strive to write generic code that works with arbitrarily index array (whenever possible) but there’s no universal effort to “hide” anything.

7 Likes

This falls into a another, more important category as it ensures an ordering which is (the most) efficient for the passed in type, see Arrays · The Julia Language

2 Likes

You can also avoid indexing at all in many problems, just iterate the elements themselves. And why not!? Compare the following:

[f(x) for x in myvalues]

and

[f(myvalues[i]) for i in 1:length(myvalues)]
5 Likes

See this answer of mine.

1 Like

Henrique said in his answer pointed to above:

the decision ends up being mostly stylistic.

I asked because am wondering if the preferred style in Julia is going to move toward the newer usage?

if you assume people prefer to write in win-win-win style instead of lose-lose-tie style, then yes.

7 Likes

I did not say it in the exact post I linked above, but three posts below, and the the context is:

But yes, I would like to believe that given time (and that nothing changes in Base) more and more people will adopt one of that three alternatives (given their specific use). If you use only values, there really no reason to not go with just for element in collection; use only indexes? go with for index in eachindex(collection); use both indexes and values? for (index, element) in pairs(collection). There can be exceptions given some particular characteristics of your loop, but these should be considered the default in the mentioned circumnstances.

2 Likes

begin

2 Likes

As a proponent of zero-based indexing, I strongly favor first[array] as a natural and intuitive way to express array[0] :wink:

Don’t even mention the abomination that is array[1]. Hasn’t anyone read Dijskstra?

Edit: Irony, joke, absurdity!

1 Like

The distinction between the serial number of an element of an array and the offset of the element is well understood. Sometimes one is of use, other times the other one is more helpful. Just because Dijskstra made some boldly worded statements doesn’t mean his viewpoint is the only one that is valid.

9 Likes

Yeah I wasn’t serious. People often cite Dijkstra as an “objective” reason why slicing 0:n is superior, when it is objectively subjective.

11 Likes

Perhaps the documentation needs to be more explicit about this. Personally I learn from examples, so that’d be a big plus for me.

Yes, and it’s completely subjective.

t doesn’t make sense to say 0-based indexing is superior to 1-based, or viceversa: they’re applicable in different contexts.

4 Likes

Should we also mention axes here?

1 Like

I wonder how index and value of the elements starting from the second can be obtained. There is an Iterators.peel which gives you first element and the an iterator over the rest, but how to get their indices as well?

To clarify, since Julia 1.4 you can use begin in indexing expressions to refer to the first index, e.g. a[begin] or a[begin+1:end] or (for multiple axes) a[:, begin:2:end].

3 Likes

While it’s implicit in some of the responses you’ve gotten here, it’s worth mentioning that unlike some other languages, Julia has good (but still not perfect) support for arrays with arbitrary indices: Knowing where you are: custom array indices in Julia

4 Likes

What’s the idiomatic (performant) way of manipulating indices?
For example, suppose that I want to fill an Array A with the values of the function f, which depend on the indices, but require some manipulation, with another function g:

A = Array{Float64}(undef, 10, 20, 30)
for i in 1:10, j in 1:20, k in 1:30
    A[i, j, k] = f(i, g(j, k))
end

I encounter situations like this one very often.

Except for the order of the indices, I don’t see what else you should change. You could precompute the outer loop value g(j, k).