Red's Take on String Interpolation

I've proposed that COMPOSE be arity-2 and able to interpolate strings, e.g.

>> num: 10

>> print compose ${{}} "Number is {{num}}, so there."
Number is 10, so there.

Having to say compose ${{}} is noisy for day to day use of a common construct like PRINT.

But even this trivial case shows a benefit of being able to put the comma right up against the number if you want to. 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.

An experiment interprets BLOCK! in the source as grouping things tightly:

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

Still, it's lousy compared to interpolation (see hiiamboris's examples for other ones).

What If PRINT of a TEXT! did "Sneaky Interpolation"?

We could make it so that PRINT is one of the sneaky constructs that captures the binding from its callsite, and that it assumes some interpolation delimiter:

>> 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.

It Could Be An Option

There could be some way of turning this behavior on or off, and specifying what the delimiters are.

Maybe the default PRINT wouldn't have it, but you could say:

/print: make-sneaky-print '(())  ; note unbound, since it captures binding

It's a little bit of a relearning of habits to know that plain print str would have this extra processing overhead. But, I think it is learnable, and I'd definitely use it.

Other Options: Brief Operators, 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.

It could also be an operator you could make arbitrarily brief:

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.

It could be the result of some decoration:

print @["Number is {{num}}, so there."]

But that's not what that is intended to mean.

It could be done with a different string type:

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

print <Number is {{num}}, so there.>

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

It seems to me that giving the power to a plain PRINT is the most useful.

Most Likely Alternative: Sneaky COMPOSE

I've debated if COMPOSE should use sneaky binding, and maybe it should.

Maybe its default should be {{...}} as well, and just make that out of band, as something that doesn't get other meaning in the system.

>> compose '[(1 + 2) {{3 + 4}} {5 + 6}]
== [(1 + 2) 7 {5 + 6}]

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

print compose:with $() "Number is (num), so there."

Or maybe the default should stay at (...) for the natural brevity:

>> compose '[(1 + 2) {{3 + 4}} {5 + 6}]
== [3 {{3 + 4}} {5 + 6}]

print compose "Number is (num), so there."

print compose:with ${{}} "Number is {{num}}, so there."

It's just that parentheses seem so common in code and text that you'd often be pushing them out of the way.

I still feel like having it built into PRINT is a sort of convenience that it's hard to like any extra word in there, even just COMPOSE. And if it's built-in, then {{...}} seems better than (...)

1 Like