Question

What is the most succinct way of removing the last element in a Rebol series?

Options I have found so far are

s: "abc"
head remove back tail s

and

s: "abc"
take/last s
Was it helpful?

Solution 2

Here I wrote a REMOVE-LAST function,

remove-last: func [
    "Removes value(s) from tail of a series."
    series [series! port! bitset! none!]
    /part range [number!] "Removes to a given length."
] [
    either part [
        clear skip tail series negate range
    ] [
        remove back tail series
    ]
]

Example use:

b: [a b c d e f g]
remove-last b ;== [], 'g removed, tail of the series return.
head remove-last/part b 2 ;== [a b c d], 'e and 'f removed

It returns the tail of the series to be able to use in following situation;

b: [a b c d e f g]
head insert remove-last b 'x  ;== [a b c d e f x]

OTHER TIPS

Define "best". Highest performance? Most clarity? What is it you want the expression to return at the end, or do you not care? The two you provide return different results...one the head of the series after the removal and the other the item removed.

If you want the head of the series after removal, you need take/last s followed by s to get that expression. Comparison:

>> delta-time [
    loop 10000 [
        s: copy "abc"
        take/last s
        s
    ]
]
== 0:00:00.012412

>> delta-time [
    loop 10000 [
        s: copy "abc"
        head remove back tail s
    ]
]
== 0:00:00.019222

If you want the expression to evaluate to the item removed, you'd need to compare take/last s against something convoluted like also (last s) (remove back tail s)... because also will run the first expression and then the second...returning the result of the first:

>> delta-time [
    loop 10000 [
        s: copy "abc"
        take/last s
    ]
]
== 0:00:00.010838

>> delta-time [
    loop 10000 [
        s: copy "abc"
        also last s remove back tail s
    ]
]
== 0:00:00.024859

etc.

If you don't care about the result, I'm going with take/last. If you do care about the result and want the head of the series, I'm going with take/last s followed by s. To me that reads better than head remove back tail s, although it's an aesthetic choice. It's still faster, at least on my netbook.

If you want the tail of the series at the end of the expression, remove back tail s is surprisingly similar in performance to take/last s followed by tail s. I'd say the latter is more explicit, and probably preferable, in case the reader forgets the return convention of REMOVE.

And also last s remove back tail s looks terrible, but is a reminder about also, which is pretty useful and easy to forget it's there. FWIW, it performs about the same as using an intermediate variable.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top