2017-04-09 55 views
7

也许我真正的问题是“这是否适合学习Perl 6”?基于Should this Perl 6 CATCH block be able to change variables in the lexical scope?,似乎最简单的例子可能超出了一个简单的例子。我什么时候需要恢复Perl 6异常?

在那个问题中,我正在处理一些对于特定问题而言似乎愚蠢或者更好的东西,因为我正在玩特性而不是解决问题。

有警告的记录使用作为特殊类型的异常(“控制异常”),你得到的消息,可以捕捉它,如果你喜欢,但也可以忽略它,它会自行恢复(虽然我是这在Where should I catch a Perl 6 warning control exception?中相当愚蠢)。

除此之外,我正在考虑调用者可以处理被调用者范围之外的失败的事情。例如,重新连接到数据库,修复丢失的目录以及被调用者没有责任的其他外部资源问题。

在阅读其他语言的这类内容时,建议主要是不使用它们,因为在“真实世界”编程中,人们往往不会真正处理问题。

C# exception handler resume next的答案似乎是说这是不好的做法和丑陋的代码。我当然还没有想到在被调用者中隐藏一堆代码的方法。

我砍掉了这个例子,虽然我不相信这是一个很好的方法来做它或推荐给初学者。该程序在启动时查找PID文件。如果它找到一个,它会抛出一个异常。处理该异常将检查其他实例是否仍在运行,这可能会引发不同类型的异常。而且,还有一个可以处理文件IO问题。诀窍是X::MyProgram::FoundSemaphore可以恢复,如果其他程序没有运行(但留下PID文件)。

+1

对于这个问题不重要,但请注意'BEGIN'在编译时运行。模块在安装时编译,因此放置在模块中的代码可能不会完成预期的工作。 'INIT'对于程序启动似乎是一个更好的选择,并且在模块情况下可以正常工作。 –

+0

是的,INIT似乎更好。 –

回答

6

可恢复的异常肯定不是东西,我发现自己深远的Perl 6中我使用他们在“用户空间”的代码在所有但我不认为。一个可恢复的例外结果是实现emit函数的正确方法,在supplyreact块中使用。 gather中使用的take函数也使用可恢复的异常实现,并且 - 如您已经发现的那样 - warn使用它们。

我怀疑最后一个 - warn - 是典型的Perl 6用户感兴趣的唯一情况。捕获警告并将它们发送到其他地方 - 可能是日志文件或日志服务器 - 是一个相当合理的事情需要做。就学习Perl 6而言,这可能是可恢复异常的一个明显有用的例子。

我认为所有利用Perl 6中的可恢复异常的用例本身都被归类为“控制异常”是很重要的。控制异常在执行级别上基本上是正常的异常:它们涉及非本地控制转移。他们在语言级别上做出不同的,因为这将是比较尴尬的,如果你的emittakewarnnextlast使用Perl 6等等停止,因为一个CATCH块的一个default吞咽控制异常的工作!

但是,它也有点像我说的那样做,而不是像我这样做:虽然Perl 6很乐意使用异常系统来实现非本地流量控制,但它在一个满是灰尘的角落的语言,而不是把它当作一件事情的例子。出于好的理由:通常情况下,使用异常来执行流量控制的代码很难遵循,而且对于可恢复的异常来说,这是双倍的。另一个很大的风险是,这种例外情况可能被代码所吞噬,代码使用的是tryCATCHdefault--这使得它在更大的代码库中变得相当脆弱。

我想象一下,可恢复异常的最佳用途将成为用户根本不会考虑异常的实现策略 - 就像takeemit(和,大部分时间,warn)。并且,与现有的可恢复异常的例子一样,恢复的事件将是一种异常类型,其被专门设计为在可恢复的情况下抛出,并且仅在这是明智的情况下才被使用。但是,直到Perl 6提供了一种定义自定义控件例外的方式,我宁愿不愿意这样做;吞咽问题使得它太脆弱了。

+0

使用$ * ARGFILES遇到坏文件的可恢复异常的用例:https://stackoverflow.com/questions/48865412/how-should-i-handle-perl-6-argfiles-that-c​​ant-be-read逐线 –

相关问题