objectrebolrebol3

How to use IN with a block instead of an object?


The IN function in Rebol finds out if a field is in an object:

USAGE:
    IN object word

DESCRIPTION:
    Returns the word or block in the object's context.
    IN is a native value.

ARGUMENTS:
    object (any-object! block!)
    word -- (modified if series) (any-word! block! paren!)

The claim is it works with objects or blocks. It works okay if I try it with an object:

>> in object [foo: 10 bar: 20] 'foo
== foo

But if I just try it with a raw block, it gives back NONE:

>> in [foo: 10 bar: 20] 'foo
== none

Guess I'd understand if it didn't support blocks (Rebol2 didn't). But what's the case in which it wouldn't return NONE that blocks are allowed for?

And at the risk of making this two questions in one, what's the deal with accepting BLOCK! for the word parameter? I'd think it would take a block if you had a set of words you were looking for, but it seems to just return the block:

>> in object [foo: 10 bar: 20] [mumble frotz bar]
== [mumble frotz bar]

>> in object [foo: 10 bar: 20] [mumble frotz]
== [mumble frotz]

And at the further risk of making this three questions, what meaning would taking a PAREN! for word have?


Solution

  • The IN function isn't primarily meant for searching an object for a word, it is for returning a word or block of words that are in the object, or in Rebol terms bound to the object. It's a variant of the BIND function that is useful in different circumstances than BIND.

    If there is no word of that name in the object, it returns none, sensibly enough. This gives it the side benefit of being able to be used in conditional expressions as a word detection function, but that's not its main use.

    IN can take a block of objects for its object parameter and then try to bind the word to each object in turn, returning a word bound to the first object in the block that has that word. This was meant as a relatively quick way to do overriding word lookup for an old design of the Rebol 3 GUI, but it turned out to not be the best approach in that case so the GUI doesn't use that design now. However, IN block word was kept as a potentially useful feature for future use elsewhere.

    In your example, there were no objects in that block, so there was nothing that IN could bind the word to. That is why IN returned none.

    If you pass IN a block for the word parameter, it binds the block to the object before it returns it. This is to allow code like do in obj [print a]. It doesn't do a bind/copy though, so you should be careful about code like that. Or maybe IN object block should copy - is it too late to change that? Passing a paren for the word argument should have the same binding behavior as passing a block.

    When last I checked, we didn't support having both the object an word parameters be blocks. This is because we couldn't figure out a good model for what that behavior should be, at least obviously. The overriding word lookup doesn't really work with a block of words because the results would be inconclusive.

    It would be useful to have a function that rebound a block to a series of objects in order, especially for recreating Rebol's not-really-nested scopes, but it would be really confusing for that function to be IN.