在 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 是我定义的类(因此可以为其编写 Str 方法)而不是 Bool,有没有办法做到这一点?

(我知道我可以写更详细的 ("a",$a,"baz")«a list of words foo».Slip,«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 」,「 d e f 」 ) )

除了使用 .Slip 或前缀 | 之外,还有另一种方式可以获得您想要的东西。

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

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

也就是说,:words:quotewords:val 都对其进行了更改,使其返回的不是单个字符串。 他们的想法是改变 DSL。

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

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

,

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

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

如果 $a 是我定义的类(因此可以为其编写 Str 方法)而不是 Bool,有没有办法做到这一点?

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

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

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...