在 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 »
即使用Q
uoting 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 创建那个专门的方法,否则很难做到。
如果我有一个变量 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 »
即使用Q
uoting 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 创建那个专门的方法,否则很难做到。