How Should You Request PRINT With Interpolation?

So it's been settled, I think, that COMPOSE is allowed to use the context of its callsite.

This makes it suitable for string interpolation: even though strings don't have bindings, COMPOSE can just use any variables visible to its frame:

>> num: 1000

>> print compose "Number is (num + 20), so there."
Number is 1020, so there.

It's very useful, and even this trivial case shows a benefit of being able to put the comma right up against the number if you want to. Traditionally that's hard to do as PRINT typically adds spaces around everything. So you have to do something like this:

>> print unspaced ["Number is" _ num ", so there."]
Number is 10, so there.

Wacky experiments of the past tried to make it nicer by interpreting BLOCK! inside the PRINT's block as grouping things tightly:

>> print ["Number is" [num ","] "so there."]
Number is 10, so there.

But that's lousy compared to interpolation.

Can we do better than PRINT COMPOSE for how you request interpolation?

PRINT STRING Interpolates, PRINT [STRING] Does Not?

We could make it so that PRINT presumes you want interpolation if you pass it a string:

>> num: 10

>> print "Number is (num), so there."
Number is 10, so there.

Then we could say that if you don't want that, you can put the string in a block:

>> print ["When using a block, (...) would not interpolate."]
When using a block, (...) would not interpolate.

There's another option to pass PRINT an @var, and if you did then that would suppress interpolation as well.

>> str: "Number is (num), so there."

>> print str
Number is 10, so there.

>> print [str]
Number is {{num}}, so there.

>> print @str
Number is {{num}}, so there.

Other Names...?

This could be a different word like echo or say or something like that, though I'm not crazy about either of those.

A Really Brief Operator?

print op "Number is {{num}}, so there."

But I don't know there's anything on the list of short words that would make the cut for "very short way to ask for COMPOSE"

Different String Type... e.g. TAG! ?

>> print <Number is (num), so there.>
== Number is 10, so there.

TAG! doesn't seem completely crazy, though I have other ideas for what TAG! means inside of PRINT as a formatting instruction.

Out of all these suggestions I probably like the TAG! one the best, so far.

1 Like

On PRINT, I tend towards not doing implicit interpolation there. But it could work quite well as a refinement: print:interpolate "Number is (num)".

The key is making it very light, and not to break the readability flow.

print* might be light enough, with the * warning "I'm doing extra processing on this string" (and "I'm doing implicit environment capture"?)

>> print* "Number is (num)"
Number is 10

There's also print+... a little less noisy, but maybe too much so... the + blends a bit and looks like a T, right against a T.

>> print+ "Number is (num)"
Number is 10

I can empathize that there needs to be something there to clue you into the extra work going on.

It may look nicer--but it is less efficient to have to scan the code every time. (Though investing on making that scan fast helps the whole system.)

A post was split to a new topic: Why Parentheses As Default COMPOSE Escape?

In the "radical ideas" category...

We have TEXT! with hyphens, as -{...}- or --{...}-- etc. even though {...} means something else.

TAG! is headed toward using -<...>- and --<...>-- etc. as a supplement to <...> (and possibly required for multi-line tag)

As of yet, there's no meaning for -(...)- or --(...)-- OR -[...]- or --[...]-- but it seems to me the most sensible thing would be if it they were string types.

What if it we had a string type that evaluated the groups in it as an interpolation?

>> -(What about (1000 + 20) this?)-
== "What about 1020 this?"

>> -[Or perhaps (1000 + 20) this?]-
== "Or perhaps 1020 this?"

The -(...)- version might be vaguely semiotic, that the parentheses give a hint that it is evaluative. A string type that evaluated using the "block" brackets seems a bit less consistent.

Since it handles things in evaluation, that means you don't have to worry about slipstreaming environmental sensitivity into every construct... PRINT can work with it, FAIL can work with it, etc.

It does have the advantage of being a 2-character asymmetric delimiter, so you can put not just parentheses inside but quotes and such also...

It's a little weird, and if you didn't like it you wouldn't have to use it, but it's a nontrivial savings on typing and clutter:

>> print -(Number is (num), "so there".)-
== Number is 10, "so there".

>> print compose -{Number is (num), "so there".}-
== Number is 10, "so there".

8 characters.