Given the [word "Value"] pattern is very common, I'd be loathe to force set-words in order to make that accessible. Aside from anything else, there'd be a dramatic rise in usage of QUOTE. My beef with (foo: [bar "Baz"], foo.bar) is that I feel it should be restricted to odd-numbered words (I have Red ticket #2850 open on this—had intended to open a parallel Ren-C ticket).
We could also consider block.'foo to mean a WORD!-search. Or we could try for block.['word] or block.[word:] or block.[<first> #second] as a way of searching for a general value or sequence of values.
It's just my feeling that the randomness of "I don't know what type it is" probably doesn't have a lot of good usages.
(Note: Since pathing itself has no refinements, any searching it does is fixed on a certain choice of "equality".)
The odd-numbering doesn't strike me as particularly useful in the dialect-driven world of Rebol. I kind of imagine formats where I might throw in comments or strings or have a dialect that augments some assignments:
stuff: [
"Maybe strings are commentary"
cool
x: 10
y: 20
/cool
]
It seems that being able to query SET-WORD!s is more generically useful. Maybe even to the point of never returning a SET-WORD!, but to keep skipping. So block: [foo: baz: 10] where block.foo and block.baz would both come back with 10.
My inclination is that tuple foo.bar notation is near exclusively associated with the notion of key/value-paired data. It's used with objects, ports, maps and predominantly key/value blocks. I'd suggest that having the following example work as expected is of greater value than hypothetical irregular dialects:
data: [foo bar bar baz]
data.bar
This is a longstanding frustration and source of confusion (and bugs).
I feel we're unpaving the cowpaths here. We're making it harder (and uglier) to do the most elementary and common things in the hopes that the set-word behaviour is more useful. I don't think tuples should get more complex—that complexity should be passed to functions like SELECT and FIND.
Carl did argue that Key: Value was Rebol's parallel to <Key>Value</Key>...
It all boils down to invariance. Who's writing this code that is supposed to be able to remain unchanged when you morph scores: [Bill: 7 Ted: 8] into scores: [Bill 7 Ted 8] or scores: [#Bill 7 'Ted 8]?
If these invariances are nonsense (I believe they are) then I don't see why having to use a construct that says what kind of thing you're looking for, scores.'bill vs scores.bill vs. scores.[#bill] is so bad.
I'm just not liking this fourth equality operator, the "one used by pick". If we are going to say:
picky-equal? 'foo: 'foo
== ~okay~ ; anti
Then it seems [foo:] and [foo] are also "picky-equal?", and I don't like that. Where does it stop?
I'd like us to kill off "pickquality" because its existence raises a lot of technical problems. But if we keep it, it needs to be reined in to specific use cases
A post was merged into an existing topic: Strict Equality, Lax Equality, Equivalence, Sameness
Let's Take This From The Top...
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 tuple 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 picking, 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 picking and poking, 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.)
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!?)
Given your demonstration block, what should block.x: 7 do?
I'd not be against giving this a try—my main objection to the Rebol 2 behaviour was the unexpectedness in the [a b b c] example. It would be good to have a literate counterpart—a refinement of SELECT (and FIND) that echoes the pathing behaviour. Not quite sure what that'd be for the poking equivalent though.
Good question, also what would block.y: 30 do. Presumably they'd either have to error -or- detach the set from the related instances, copying values if necessary. Also to consider: block: [final:] block.final: 10
Red recently revived old debates over whether SET-PATH! should be able to add to blocks, or if you should have to use append. OBJECT!s don't let you set or get keys that aren't there (which protects against typos), and don't let you delete keys...because integer-based existing bindings would be invalidated if those slots wound up being reused.
But I guess the thing to think about here is common use cases. Perhaps the real parallel is to MAP!, and arbitrary additions and removals should be allowed. I don't know, but either way there are more tools available to think about this.
As another point on BLOCK! and OBJECT! parity, people seemed to think you could SET an OBJECT! to a block.
rebol2>> o: make object! [x: 10 y: 20]
rebol2>> mold o
== {make object! [
x: 10
y: 20
]}
rebol2>> set o [30 40]
== [30 40]
rebol2>> mold o
== {make object! [
x: 30
y: 40
]}
Here we see a hardened assumption that objects have fields and they are ordered. Red has carried this assumption forward.
It complicates features that try to be "more than blocks". e.g. when R3-Alpha added "hidden" fields there was no definition of what SET via BLOCK! would do to it, so it just said "not allowed: would expose or modify hidden values."
But it suggests the kinship to blocks being far closer than one would think. This raises deep questions for the system. And I feel like there's no way to answer those questions without putting stakes in the ground and listing the things that must work.
(Clearly hiding fields doesn't have to work with SET. What's the justification that all bets are off then?)
6 posts were merged into an existing topic: Portable Bridge Notation (PBN) Parser
We've clearly come at this from a different perspective...
-
ME: Rebol is a dynamic medium with irregular parts that you're encouraged to mix up and compose and dialect in all kinds of wacky ways.
- I look at
[foo bar bar baz]and I see:[ سم الله الرحم 😈 ⠼⠚⠃]
- I look at
-
YOU: Live in a world where Rebol is the database as well as the language.
-
You look at
[foo bar bar baz]and are able to see:KEY VALUE +---------+---------+ | foo | bar | +---------+---------+ | bar | baz | +---------+---------+
-
I don't see that. I don't see this magic number 2, and even if I were to see the magic number 2, I don't see the KEY=>VALUE mapping because what if it said:
[foo bar bar baz bar mumble]
In object KEY=>VALUE access, the last SET-WORD! assignment in the creation wins. But when treating this as a keyed thing, presumably you want the first thing to win?
But that applies to any argument, whether you were seeking out SET-WORD! or not.
And I've struggled with the idea that PICK doesn't do equality matching for INTEGER! but treats that as an index:
>> block: [4 2 3 1]
>> block.3
== 3 ; not 1, as it would be if skipping by 2 and geting what's after a 3
So I think if these little blocks are just lexically light ways of specifying objects, you should treat them as an object specialization dialect and move on. I've suggested maybe imbuing {{...}} with that ability...
>> data: {{foo bar bar baz}}
== &[object! [ ; or map, or whatever, different discussion
foo: 'bar
bar: 'baz
]]
Then there's the idea that it's just some large dataset, loaded or has been constructed as a BLOCK!, and you don't really want to have to create a key/value structure for it. I really feel like if you're doing this, SELECT and FIND are probably the place to do it.
The uniformity pleases me, e.g. with SELECT 1
>> block: [4 2 3 1]
>> select block 3
== 1
Here you are beholden not to "pickquality" but to plain old equality. Your keys are expected to match what you're asking. You have a :SKIP count to say when your operations aren't implicitly going by 2 (with dialected function calls you could even put the skip count in the call)
And maybe SELECT should return a pack if you're selecting in this fashion:
>> block: [a b b b x y]
>> select:3 block 'b
== \~['x 'y]~\ ; antiform (pack!)
So it would by default decay to the first element:
>> block: [a b b b x y]
>> var: select:3 block 'b
>> var
== x
But you could capture up to (SKIP - 1) elements:
>> [var1 var2]: select:3 block 'b
>> var1
== x
>> var2
== y
That's... pretty cool, I think you'd agree.
It's a little weird that FIND skips 1 by default and SELECT skips 2 by default... but if this implicit idea has been found useful there's probably no reason to make SELECT skip 1 and force you to write select:2 to get a skip of 2.