To reiterate an earlier point: There's something inconsistent about saying case-preservation is important, but then systemically not heeding case. When an optimization caused a historical case-preservation to lose it, I called this bad:
>> obj: make object! [Some-Name: 10]
>> block: [some-name, some-other-name]
>> bind block obj
>> block
== [Some-Name, some-other-name] ; ack, where'd my case go?!
I think it would be also bad if everything got lowercased automatically by the system:
>> block: [Some-Name, Some-Other-Name]
== [some-name, some-other-name]
SO...if we can agree both of those situations are bad...then why wouldn't we agree that this r3-alpha behavior is bad?
r3-alpha>> load/header "Rebol [Title: {My Title}]"
== [make object! [
title: "My Title" ; Hey, I said `Title:` !
name: none
type: none
; ...
]]
As is Rebol2's habit of going the other way:
rebol2>> print mold load/header {Rebol [title: {my title}]}
make object! [
Title: "my title" ; This time I said `title:` !
Date: none
Name: none
; ...
]
It just goes to show you can't have it both ways. Case-Preservation and Case-Insensitivity are fundamentally at odds.
But this is unfortunate:
>> [code header]: load "Rebol [title: {my title}]"
>> header
== make object! [
Title: "Untitled" ; ... huh?
Date: _
Name: _
; ...
title: "my title" ; ... grrr.
]
If we tuned OBJECT! to use the same trick that MAP! does at the moment, it could error when you do a case-insensitive access:
>> select header 'title
** Object has different key cases for `title`, use SELECT/CASE
>> select/case header 'title
== "my title"
>> select/case header 'Title
== "Untitled"
Doing that test efficiently would require keeping track of if object keys have synonyms; so each object expansion would need to re-check that and update some bits.
FAIL was the only example I had of deliberately using case to "stand out". I found no others, and apparently I've always stuck to the capitalization in file headers.
The best way to maintain sanity might be to couple my "error if multiple cases exist by default" above with "force case to match by default." It could give intelligible errors:
>> header/date
** Object does not have `date` field, but has `Date`
But we can't let multiple cases break binding in a case-sensitive world, because then if you have multiple cases of the same word anywhere in the user context it would conflict.
>> o: make object! [Title: {Thing}]
; `Title` is now in the user context, because all words are bound into the
; user context *before* the code runs (and makes it a field in the object).
; If you are unclear on this point, re-read:
;
; https://forum.rebol.info/t/the-real-story-about-user-and-lib-contexts/764
>> title: "hello!"
>> title
** If this errors there's already `Title` then that's bad
So binding would have to be one of the /CASE
tolerant operations, which makes sense in this concept.
We have some interesting options for saying "I mean it", like doubling up slashes in the path:
>> header/title
** Object has different key cases for `title`, use SELECT/CASE
; ^-- more than likely, this generates an "uh oh" and people would then
; look and say "why is there more than one case"
>> header//title
== "my title"
; ^-- could be a nice syntax for getting things case-sensitively out of
; MAP! as well
And I've already mentioned there might be nuances between .
and /
, though I don't want any nuances that make me less likely to use .
because I think it is going to be my preferred field selector. So above I'd probably want header.title to error on the ambiguity, because that's the safer behavior, and say header..title if I meant there's a Title:
too and I'm aware of that fact.
Altogether, I'm just about convinced about case-sensitive binding. There are some epicycles to deal with, but it's rather telling that I got a working system so quickly. We know somewhere that case-insensitive comparisons have to be offered, but I think you don't want it anywhere that comes into conflict with the ability to do case-preservation, which means object keys have to preserve case...hence binding itself has to be case-sensitive.