在 Raku 中不创建 String 上下文进行插值?

Interpolate without creating a String context in Raku?

如果我有一个变量 my $a = True,那么我从下面的代码中得到这个输出:

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

也就是说,即使结果是 List,元素 True 在被包含在列表中之前被字符串化 – 列表包含 "True",而不是 True.有没有办法在仍然使用插值的同时避免这种字符串化?

如果 $a 是我定义的 class(因此可以编写 Str 方法)而不是 Bool?

(我知道我可以写更冗长的 ("a", "list", "of", "words", "foo", $a, "bar", "baz")«a list of words foo».Slip, $a, «bar baz».Slip,但我想问是否还有办法继续使用插值)。

插值是将一个东西放入一个字符串中。

"a b c $thing d e f"

它首先将事物本身变成一个字符串,然后将字符串的其余部分连接起来。

基本上上面的编译成这段代码:

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

« a b c $thing »

是以下简称:

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

即使用Quoting DSL,开启:double引用语义(“”)并开启:quotewords.

:quotewords 是将字符串拆分为各个部分的功能。 只有在它变成字符串后才会发生。

假设上面编译成:

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

除了使用 .Slip 或前缀 |.

之外,还有另一种方法可以获得您想要的内容
flat «a list of words foo», $a, «bar baz»

引用 DSL 的全部目的是生成一个字符串。

也就是说 :words:quotewords:val 都会更改它,以便它 returns 不是单个字符串。 他们的想法是他们改变了DSL。

所以可能你可以说服足够多的人相信这样的改变是值得的。 那是一个很大的也许

它可能会破坏许多现有的代码库,因此您将面临一场艰苦的战斗。

这里发生的事情与引用关系不大,而与 context 关系很大。正如@brad-gilbert 所指出的,任何通过将 ~ 放在前面的方法都会将变量强制转换为 String 上下文。

但这可以回答你的第二个问题:

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?

理论上,这样的事情应该可行:

class A { 
    has Bool $.foo;
    method Str { $.foo }
};
my $a = A.new( :foo(True) );
say «a b $a».raku

唉,这个 returns «No such method 'WORDS_AUTODEREF' for invocant of type 'Bool'␤ 所以它可能需要一些工作(或者我可能遇到了一些错误)。因此,目前,对于您的精确示例,这是 nanswer。事实上,只有 Str 有那个方法,所以我认为暂时,除非你费心为 class 创建那个专门的方法,否则很难做到。