The Meaning of the FORM String Operation

So FORM's vague job is to give a "human readable representation" of the data it's given.

So for TEXT!, it gives you a representation of the string without delimiters--in contrast to MOLD, which gives you the delimiters:

>> form "hello world"
== "hello world"

>> mold "hello world"
== {"hello world"}

And you're probably thinking "Uh...FORM of a text string is a no-op. Why would you do that?"

The idea is that there are things other than text which do what the delimiters. Such as TAG!

>> form <hello world>
== "<hello world>"

>> mold <hello world>
== "<hello world>"

What if you don't want delimiters on your TAG!s and such? Well... for any string-ish type, thanks to UTF-8 we have a super efficient operation called AS TEXT! which aliases any type as a string. It reuses the memory:

>> tag: <hello world>

>> text: as text! <hello world>
== "hello world"

>> append tag "ly Ren-C user"
== <hello worldly Ren-C user>

>> text
== "hello worldly Ren-C user"

You can use it on ANY-WORD! as well, and it will give you a read-only string... and not have the sigils:

>> as text! '$var
== "var"

I have an inkling that over the subset of operations to which you can use both TO and AS, that you should get the same result... just a copy:

>> tag: <hello world>

>> text: to text! <hello world>  ; TO TEXT!, not AS TEXT!
== "hello world"

>> append tag "ly Ren-C user"
== <hello worldly Ren-C user>

>> text
== "hello world"

So FORM adds delimiters, and TO+AS TEXT! Does Not...

...BUT...let's go back:

>> form "hello world"
== "hello world"

>> form <hello world>
== "<hello world>"

Why again is FORM a no-op on text, but adds delimiters to tags?

And How About Blocks?

The block behavior of FORM historically strikes me as not terribly useful:

rebol2/red>> form [I am [:a "block" that:] <is> (being formed)]
== "I am a block that <is> being formed"

r3-alpha>> form [I am [:a "block" that:] <is> (being formed)]
== "I am :a block that: <is> being formed"

How often do you want to take a bunch of material and throw away decorations from some of it, and flatten out all the lists with no processing but spaces?

I don't think I've ever used that. I see more use in MOLD SPREAD, which it seems like R3-Alpha was edging toward and didn't quite get there.

>> mold spread [I am [:a "block" that:] <is> (being "formed")]
== {(I am :a "block" that: <is> (being "formed"))}

Who is Calling FORM (and why are they calling it?)

The variance in behaviors across R3-Alpha and Red show what is usually true when you see variation--people don't know why the thing exists, find out it has random behavior, then avoid using it in favor of other things.

Most uses seem to be turning WORD! to string, and turning TAG! to string with some assurance it will have the delimiters on it. Nobody really uses it on blocks.

I don't yet have a complete answer for either getting rid of it, or defining it rigorously. But I'm going to start paying more attention to it.

1 Like

I think it may be useful to compare the set of operations used in Haskell:

  • The main function is show. It can convert any type to String (well, any Show instance). The intention is that it should return a string with valid Haskell syntax, which can be printed for debugging purposes, or converted back to a Haskell value with read (although no-one ever uses read in practice). This is therefore Haskell’s equivalent to MOLD.
  • What a lot of people want is a function which can nicely pretty-print any value. People tend to co-opt show for this, but that breaks its usual behaviour. I believe a function for this is provided in third-party libraries, but simply by the nature of being third-party they’ve never gotten much traction.
  • Haskell doesn’t have many types like TAG! which are pure string wrappers. When they crop up, they tend to define their own individual functions for conversion to strings.

Compared to these, the behaviour you’ve described for FORM sounds dreadfully ad-hoc. No delimiters for TEXT!, delimiters for other string types, and something weird for blocks. I can think of no use-case for this.

I thus suggest getting rid of FORM entirely. It can easily be replaced with MOLD where delimiters are needed, and AS/TO TEXT! where they’re not. If someone really needs to strip off the delimiters for strings only (an unlikely scenario), they can use a conditional and make it clear that that’s really what they want.

1 Like