[REBOL] Pre-REP on NONE! and SERIES! polymorphism
From: joel::neely::fedex::com at: 10-Jun-2002 7:48
Since we've been discussing enhancements recently, let me offer a
common situation (at least in my experience) and ask the collected
wisdom of the list for thoughtful opinions...
There are several REBOL features for working with series values
that are quite comfortable with an empty series:
foreach item foo [print item]
find foo bletch
select foo bletch
Evaluating each of the above with an empty series will nicely
obey the "Principle of Least Surprise" and
do nothing
yield none
yield none
respectively. However, all of the above will choke if FOO is
set to NONE instead. It still seems reasonable in that case for
the expressions to
do nothing
yield none
yield none
IMHO. Given that (for example) PARSE-XML provides NONE instead
of an empty block for the attribute portion of XML elements that
have no attributes, and for the content portion of XML elements
that have not content (and I could give other examples where
compound data structures could have NONE rather than an empty
block due either to simpler initialization or missing data),
I often find myself wrapping FOREACH, FIND, and SELECT with
tests to ensure that the argument is a series instead of a NONE
value, even though I'd be perfectly happy with NONE to behave
exactly the same as an empty series.
So, what to do...?
1) Keep using wrapper code.
2) Define appropriate wrappers and use those wherever needed,
e.g.:
find?: func [s [series! none!] v [any-type!]] [
if found? s [ find s v ]
]
3) Propose a REBOL enhancement...
3a) ...of additional natives FIND? SELECT? and FOREACH?
3b) ...of refinements FIND/ANY SELECT/ANY and FOREACH/ANY
(or /NULL or /EMPTY or whatever...)
3c) ...asking for FIND SELECT and FOREACH to be extended to
accept NONE as a first argument.
Of course, (1) is kludgy but simple on a case-by-case basis,
(2) is straightforward but adds the overhead of function eval
to every use (significant in inner loops, of course), and
(3) is political (and might appear to contradict my POV on
keeping the /Core as focused as possible ;-)
Since the issues here involve BOTH convenience (addressed by all
options but (1)) AND performance (addressed only by (3)), I'm
interested in the views of the list.
OBTW, the above function could certainly have been written
find?: func [s [series! none!] v [any-type!]] [
all [found? s find s v]
]
instead; are there any other interesting variations (just as a
matter of coding style, clever hackage, etc.)?
-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 ]