Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: Why does 'reverse returns the tail of the block?

From: joel:neely:fedex at: 12-Nov-2002 7:04

Hi, Andrew, Another wild guess below... Andrew Martin wrote:
> Jan wrote: > > > worst of all 'reverse, which returns empty block. > > Gabriele wrote: > > I don't know why REVERSE returns the tail of the block. > > You can use HEAD REVERSE in expressions,... > > I suspect that 'reverse returns the 'tail of the block, because > to return the 'head of the block could be wrong, if one is > 'reverse-ing only part of a block? >
But those aren't the only two options! IMHO the more intuitive thing would be to return a block reference positioned at the same place as the beginning of the reversed sequence (see below for example). I'm inclined to wonder whether the resulting value is merely an artifact of the way REVERSE is implemented, rather than being carefully chosen for some strategic purpose.
> For example: > > >> reverse next x: [1 2 3 4 5] > == [] > >> x > == [1 5 4 3 2] >
In the variation I'd advocate, your example would behave as the following *H*Y*P*O*T*H*E*T*I*C*A*L* case
>> reverse next x: [1 2 3 4 5]
== [5 4 3 2]
>> x
== [1 5 4 3 2] As it is, we can get roughly the equivalent behavior only at the cost of some extra typing ...
>> reverse y: next x: [1 2 3 4 5]
== []
>> y
== [5 4 3 2] ... to preserve the position of the series (sub-) reference. REBOL seems in general to follow the principle of returning results that are most likely to be useful in a larger expression (e.g. INSERT returns a reference *after* the inserted content, making it easy to "chain" insertions into a single expression). That principle is broken here IMHO as every use I can recall making of REVERSE falls into one of two categories: 1) Imperative - purely for effect, in which case I don't *care* how the resulting value is positioned, or 2) In-line - needing to perform some additional manipulation on the result, in which case I *always* have to write the equivalent of ... head reverse ... to get back to the beginning of the REVERSEd content. I'd much rather have REVERSE return a preserved position.
> Though I'm not sure why one would want to only reverse part of > a block (or series)? >
Most (all?) operations on series values respect the current position within the underlying sequence. Consistency with that rule is A Good Thing IMHO. A specific example of how this could be used is the "line breaking" problem: given an ordered collection of values and a position within the collection, bring the value at that position to the "front of the line" without disturbing the relative order of the rest of the values in the collection. An obvious approach is to insert the designated value (i.e. the value at the designated position) into the front of the line, and remove it from its previous place. This is easy to write: breakline-ins-rem: func [ s [series!] p [integer!] ][ head remove at insert s pick s p p ] It behaves as specified ...
>> breakline-ins-rem [1 2 3 4 5 6 7 8 9] 4
== [4 1 2 3 5 6 7 8 9] ... but we know that INSERTing and REMOVEing (in blocks with many values following the point of action) can be expensive. A subtler approach can be designed as follows: - REVERSEing a subseries at the beginning will put the desired element at the head of the line, but will mess up the relative order of the values that were before it:
>> head reverse/part [1 2 3 4 5 6 7 8 9] 4
== [4 3 2 1 5 6 7 8 9] - We can prevent that by REVERSEingthe *preceding* values first, and then REVERSEing the entire leading subseries:
>> head reverse/part [1 2 3 4 5 6 7 8 9] 3
== [3 2 1 4 5 6 7 8 9]
>> head reverse/part [3 2 1 4 5 6 7 8 9] 4
== [4 1 2 3 5 6 7 8 9] This gives us another design ... breakline-rev-rev: func [ s [series!] p [integer!] ][ head reverse/part head reverse/part s p - 1 p ] ... which only manipulates the part of the series that actually needs to change! This latter version can be *much* faster, depending on the length of the series and how close the desired position is to the front. -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]