Search code examples
stringrakustring-interpolationrakudo

Interpolate without creating a String context in Raku?


If I have a variable my $a = True, then I get this output from the following code:

say «a list of words foo $a bar baz».raku; 
# OUTPUT: ("a", "list", "of", "words", "foo", "True", "bar", "baz")

That is, even though the result is a List, the element True is stringified before being included in the list – the list contains "True", not True. Is there any way to avoid that stringification while still using interpolation?

Would there be a way to do so if $a were a class I'd defined (and thus can write the Str method for) rather than a Bool?

(I am aware that I can write the more verbose ("a", "list", "of", "words", "foo", $a, "bar", "baz") or «a list of words foo».Slip, $a, «bar baz».Slip, but I'm asking if there is a way to still use interpolation).


Solution

  • Interpolation is putting a thing into a string.

    "a b c $thing d e f"
    

    It does that by first turning the thing itself into a string, and concatenating the rest of the string around it.

    Basically the above compiles into this code:

    infix:<~>( 「a b c 」, $thing.Str, 「 d e f」 )
    

    « a b c $thing »
    

    Is short for:

    Q :double :quotewords « a b c $thing d e f »
    

    That is use the Quoting DSL, turning on :double quote semantics (“”) and turning on :quotewords.

    :quotewords is the feature which splits the string into its individual parts. It happens only after it has been turned into a string.

    Imagine that the above compiles into:

    Internals::quotewords( infix:<~>( 「 a b c 」, $thing.Str, 「 d e f 」 ) )
    

    There is another way to get what you want, other than using .Slip or prefix |.

    flat «a list of words foo», $a, «bar baz»
    

    The whole purpose of the quoting DSL is that it produces a string.

    That said :words, :quotewords, and :val all change it so that it returns something other than a single string. And the idea of them is that they alter the DSL.

    So MAYBE you could convince enough people that such a change would be worth it. Thats a big maybe.

    It would potentially break many existing codebases, so you would have an uphill battle to do so.