There have been several other good comments on this question, but here are a few more for this discussion.
If you know that your code will always work on (1:3)
arrays, say they are Cartesian space coordinates, then specifying that slice might be a good idea because it tells other programmers (or you yourself) that the variable is an array rather than a scalar within an expression. But if your current problem just happens to have bounds 1:3
, and you might need to change this in the future to some other upper bound, then it might be better to either remove the slice notation entirely (and use a whole array expression instead) or change the slice to simply (:)
. This way, your code will adjust automatically if you ever change the upper bound.
When this occurs on the lhs of an expression, there are also complications related to the automatic reallocation. If you know that the lhs is allocated and is already the correct shape, then
a(:,:) = b
a = b
should do the same thing, but perhaps with different amounts of effort. I’m using a 2D example here just to show that this is general, not specific to 1D arrays. In that first expression, the compiler might first check that the arrays (or the expression on the rhs in the general case) conform. In this context, it means that they have the same extents in all dimensions (ignoring the array=scalar special case here). It does not mean that the lower and upper bounds must match, just that the extents all match. That array shape check requires a little effort, but not much. Typically the subsequent memory to memory copy will require more effort than the check. If this expression occurs in a tight loop, then a programmer might even specify through optimization compiler options that the check can be removed. In this case, the programmer is assuming all responsibility for the shape matching in order to get the most efficient runtime performance.
But if the allocation status of the lhs is unknown to the programmer, then the second expression might be used. This expression requires that the compiler test for allocation of the array a(:,:)
, and allocate it appropriately if necessary before the assignment operation occurs. It will allocate the array of the correct shape and with the default lower bounds of 1 in all dimensions. If the programmer wants different bounds, then he must assume the responsibility for the allocation test, the allocation, and for setting the bounds.
The language standard is a little ambiguous about what happens in the second expression when the shapes match, it only specifies clearly what happens when they don’t match. Thus the compiler must check, typically at run time, if the shapes match. When the shapes match, then the programmer might reasonably expect the lhs will retain its original allocation and with its original bounds. However, a compiler is allowed to reallocate even in this case. A consequence of this is that upon execution of the statement the bounds of the lhs array might change, and pointers to the lhs array become dissociated from their original targets. Of course, it might also mean that the assignment statements takes more effort than necessary. Allocation, especially heap allocation that is typically associated with allocatable arrays, is an expensive operation. However, there are also cases where the reallocation might require less effort, e.g. where the assignment is achieved with a move_alloc() kind of operation. I think that is why the language standard has remained ambiguous on this particular point for the last two decades, it wants to allow compilers the freedom to implement this potentially very efficient optimization technique for whole array assignment.
This ambiguity then places more responsibility on the programmer who wants to write the most efficient code. If the programmer wants the move_alloc() kind of operation, then he can program it explicitly. If the programmer wants to avoid the shape tests and the allocation, then he can write the lhs with slice notation, (:,:)
. If the programmer don’t care about any of that, then he can write the assignment as a whole array expression.