In Rebol 2 there was a HASH! type as well as a MAP! type. Both of which were supported by the FIND and SELECT functions, as well as by path-based selection:
>> m: to map! [someKey someValue]
== make hash! [someKey someValue]
>> m/someKey
== someValue
>> select m 'someKey
== someValue
To detect that a key wasn't in the map, you could use FIND and test against NONE
>> find m 'someOtherKey
== none
But path-based selection would get an error in this case:
>> m/someOtherKey
** Script Error: Invalid path value: someOtherKey
** Near: m/someOtherKey
On the other hand, Rebol 3 only has MAP!. But FIND and SELECT only support series types, and MAP! is not considered to be a series any longer. The only way I see (?) to interact with maps is through path selection, which does not throw an error in the non-membership case:
>> m/someOtherKey
== none
...and if your key is in a variable (or a string) you have to use PAREN!
>> var: 'someKey
== someKey
>> m/(var)
== someValue
That works in Rebol 2 also, but with the same caveat of throwing an error instead of returning NONE when you ask for something that doesn't exist.
So if I'm getting this right, path selection is the "common" way of retrieving values from keys in Rebol 2 and 3. Despite that, I'm not seeing a common way of testing for lack of membership. How does one handle this?
Three things to note:
Most immediately pertaining to your question: select
works fine in Rebol 3 as well, as the following interaction shows:
>> system/version
== 2.100.111.4.4 ; That's Rebol 3 A111.
>> m: map [a 1 b 2 c 3]
== make map! [
a 1
b 2
c 3
]
>> select m 'b
== 2
>> select m 'd
== none
By looking at the spec of select
in R3 (using e.g. ? series
), we also quickly find out that it accepts values of the following types as first argument: series!
, port!
, map!
(!), object!
, none!
.
R2 does not really have a map!
type. It is faked using hash!
as part of the "R2/Forward" forward-compatibility layer for R2. (Look at what result you get from to map! [a 1 a 2]
in R2 and R3 to see how this may hit you.)
Note that with select
you can not really distinguish between keys without any associated value or keys associated with #[none]
as value. If you really need that distinction, it's easy to do in R3, where you can use words-of
to retrieve the keys of a map!
:
>> words-of map [a 1 b 2]
== [a b]
However, that was not yet back-ported to R2.
One more portable way which, however, may be considered relying on implementation internals, is to convert map!
(R3) or hash!
(R2) back to a block!
, and using extract
to obtain only the keys:
>> m: to map! [a 1 b 2]
>> extract to block! m 2
== [a b]