Rebol didn't have any great answer for "object literals" and "map literals". Yet literal objects ("dictionaries") are critical to JSON. So it has seemed that Rebol needs an answer here.
Notationally we're at a bit of a loss of how to represent them. But something I began to wonder is if Rebol has been losing some of its advantage of having a SET-WORD! type. If you look at:
array: [foo <baz> #bar]
dictionary: [field1: ... field2: ...]
Couldn't it just be that the presence of SET-WORD!s in the dictionary-like thing is what gives you the tip-off? Why exchange files with literal objects, instead of doing it with blocks? The kinds of data exchanges we see using such forms are not rigorously glued to a schema--by design--the concept is that the sender and recipient are on the same page about things.
There may be little benefit to having another container type saying "this is an object", if objects and blocks act more or less interchangeably when used with keyed access. The user of the data would have the option to make a block into an object if they needed to, or not if they didnt?
I've suggested before that I feel there's something wrong with "pickquality", where it's the idea that picking and pathing consider WORD!, SET-WORD!, ISSUE!, etc. to be equal. I felt that if BLOCK!s are used for keyed access in this way, they should use SET-WORD!s...and then the seeking process in the block can look specifically for them. If we use "scant evaluation", then this could even allow for SET-WORD! values.
Demonstration
block: [
<meta-tag 1> <meta-tag-2> #meta-issue
string: "hello"
x: y: 100
code: '(1 + 2)
setword: 'something:
]
>> block/string
== "hello" ; skips info before set-word!
>> block/x
== 100 ; advances to first non-set-word value
>> block/code
== (1 + 2) ; "scant" evaluation, removes quote
>> block/setword
== something: ; also "scant" evaluation
Imagine being able to manipulate the block in a way that has parity with how it would act if it were an object. So getting the quoting if necessary:
>> block: [thing: 10]
>> block/thing: first [a b c]
>> block
== [thing: 'a]
You don't want path access to trigger an actual evaluation of something that isn't inert or quoted, so that should give an error:
>> block: [thing: (1 + 2)]
>> block/thing
** Error: keyed access of block only works on inert and quoted types
To me, this really feels like a coherent direction, with something that has been very lacking in coherence historically.
Cowpaths
@rgchris very much likes the freedom in blocks to say [a 1 b 2] and not [a: 1 b: 2]. So his direction of cleanup of the historical behavior would be to treat blocks as collections of 2-element records, which would prevent confusion if you wrote [a b b 2].
I appreciate wanting to have this choice. But for pathing, I like this parity with objects idea. I do not feel like enforcing the SET-WORD!s at odd numbered positions feels like the right choice there...I'd like to be able to be more free-form, as I would be able to do with MAKE OBJECT!. It addresses several dark corners, and I think that it will make blocks stronger for data exchange.
Pathing and selection are already not the same (as block/2 gives you the second item of the block, not an item immediately following an INTEGER! 2 inside the block). If we changed SELECT to a /SKIP default of 2, and went with the SET-WORD!-based behavior for pathing (hence also PICK+POKE), would that make everyone happy?
>> select [a b b 2] 'a
== b
>> select [a b b 2] 'b
== 2
And I'd suggest that SELECT would have you use the data type you were selecting on. So it would not consider SET-WORD! and WORD! the same (nor ISSUE! and WORD!, etc.) With skippable functions to do the equality, you could ask for varying behaviors:
>> select [a 1 10 20] .matches integer!
== 20 ; e.g. a wasn't an INTEGER!, but 10 was (1 skipped going in steps of 2)
And one of those behaviors could ask for a more lax style of comparison which considered SET-WORD! and WORD! to be equal. .synonymizes
, perhaps. or .wordequals
>> select [a 1 b: 20] .wordequals first [a:]
== 1
>> select [a 1 b: 20] .synonymizes 'b
== 20
In any case, the idea is that the SELECT command is about treating a block as records of fixed size. I don't know if that means that it should not be used with objects (preferring PICK). It might be clarifying. PICK is a shorter word.
(I also don't know what the applications are to having SELECT default to 2 characters at a time when selecting from strings. But then again, I'm not really sure what sort of scenarios would get people to select out of a string in the first place, if all you get back is a single character. Should it be limited to just ANY-ARRAY!?)