TAKE Action

Carl Sassenrath, CTO
REBOL Technologies
6-Apr-2007 17:32 GMT

Article #0082
Main page || Index || Prior Article [0081] || Next Article [0083] || 13 Comments || Send feedback

A lot of language design is concern over little things - many little things.

There is a functional asymmetry in REBOL's series access model. It pops up when you write objects like I/O ports (which I tend to be doing a lot these days.) A voice has been telling me to fix this for a long time. (Is 8 years a long time?)

Those of you who use queues or stacks may already know what I'm talking about. Implement a queue (FIFO):

queue: make block! 20

; To enqueue (add new item):
append queue item

; To dequeue (get top item):
item: first queue
remove queue

(Note that in R3, first on empty queue is not an error, so the above works.)

The issue: that last section cannot be written as a single sentence. The function stream is interrupted, which becomes obvious in this case:

dequeue: func [queue /local item][
    item: first queue
    remove item

So, enqueuing is a singular series action, but dequeue cannot be.

This violates the "simple as possible" design rule of REBOL... because there is indeed a simple alternative.

The solution is:

; To dequeue (get top item):
item: take queue

Here, take is equivalent to a first and remove on the series. The dequeue function written above becomes trivial, so you no longer need it.

What if you want to take more than just one?

items: take/part queue 3

and now items is a series itself.

And finally, what about stacks?

We know that implementing a stack with top-at-tail gets us the best performance. So, we would want:

item: take/last queue

which roughly does a:

item: take back tail queue

We can also allow:

items: take/last/part queue -3

The reason for the negative number comes from this property:

items: take/part at queue 5 -3

So, take works anywhere within the series.


Updated 24-Jun-2024 - Edit - Copyright REBOL Technologies -