Raku中的Haskell型模式匹配
Haskell和Rust(以及我不知道的mabye其他语言)有一个他们称之为“模式匹配”的命运。以下是Haskell的一个例子:Raku中的Haskell型模式匹配,haskell,functional-programming,pattern-matching,raku,Haskell,Functional Programming,Pattern Matching,Raku,Haskell和Rust(以及我不知道的mabye其他语言)有一个他们称之为“模式匹配”的命运。以下是Haskell的一个例子: data Event=HoldKey Char | PressKey Char | Err String someFunc=let someEvent进程keySym 错误->退出错误 在Keepodingstaff 在Raku,最接近这一点的似乎是多方法多功能(术语在下面的答案中固定,但多方法也可以工作) 但是,如果我想要一个“本地”模式匹配表达式(如上面hask
data Event=HoldKey Char | PressKey Char | Err String
someFunc=let
someEvent进程keySym
错误->退出错误
在Keepodingstaff
在Raku,最接近这一点的似乎是多方法多功能(术语在下面的答案中固定,但多方法也可以工作)
但是,如果我想要一个“本地”模式匹配表达式(如上面haskell代码片段中的case
表达式),这就没有帮助了。大概是这样的:
given Hold.new(:key<a>) {
when Hold (:$key) { say $key }
when Press (:$key) { say $key }
when Err (:$msg) { say $msg }
default { say "Unsupported" }
}
给定保持。新建(:键){
当按住(:$key){say$key}
按(:$key){说$key}
当Err(:$msg){say$msg}
默认值{say“Unsupported”}
}
这不是编译的。那么,我是否遗漏了什么,或者Raku是否可以用其他方式表达这一点?您试图在不需要签名的情况下使用签名 签名更可能是块的一部分,因此看起来更像这样:
given Hold.new(:key<a>) {
when Hold (:$key) { say $key }
when Press (:$key) { say $key }
when Err (:$msg) { say $msg }
default { say "Unsupported" }
}
给定保持。新建(:键){
当按住->(:$key){say$key}
按->(:$key){说$key}
当Err->(:$msg){say$msg}
默认值{say“Unsupported”}
}
这在当前不起作用,因为块没有任何参数
可以说,这将是一个需要添加的有用特性
请注意,
给定的
只做两件事
继续
和成功
以完成$设置为您给定的值
$\uu
已设置为您要智能匹配的值
给定保持。新建(:键){
何时按住{say.key}
当按下{say.key}
当Err{say.msg}
默认值{say“Unsupported”}
}
您尝试的语法实际上非常接近。以下是您想要的:
class Hold { has $.key; }
class Press { has $.key; }
class Err { has $.msg; }
given Hold.new(:key<a>) {
when Hold { say .key }
when Press { say .key }
when Err { say .msg }
default { say "Unsupported" }
}
类保持{has$.key;}
类Press{has$.key;}
类Err{has$.msg;}
给定保持。新建(:键){
何时按住{say.key}
当按下{say.key}
当Err{say.msg}
默认值{say“Unsupported”}
}
需要注意的几件事:正如语法的变化所显示的,您正在匹配Hold
的类型,但您没有对Hold
进行解构。相反,您正在利用这样一个事实,即当
块将块内的主题变量($\ucode>)设置为与匹配项相等
其次(看起来您已经意识到了这一点,但我将添加它以供将来参考),需要注意的是,给定的
块不能保证穷举模式匹配。你可以用一个默认的{die}
块来模拟这种保证,但这当然是一个运行时检查,而不是编译时检查。我同意在Raku中有优雅的语法会很好。但从功能上讲,我认为Raku比你想象的更接近你所描述的
在拉库,最接近这一点的似乎是多重方法
Raku确实支持多种方法。但你展示的是多功能
我也认为多功能是Raku目前最接近你描述的东西。但我也认为他们比你现在认为的更接近
我想要一个“本地”模式匹配表达式
多功能是局部的(词汇范围)
类保持{has$.key;}
类Press{has$.key;}
类Err{has$.msg;}
{
匹配Hold.new::key;
多重匹配(保持(:$key)){say$key}
多重匹配(按(:$key)){say$key}
多重匹配(Err(:$msg)){say$msg}
多重匹配($){say“unsupported”}
}
#匹配;谢谢你的全面回答!我同意,在使用支持模式匹配的语言时,我非常喜欢依赖模式匹配。不过,你给出的另一种方法似乎已经相当强大了。这种特性在过去曾被推测过。从正在进行的dispatch工作到明年即将推出的新编译器前端,它的实现和性能可能会比今天更容易。是的,这就是我在上述评论中所说的“替代方法”,遗憾的是,无法访问更高级的模式匹配功能。您在类定义中缺少空格对齐方式,这让我很难受,默认块也是如此^_^查找“函数式编程”和“模式匹配”表明它只是语法上的糖分,具体的Raku示例可能会在上找到,尽管我希望@JonathanWorthington这样的人可能会纠正我,如果不是这样的话。请看:我想这就是@raiph在他的回答中所说的:模式匹配基本上已经通过多功能在Raku中出现了。在这一点上,我真正想要的是匿名表达式中的模式匹配,它可以使用synctatic sugar与Raku的多函数或C#s/C++s/Java/etc一起实现。。。访问者模式(如中所述)。不幸的是,Raku缺乏一个稳定的宏系统来自己实现这种糖(也被@raiph提到)。@jubilatious1只展示了给定的表达式,它并不真正支持完全模式匹配。对于任何对此感兴趣的人来说,这可能值得一读,通过使用多功能模式匹配和真正的代数数据类型(与我的bear类相反),这更进一步。此外,这也是一个很好的例子,说明了为什么Raku宏系统是一个非常好的主意haha@dincio“不幸的是,Raku缺乏一个稳定的宏系统来自己实现这个糖。”Fwiw一个人现在可以使用grarmmars/actions/slags,即非宏功能实现任何想要的语言变异。而且它至少是稳定的。也就是说,变更受st
class Hold { has $.key; }
class Press { has $.key; }
class Err { has $.msg; }
{
match Hold.new: :key<a> ;
multi match (Hold (:$key)) { say $key }
multi match (Press (:$key)) { say $key }
multi match (Err (:$msg)) { say $msg }
multi match ($) { say "unsupported" }
}
# match; <--- would be a compile-time fail if not commented out
match Hold.new: :key<a>
-> Hold (:$key) { say $key }
-> Press (:$key) { say $key }
-> Err (:$msg) { say $msg }
else { say "unsupported" }