Rebol2/R3-Alpha/Red have a notation for molding out objects:
Red>> obj: make object! [a: 10]
== make object! [
a: 10
]
Let's ignore for the moment the fact that it's giving a sequence of what looks to be two words and a block to denote a single OBJECT!. What it's trying to do is give you a syntax that looks like what it would take to create the object if typed from source. (Perhaps it would more appropriately be SOURCE OBJ vs. MOLD OBJ)
Little Objects with Big Problems
What if you said:
Red>> obj: make object! [g: quote (1 + 2) u: 0 unset 'u w: quote 'word n: none]
== make object! [
g: (1 + 2)
u: unset
w: 'word
n: none
]
The resulting MOLDing MAKE OBJECT! doesn't get close to what it's trying to capture.
-
In the original object G is a "PAREN!" with (1 + 2). Running that MAKE OBJECT! would give you G of INTEGER 3.
-
We'll assume it meant #[unset] instead of the word UNSET
-
To run as written, it would confusingly pass the UNSET function the next line as an argument. It would do
unset w: 'word
, thus unsetting word -
If it had said
u: #[unset]
instead, the make object! would have failed, as it's not legal to assign unsets via set-word in historical Rebol or Red.
-
-
W would come out as a WORD! here, instead of the LIT-WORD! in the original object.
-
N here might seem to work, but it only works so long as the word NONE is bound to #[none]. So round-tripping this field depends on the context you run the make object in.
Generalized escaping to the rescue
Ren-C doesn't have a full solution to the problem of round-trip representations as text. But now, when it comes to this, it's at least a powerful step closer.
>> obj: make object! [g: lit (1 + 2) u: ~unset~ w: the 'word n: null]
== make object! [
g: '(1 + 2)
u: ~unset~
w: ''word
n: '
]
Here we see these loopholes getting closed. The make is actually able to produce a structurally identical object (like I said, let's avoid talking about binding, that's its own conversation).
And reconstructing the object is context-independent...no keywords are being used. Note that I threw in a NULL for good measure, to show that there's a representation for that... a QUOTED! of absolutely nothing. So (n: ') acts the same as (n: null).
- In fact, (null: ') is the very definition the NULL word has in the bootstrap code!
UPDATE FOR THE AGE OF ISOTOPES: the
n: ~unset~
in the object is indicative of the isotopic form. If it were a non-isotopic BAD-WORD! then it would show up as n: '~unset~. But by omitting the quote, it's set to regenerate the isotopic form on evaluation...as it should be!
It's not necessary to put the apostrophe on all items, only those that evaluate...so the system should probably only add them if needed:
>> obj: make object! [i: 10 t: "hello" p: ''a/b/c]
== make object! [
i: 10
t: "hello"
p: ''a/b/c
]
INTEGER! and TEXT! can be left as-is, so perhaps worth it to do so. Here we see a LIT-PATH!, escaped in the original representation for its assignment, escaped again for its re-representation.
This generalized-escaping-based mechanism replaces a previous attempt to deal with the issue, and gives strong evidence that the effort was time well spent.