Why does 'reverse returns the tail of the block?
[1/9] from: al::bri::xtra::co::nz at: 12-Nov-2002 16:31
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? For example:
>> reverse next x: [1 2 3 4 5]
== []
>> x
== [1 5 4 3 2]
Though I'm not sure why one would want to only reverse part of a block (or
series)?
Andrew Martin
ICQ: 26227169 http://valley.150m.com/
[2/9] from: brett:codeconscious at: 12-Nov-2002 17:41
> 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? For example:
Probably a little more accurate to say that reverse returns the tail of the
changed sequence. Having reverse return a modified series reference probably
gives a little more info than just returning the original series reference,
especially when you include the /PART refinement:
>> s2: reverse/part at s1: [1 2 3 4 5] 2 3
== [5]
>> s1
== [1 4 3 2 5]
>> s2
== [5]
> Though I'm not sure why one would want to only reverse part of a block (or
> series)?
Insert, Change, Remove, Find, Copy, Uppercase all have a part sequence
effect - seems reasonable for REVERSE to have one too :^)
Regards,
Brett.
[3/9] from: g:santilli:tiscalinet:it at: 12-Nov-2002 12:39
Hi Andrew,
On Tuesday, November 12, 2002, 4:31:00 AM, you wrote:
AM> I suspect that 'reverse returns the 'tail of the block, because to return
AM> the 'head of the block could be wrong, if one is 'reverse-ing only part of a
AM> block? For example:
Indeed, it could be useful to chain two or more REVERSE/PART:
>> x: [1 2 3 4 5 6]
== [1 2 3 4 5 6]
>> reverse/part reverse/part reverse/part x 2 2 2
== []
>> x
== [2 1 4 3 6 5]
However, maybe it is more common to have it chained with other
functions, where returning the series at the same position as the
argument would be more useful. What do you think?
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[4/9] from: brett:codeconscious at: 13-Nov-2002 0:07
> However, maybe it is more common to have it chained with other
> functions, where returning the series at the same position as the
> argument would be more useful. What do you think?
If someone wants to chain it why not define a chainable reverse?
>> reverse0: func [value][reverse value value]
>> reverse0 s: [ 1 2 3 4]
== [4 3 2 1]
Regards,
Brett.
[5/9] 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.
<<quoted lines omitted: 4>>
> 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 ]
[6/9] from: rotenca:telvia:it at: 12-Nov-2002 15:13
Hi all,
it seems to me always the same behaviour:
>> reverse/part next b: [0 1 2 3] 2
== [3]
>> remove/part next b: [0 1 2 3] 2
== [3]
>> change/part next b: [0 1 2 3] [a a] 2
== [3]
Rebol returns the end of the changed/removed/inserted/reversed part of series,
if the part is all the serie, then it returns the tail of serie.
---
Ciao
Romano
[7/9] from: joel:neely:fedex at: 12-Nov-2002 10:51
Hi, Gabriele,
Gabriele Santilli wrote:
> However, maybe it is more common to have it chained with other
> functions, where returning the series at the same position as the
> argument would be more useful. What do you think?
>
I agree with preserving the position in the value yielded by REVERSE
as I think that's the most likely value to be relevant in a larger
expression.
It would be really interesting to examine a reasonably-sized sample
of REBOL scripts to see how often REVERSE is preceded by HEAD.
-jn-
--
----------------------------------------------------------------------
Joel Neely joelDOTneelyATfedexDOTcom 901-263-4446
[8/9] from: g:santilli:tiscalinet:it at: 12-Nov-2002 20:41
Hi Romano,
On Tuesday, November 12, 2002, 3:13:27 PM, you wrote:
RPT> Rebol returns the end of the changed/removed/inserted/reversed part of series,
RPT> if the part is all the serie, then it returns the tail of serie.
Indeed, but while this is very useful for CHANGE, REMOVE and
INSERT, it is not that useful for REVERSE, IMHO.
Anyway, there are cases where the current behavior of REMOVE is
useful, so I'm not saying that it is broken.
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[9/9] from: jeff:rebol at: 12-Nov-2002 16:15
<[3DCEBE3E--2DDAC72--sympatico--ca]> <[1822275075--20021111113147--tiscalinet--it]>
<006f01c289fb$ec2109e0$[4a6036d2--Garfield]> <[892917909--20021112123948--tiscalinet--it]>
Howdy, Gabriele:
> Indeed, it could be useful to chain two or more
> REVERSE/PART:
<<quoted lines omitted: 4>>
> >> x
> == [2 1 4 3 6 5]
As your example suggests, REBOL series functions always return
the end of the "affected area" because this might be the
result of some computed operation. Always returning the head
(or the current series index) would throw away the important
information of the affected index.
Salutations!
-jeff
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted