PRINT for empty BLOCK!, empty TEXT!, or Text of Just Spaces

I just wrote something I thought was kind of neat, a way to do indentation via COLLECT:

print [collect [repeat indent [keep tab]]], "some indented stuff"]

So if INDENT were 3 this would act as:

print [[#"^-" #"^-" #"^-"] "some indented stuff"]

This made me feel like the historical answer of PRINT treating a BLOCK! of material as if it were a set of already-reduced and calculated parts was probably a good answer. In the past I've questioned it, but I think the value is demonstrated right there.

(I'll also point out that with GET-BLOCK!, we'll have a nice way of asking to reduce the block first... print ["For instance:" :[your vars here]]...this lets you mix up spaced and unspaced parts easily!)

But then I noticed it was screwing up in the base case of zero indentation, e.g.

ren-c>> print [[] "some stuff"]
 some stuff

There's an extra leading space there. :frowning: Checking Red, it does the same thing:

red>> print [[] "some stuff"]
 some stuff

It made me wonder, does Rebol2 do this?

rebol2>> print [[] "some stuff"]
some stuff

Oddly no. Did R3-Alpha?

r3-alpha>> print [[] "some stuff"]
some stuff

Again no. Is it putting spacing around non-empty blocks?

r3-alpha>> print [["test"] "some stuff"]
test some stuff

Well, yes. But what if that string were empty?

r3-alpha>> print [[""] "some stuff"]     
some stuff

The reason Red and Ren-C have the extra space is because there's a generic handling of turning values into strings that adds spacing even if a string is empty.

But waitasec: How does Rebol2 know psychically in advance whether a molding operation is going to produce content or not? It would have to use a separate buffer, and I can't imagine Carl doing that.

So let's try something else:

rebol2>> print ["here's" [] "some stuff"]
here's  some stuff

There's the extra space, due to not being psychic.

We see some weird exception was made regarding empty strings that didn't have a holistic answer. Red and Ren-C both lack that broken weird exception.

So what can we do to get desirable results in a non-broken way?

Empty BLOCK! Should Act The Same As NULL

I've been firm on the "detail" that NULL vaporization really means it's as if it weren't there, and the spacing acts appropriately:

>> print ["here's" if false ["!!!"] "some stuff"]
here's some stuff

That's one of my non-negotiables. Now I'm going to add another to the list:

>> print ["here's" [] "some stuff"]
here's some stuff

It's tempting to add another one, which is to not put spacing around empty strings:

>> print ["here's" {} "some stuff"]
here's some stuff

The reasoning is that I don't see why robotically putting spacing around an empty string would ever be useful. But this is a slippery slope. What if the string contains just spaces, let's say 4?

>> print ["here's" {    } "some stuff"]
here's    some stuff

Should there be 4 spaces in that gap? 5 spaces? 6?

Mechanically the easiest answer would be 6...which is to say that it's agnostic about the string contents and just puts one space before and one space after. Doing anything else requires analyzing the molded content, which is methodized in the general case.

But the empty string case doesn't really require you to analyze the molded contents. It just requires you to notice how much the pre-delimiter added to the molding buffer...and then if the buffer didn't get any longer during the molding operation, backtrack the buffer index behind the now-superfluous delimiter.

To my mind it's worth it to just make the exemption that empty moldings do not get delimited. It's a more useful behavior and puts Ren-C once again in the clear lead for usage sanity. :slight_smile:

1 Like

Okay, I take this particular bit (empty string) back.

Imagine the delimiter is not a space, but say... a colon.

>> field1: "one"
>> field2: ""
>> field3: "three"
>> delimit ":" [field1 field2 field3]
== [one::three]

You want that second colon there. And technically speaking there's no reason you couldn't use spaces as a delimiter for a format that required spaces to be escaped in the content (or not allowed at all).

But I'm going to say an empty block with no contents has more in common with null than an empty string.

If you are unhappy that empty strings are giving you two spaces, then use nulls/blanks like you are supposed to.