FIND and SELECT polymorphism

In Rebol2, you can run FIND on OBJECT! as well as on BLOCK!:

rebol2>> obj: make object! [a: 10 b: 20]

rebol2>> find obj 'a
== true

rebol2>> find obj 'asdf
== false

I'll point out that Red does not support FIND on OBJECT!, and that was intentional. There's no real explanation other than than something approximating "objects and bitsets don't support a lot of series operations because they don't necessarily make sense".

But Red allows FIND on maps, for some reason?

red>> m: make map! [a 10]
== #(
    a: 10
)

red>> find m 'a
== a

Is This A Polymorphism You Can Even Use?

There's no real clarity in OBJECT!/BLOCK! duality. I've tried to invent some out of the murk, but come up short.

We might ask ourselves:

Has there ever been a situation where you've had something--you didn't know what it was, either an OBJECT! or a BLOCK!--and your generic code can meaningfully use a FIND call on that thing?

I can't imagine the answer to that is yes. :roll_eyes:

BUT... what about something you didn't know if it was an OBJECT! or a MAP! ?

You can pass a WORD! to IN for an OBJECT!, and get either a bound word back in that object or NULL. But you can't use IN on a MAP.

So the only polymorphic operators you can use to determine if something is in either an OBJECT! or a MAP! these days are FIND and SELECT. Ren-C has the advantage that SELECT returns NULL if-and-only-if something isn't in a map or object, so even if you don't need the selected item you can use it.

Some Line Of Argumentation Might Support Rebol2's Behavior

To truly generalize FIND, you could consider it to be with respect to an iterator... e.g. how C++'s find works.

We might then look to FOR-EACH to see what it would give you if you asked it for a generic "something". R3-Alpha supports this (not Rebol2 or Red):

r3-alpha>> obj: make object! [a: 10 b: 20]

r3-alpha>> foreach something obj [print mold something]
a
b

So maybe if all of that was built on some common infrastructure, you could build a rationale for why searching keys-only made sense for FIND in an object.

But it's not built on any common infrastructure, so it's just extra random code.

Moreover, what About BITSET! ?

Above I made a potential case for seeing FIND as applying to the keys of an object. But... BITSET!?

If you say bs: make bitset! 8 and then bs.4: true, you're making something kind of like a block:

[0 0 0 1 0 0 0 0]

So semantically, why would find bs 4 be true? Where's the 4?

I think what this really is more like is a positional PICK (which makes sense because bs.4: true is running the code poke bs 4 true, and bs.4 acts as pick bs 4)

But..it may be a potentially interesting polymorphism to think of a bitset as a mapping from integers to LOGIC!. You might swap in something that is using a BITSET! to use a MAP!. So SELECT with integer could be coherent here.

I think PICK is the best choice, though.

Anyway...I'm removing FIND on Maps/Objects/Bitsets for Now...

For the moment, I think that did select or didn't select are the best invariant ways of detecting if things are in objects or maps. (Or use with ELSE/THEN)

This leaves FIND as something that might be more dialected, with options that let you search the values and not just the keys (maybe search deeply?)

Also it saves us from returning the kind of hokey idea of "true or null". I'm suspicious of most functions that are in situations where they only return true or null, anyway.