Generic Quoting Makes Headway on MAKE OBJECT!

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 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 it should be!

It's not necessary to put the apostrophe on all items, only those that 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. :face_with_monocle:

1 Like

It's amusing to see 2 years later that Red is only beginning to discuss the question.

Oldes says:

"To be honest, I'm not sure if it's correct in Red. I think Red's behavior is inconsistent.
I believe that these 3 results should not be same:"

red>> body-of make object! [a: 1 + 1 c: to lit-word! 'a]
== [
   a: 2 
   c: 'a

red>> body-of make object! [a: 1 + 1 c: 'a]
== [
    a: 2 
    c: 'a

red>> body-of make object! [a: 1 + 1 c: to word! 'a]
== [
    a: 2 
    c: 'a

They then try to discuss it, but of course they've rejected the techniques that can resolve it... generic quoting, an unset assignment form, BAD-WORD! notations...

I'll again point out that there are still fundamental issues with representing bound structures via a text-based round trip that should not be ignored. But, for the basic considerations here are fairly well considered. Even things like the difference between an isotope BAD-WORD! and a non-isotope:

ren-c>> obj: make object! [a: '~unset~, b: ~unset~]
== make object! [
    a: '~unset~
    b: ~unset~

ren-c>> obj.a
== ~unset~

ren-c>> obj.b
** Script Error: obj.b is ~unset~ isotope (see ^(...) and GET/ANY)

Since we're working on reminders of what META-XXX types do...they will allow you to get the value with a quoting level added, but it will bump the isotope to plain status:

ren-c>> ^obj.a
== '~unset~

ren-c>> ^obj.b
== ~unset~

There's simply a lot of solutions here bearing fruit, while their understanding has not moved an inch since Rebol2. :man_shrugging:


Another year down the road, they're talking about it again...issue opened May 15th:

Oldes demonstrates a flicker of awareness, here:

"Ren-C has some concept of multi-quoting. I suppose that you would use object [a: ''x b: 'x], but I don't have access to Ren-C for a try."


1 Like