last day (15 days later) » 

11:10
4
Q: Which programming language first used negative indexing to mean counting from the end?

qwrNegative indexing is a well-known feature of Python, for example a[-1] gets the last element of list a. Which programming language was the first to do this? (FORTRAN has supported arbitrary indexing for a long time, but -1 is simply another index. This 1965 article proposes that behavior as an ex...

Assembly language would be the oldest and most basic, and it lets you do anything. So it has been possible from the beginning. Are you restricting this question to higher level languages that can be compiled to run on multiple architectures?
@AlexCannon Assembly language doesn't have a concept of arrays or strings. OP is asking about indexing into a 'range' where positive indices are from the start of the range and negative indices are from the end of the range. You are thinking about positive and negative offsets from an address.
@hippietrail I tend to object. The x86 even calls the "S" mnemonics (MOVS, LODS, STOS, CMPS, SCAS) "string instructions".
@AlexCannon - Nevertheless, FOO[-1] is not 'the last element' but 'the probably-unallocated element before the first element'. Sure, you can plant an end label so FOOEND[-1] is the last element of FOO, but that is not very different from FOO[FOOLEN-1] in any language with indexing.
If you consider Mathematica a programing language and consider Mathematica lists arrays, then it's probably that. I don't know any other programming language that interprets negative array indices (if it even allows them) as "from the end".
qwr
qwr
11:10
@AlexCannon as @hippietrail said, I am specifically asking about a language where you would write a[-1] in the source and it will index counting from the end, not offset from the start.
@tofro the x86 string instructions only operate on strings in terms of comparing two memory addresses and incrementing a pointer, so more like arrays
That is my definition of a string - an array of characters. Do you have a different one?
qwr
qwr
C mixes the two, but in later languages arrays and strings are treated as separate types in a typing system
@hippietrail The VAX family of CPUs, introduced in 1977, supported arrays in hardware. The assembler just went along for the ride. Indexed addressing involved taking a base address and adding the value of the specified index register multiplied by the size of the operand. Ref Index Mode. The use of negative index values with the semantics the OP refers to was not supported.
@HABO is that different from normal index registers / indexing addressing modes? I kind of think of all those as pointer support since I think of arrays as having an end (or size) as well as a beginning. But there's more than one way to think about these things.
@qwr I was never much for Python though I used it a tiny handful of times. Yet I know I often test new languages I play with with this technique, so I'm pretty sure I became aware of it somewhere other than Python, but I'm not sure where or when.
Neither ABC nor SETL, precursors to Python, have the feature.
11:10
@hippytrail if a = a + sizeof(a); then a is now set one beyond the end of the array, and a[-1] now gets the last element. But the question must be about a programming language that does this automatically
@hippietrail Two differences: There were no dedicated index registers, the index was taken from any of the general purpose registers. The index value was multiplied by the operand size, not just added to the base address, e.g. an ADDB instruction multiplied the index by 1 and a SUBH instruction multiplied by 16 (for an H-float). Aside: There was also support for strings, e.g. MOVTUC (MOVe Translated Until Character) that moves a character string using a translation table for each character until a specified character is found. Definitely a CISC architecture.
On some platforms, indexing using short subscript types would be faster than using subscript types that could reach all of memory. On the 6502, for example, if a pointer is in zero page, ldy index; lda (ptr),y would be much faster than 16-bit pointer computations. If a language were to use [] to indicate subscripting with an 8-bit index, then when using a 256-byte array, arr[-1] would naturally be equivalent to arr[255]. Not sure if that inspired the use of such conventions elsewhere, but such a thing could have been an antecedent.
Interesting, how many interesting, but totally irrelevant comments this question seems to invite.
@hippietrail But the CPU part of Assemblers (aka CPU-instructions) do have such. But given, it's not many offering a 'from the end' addressing - plus a few where this works as a fringe case.
@tofro it's RC.SE. Eventually the most knowledgeable bunch of nerds. Like all nerds having a hard time to hold back information :))
@AlexCannon Well, Assembler can do most/all of that - after all, any serious assembler is based on/ capable of macros - by implementing/using a string/array type. Keep in mind, language features are more often than not runtime/library based additions. Capable Assemblers are around since at least the mid 1960s.. In ASSEMBF one could write (already without macros) STRING+L'STRING-1 to access teh last element of a string (or array for that matter - which would even adjust according to basic data type - string beeing just the application of byte).

last day (15 days later) »