在 Perl 6 中创建一个 Maybe 类型 [英] Creating a Maybe type in Perl 6
问题描述
我有很多可能会失败的函数,但它们的签名中也定义了返回类型.因为我喜欢尽可能定义变量的类型,所以我想定义一个 Maybe 子集来使用它.我想出了这个:
I have a lot of functions that can fail, but also have a return type defined in their signature. Since I like defining the types of variables whenever possible, I want to define a Maybe subset to use for this. What I came up with is this:
subset Maybe is export of Mu where Mu | Failure;
问题在于 Failure
是 Mu
的子类,所以这将匹配任何东西,当我真正想要的是能够匹配一个特定的与 Failure
一起动态输入.我的下一个想法是创建一个参数化角色以用作类型,因为我不想为每个可能也是 Failure
的类型创建子集.我想它看起来像这样:
The problem with this is Failure
is a subclass of Mu
, so this will match anything and everything, when what I really want is to be able to match one specific type along with Failure
dynamically. My next thought was to create a parameterized role to use as a type, since I don't want to create subsets for every single type that could also be a Failure
. I imagine it looking something like this:
role Maybe[::T] {
# ...
}
sub foo(--> Int) { rand < 0.5 ?? 1 !! fail 'oops' }
my Maybe[Int] $foo = foo;
只有我不知道我需要为角色添加什么才能完成这项工作.是否可以创建这样的角色?如果没有,是否有另一种方法可以创建一个类型来做我想做的事?
Only I have no clue what I'd need to add to the role in order to make this work. Is it possible to create a role like this? If not, is there another way I could create a type to do what I want?
推荐答案
Perl6 类型已经是 Maybe 类型了.
Perl6 types are already Maybe types.
只是 Perl6 与大多数其他具有 Maybe 类型的语言不同,它具有类型化的空值.
It's just that Perl6 has typed nulls unlike most other languages with Maybe types.
这是Maybe[Int]
变量:
my Int $a;
my Int:_ $a; # more explicit
这里有一个明确的Int
:
my Int:D $a = …; # must be assigned because the default is not "definite"
这包含一个空 Int
:
my Int:U $a;
<小时>
请注意,Failure
是 Nil
的子类型,因此即使是指定了返回类型的子例程也可以返回它们.
(Nil
与其他语言中的 null
或 nil
不同.)
Note that Failure
is a subtype of Nil
, so even subroutines that have a return type specified can return them.
(Nil
is not like null
or nil
from other languages.)
sub foo ( --> Int:D ) { Bool.pick ?? 1 !! fail 'oops' }
my $foo = foo; # $foo contains the failure object
Nil
实际上是一种通用的软故障.当分配给一个变量时,它只是将其重置为默认值.
Nil
is really a type of generic soft failure. When assigned to a variable it just resets it to the default.
my Int $foo = 1;
$foo = Nil;
say $foo.perl; # Int
my Int:D $bar is default(42) = 1;
$bar = Nil
say $bar.perl; # 42
典型的默认值与类型相同.
The typical default is the same as the type.
my Int $foo;
say $foo.VAR.default.perl; # Int
一个特定的软失败是返回一个类型对象
A specific soft failure would be to return a type object
sub foo ( --> Int ){
Bool.pick ?? 1 !! Int
}
这就是为什么我说 Nil
是通用"软故障.
That is why I said Nil
is a "generic" soft failure.
通常,如果您要定义变量的类型,则希望它属于该类型.因此,如果您的代码得到其他类型的东西,它应该立即抱怨.
Generally if you are defining the type of a variable, you want it to be of that type. So your code should complain immediately if it gets something of another type.
有更好的方法来处理失败
.
sub foo(--> Int:D ) { rand < 0.5 ?? 1 !! fail 'oops' }
with foo() -> Int:D $foo {
… # use $foo here
} else -> $fail {
… # use $fail here
}
这是可行的,因为 Failure
总是认为自己是未定义的.
This works because Failure
always sees itself as being undefined.
您也可以将其与 when
given foo() {
when Int:D -> Int:D $foo {
… # use $foo here
}
when Failure:D -> Failure:D $fail {
# a DEFINITE Failure value
# (`DEFINITE` is different than `defined`.)
}
default {
… # handle unexpected values (can be removed if not needed)
}
}
或者只是定义或运算符 //
如果你不关心它是什么类型的失败.
Or just the defined-or operator //
if you don't care what kind of failure it is.
my Int:D $foo = foo() // 1;
您甚至可能想用它来将 Failure
变成 Nil
.
You may even want to use that to turn a Failure
into a Nil
.
my Int:D $foo is default(42) = foo() // Nil;
<小时>
如果你真的想要一个可能失败的子集,我认为这应该可行:
If you really want a maybe-failure subset, I think this should work:
sub Maybe-Failure ( Any:U ::Type ) {
anon subset :: of Any where Type | Failure
}
my constant Maybe-Int = Maybe-Failure(Int);
# note that the type has to be known at compile-time for this line:
my Maybe-Int $foo = foo;
它目前不起作用.
(注意你不应该处理 Mu
除非你需要专门处理 Any
类型之外的类型和值;比如 Junction
和 IterationEnd
.)
(Note that you should not be dealing with Mu
unless you need to specifically deal with the types and values that are outside of the Any
type; like Junction
and IterationEnd
.)
可能也应该起作用的其他东西是:
Something else that should probably also work is:
my class Maybe-Failure {
method ^parameterize ( $, Any:U ::Type ) {
anon subset :: of Any where Type | Failure
}
}
my Maybe-Failure[Int] $foo;
这似乎与另一个失败的原因相同.
This seems like it fails for the same reason the other one does.
另一种方法是创建一种新类型的类,例如 subset
.
那就是 subset
使用与 Perl6 中其他类不同的 MOP.
Another way would be to create a new type of class like subset
.
That is subset
uses a different MOP than the rest of the classes in Perl6.
这篇关于在 Perl 6 中创建一个 Maybe 类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!