TAKE Action
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
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.
13 Comments
|