Negative indexing as Rebol2/Red compatible... just do it?


>> pick next [a b] 1
== b

>> pick next [a b] 0
== none ;-- Red proposes error, which was also the revised R3-Alpha proposal

>> pick next [a b] -1
== a


>> pick next [a b] 1
== b

>> pick next [a b] 0  
== a

>> pick next [a b] -1
== none

The decision to make this change in R3-Alpha was before my time. But what I know of it, is that it was motivated by some people feeling the "hole at 0" made it hard for mathematics-like algorithms to index into arrays.

It also seemed to be that changing it didn't really please anyone that much.

The general concept behind PICK is to try and be a kind of "natural, do what I mean" selector. Ren-C has taken this further by making it come back with an answer that's the same as what pathing does (hence it's "path picking" and not "path selection"). So pick a/b 'c acts like a/b/c...they run the same code.

People who want more numerical access can use SKIP, which navigates series predictably by a number of elements...including 0.

There was a lot of talk about how to change the indexing back safely, but I have to wonder, can we just change it, call it done, and move on? There's not that much negative indexing going on in general with PICK. And we have the wherewithal to generate some kind of log to help debug anyone who merges a negative indexing change and it breaks things.

(I was provoked to look into this because there's an old list of stray tests that were only run under Rebol2, and I feel like it's time to get rid of that file by going ahead and doing triage on everything in here are the tests that involve indexing, so they can be deleted from there. No it's, not much!)

[1 = pick at [1 2 3 4 5] 3 -2]
[2 = pick at [1 2 3 4 5] 3 -1]
[none? pick at [1 2 3 4 5] 3 0]
[#"1" = pick at "12345" 3 -2]
[#"2" = pick at "12345" 3 -1]
[none? pick at "12345" 3 0]

For some things changed in R3, it is ok to change those back to R2 way of handling. I think this one fits that view especially because you point out the alternative with SKIP does what you want in this case.

1 Like

Trying to decide on a binary choice between the intent of PICK being more "natural selector" or "mathematical" array access was probably a mistake. A bit too much "let's minimise what's in the box".

There's a performance angle too. In Rebol 2, it was known that the fastest way to modify a series was not using CHANGE but to use POKE. When using POKE one naturally thinks to PICK rather than SKIP.

I'm also unsure if the semantics of SKIP are enough to satisfy a mathematical style access.

So I'm in favor of going back to Rebol2's PICK but wonder if a PEEK could satisfy the fast mathematical access intent scenario.

In the change which unified PICK and pathing, it also unified POKE and set-pathing. So poke 'a/b 'c 10 would do the same thing as a/b/c: 10...because it ran literally the same code. It also unified with GET and SET, so that get 'a/b/c would give you the same thing as :a/b/c and set 'a/b/c x would give you the same thing as a/b/c: x (modulo some details). Previously, there were all kinds of behavior deviations of each choice. :-/

PEEK and POKE are "obscure" words, and tend to go together in other languages. One would think of them as a pair. Maybe having them be zero-based would make sense, and not doing any of the bizarre things that pathing do (like no getting you a FILE! back from f: %foo | f/bar).

Red added PUT, which is a writing variant of SELECT. x: [a 10 b 20] then put 'a 30 gives you x of [a 30 b 20]. But PICK and PUT might go together better than PICK and POKE?

Wilder options--which I bring up now and again--is to make / a specific type (SLASH!, perhaps) and have the evaluator know about it, and do pathing with it. x / y: z could be like poke x y z is today. Getting that to work generically would require SET-GROUP! and GET-GROUP!, e.g.:

:(x x x) / y: z
x / (y y y): z

But I've wanted those anyway. And then maybe the named forms could be zero-based?