类型强制绑定

dol*_*men 3 raku

我正在尝试在签名中使用类型强制。

如何修复该my Chars(Str) @a := 'hello';行以使此代码正常工作?

class Chars is Array {
        submethod new(Str:D $s) {
                nextwith(|$s.comb);
        }
}

use MONKEY-TYPING;
augment class Str {
    method Chars { Chars.new(self) }
}


say Chars.new("hello").raku;
say "hello".Chars.raku;

my Chars(Str) @a := 'hello';

@a.raku.say;
Run Code Online (Sandbox Code Playgroud)

rai*_*iph 5

你还没有说你要做什么作为一个实际问题,所以这个答案试图在字里行间阅读。幸运的是,它可能接近你想要的,或者至少是教育性的,或者离你很远。无论哪种方式,如果您通过评论和/或编辑您的答案来回应此答案,我可能会使其更有用。

我对你所追求的事物的最佳猜测

以下似乎工作正常,但不暗示保证:

subset Char of Str where .chars <= 1;
say Char ~~ Str;         # True

class Chars is Array[Char] { multi method new (Str:D $_) { samewith |.comb } }

my @a is Chars;

say @a.WHAT;             # Chars

@a = Chars.new: 'foo';
say @a;                  # [f o o]
say @a.elems;            # 3
say @a.of;               # Char

@a = 'buzz'.comb;
say @a;                  # [b u z z]
say @a.elems;            # 4

@a = '4', '2';
say @a;                  # [4 2]

@a[3] := '9';
say @a;                  # [4 2 (Char) 9]

@a[4] = '100';           # Type check failed in assignment to ;
                         # expected Char but got Str ("100")
use MONKEY-TYPING;
augment class Str { method Chars { Chars.new: self } }

my (Chars(Str) $a) := \'hello';
say WHAT $a;             # Str
say $a;                  # [h e l l o]
$a[1..3] = 'bar'.comb;
say $a;                  # [h b a r o]
Run Code Online (Sandbox Code Playgroud)
  • 我引入了一个Char 子集来对应单个字符串类型约束,并在is Array[Char]声明/定义Chars 时使用该约束。

  • 我用过samewith,没有nextwith。如果你把它改回来并运行我的代码,你就会明白为什么。

  • 类型检查错误消息很奇怪:“分配给;”。

  • my @a is Chars是new和相应类型约束到符号永久编译时绑定。Chars @a

更字面地回答你的问题

类型强制绑定

我的 (Chars(Str) $a) := '1'; 说 $a.WHAT; #(字符)

我正在尝试在签名中使用类型强制。

使用签名一词表明:

sub a (Chars(Str) $a) { $a }
say WHAT a '1'; # (Chars)
Run Code Online (Sandbox Code Playgroud)

或者,不太可能:

my Chars $a;
:(Chars(Str) $a) := \'hello';
Run Code Online (Sandbox Code Playgroud)

语法:(...)指定了一个独立的签名。它们很少使用,有点奇怪。例如,如果您绑定到一个独立的签名,那么其中的任何变量都必须存在于绑定发生的直接词法范围内。就像常规签名一样,它们绑定到Capture. 与调用例程时发生的例程签名绑定不同,编译器不会将:=绑定的 RHS (相当于例程的参数)转换为Capture适合您的,因此您必须这样做,例如通过使用\捕获运算符。

但我强烈怀疑这就是你所追求的。


如果您真的有兴趣在例程之外声明一个变量,那么可以使用列表声明语法(即使您只绑定到一个变量):

my (Chars(Str) $a) := \'hello';
Run Code Online (Sandbox Code Playgroud)

额外的括号会有所不同。但是您仍然必须使用绑定和捕获。

而且,奇怪的是(或者我只是太困了?),如果您尝试分配,则不会发生强制:

my (Chars(Str) $a) = \'hello';
say WHAT $a;                    # Str
Run Code Online (Sandbox Code Playgroud)

我该如何解决my Chars(Str) @a := 'hello';

如果您尝试它,您将看到如下错误消息:Coercion Foo(Bar) is insufficiently type-like to qualify a variable

如果绑定到签名,则必须绑定Capture.

您正在声明一个带有@符号的变量。这意味着其左侧的类型约束约束变量的元素,而不是整个变量本身。也就是说,像这样的my Chars @a;声明会声明一个Array[Chars]. 鉴于我上面的代码,这将是一个Array[Array[Char]]由单个字符元素组成的数组。我很确定你不是那个意思。