Exception handling 是否所有异常处理都必须使用动态查找? 根据Coursera课程《华盛顿大学的Dan Grossman》第3节摘要:

Exception handling 是否所有异常处理都必须使用动态查找? 根据Coursera课程《华盛顿大学的Dan Grossman》第3节摘要:,exception-handling,programming-languages,sml,Exception Handling,Programming Languages,Sml,但您已经看到了一个更像动态范围而不是词汇范围的特性:异常处理。当引发异常时,求值必须“查找”应该求值的句柄表达式。这种“查找”是使用动态调用堆栈完成的,不考虑程序的词法结构 我认为作者在谈论标准ML,但是C++似乎也做同样的事情。是否所有语言都使用这种动态查找进行“异常处理” 是否所有语言都使用这种动态查找进行“异常处理” 如果您将异常处理定义为“始终”:展开调用堆栈并查找异常处理程序,那么这种相似性是不可避免的。但“类似动态范围”和“具有动态范围”之间有区别 顺便提一下,标准ML允许本地定义的

但您已经看到了一个更像动态范围而不是词汇范围的特性:异常处理。当引发异常时,求值必须“查找”应该求值的句柄表达式。这种“查找”是使用动态调用堆栈完成的,不考虑程序的词法结构

我认为作者在谈论标准ML,但是C++似乎也做同样的事情。是否所有语言都使用这种动态查找进行“异常处理”

是否所有语言都使用这种动态查找进行“异常处理”

如果您将异常处理定义为“始终”:展开调用堆栈并查找异常处理程序,那么这种相似性是不可避免的。但“类似动态范围”和“具有动态范围”之间有区别

顺便提一下,标准ML允许本地定义的异常,并且不提供值,包括异常。例如,以下程序不进行类型检查:

fun foo () =
    let exception Foo
    in bar () handle Foo => true
                   | _   => false
    end
and bar () = raise Foo
它确实强制执行一个类似于动态作用域的标识符查找机制的控制流,但处理程序不会继承命名异常的作用域,以与其父处理程序进行匹配。所以我认为,说标准ML异常与动态范围有那么大的相似性是不合理的。从基类继承的类似异常和运行时类型注释中的常见特性使类比更加有力

还有其他错误处理系统在调用堆栈中向上以外的其他地方传递控制流。例如,您可以将to Erlang视为一种异常处理机制,其中多个链接进程可以处理进程退出的事件。在这里,控制流只是模糊地类似于动态作用域,因为异常处理程序没有严格的层次结构,而是一个图形。即使进程崩溃是异常的,它也不太接近任何常见的异常定义。

(修订答案)

是否所有语言都使用这种动态查找进行“异常处理”

如果您将异常处理定义为“始终”:展开调用堆栈并查找异常处理程序,那么这种相似性是不可避免的。但“类似动态范围”和“具有动态范围”之间有区别

顺便提一下,标准ML允许本地定义的异常,并且不提供值,包括异常。例如,以下程序不进行类型检查:

fun foo () =
    let exception Foo
    in bar () handle Foo => true
                   | _   => false
    end
and bar () = raise Foo
它确实强制执行一个类似于动态作用域的标识符查找机制的控制流,但处理程序不会继承命名异常的作用域,以与其父处理程序进行匹配。所以我认为,说标准ML异常与动态范围有那么大的相似性是不合理的。从基类继承的类似异常和运行时类型注释中的常见特性使类比更加有力


还有其他错误处理系统在调用堆栈中向上以外的其他地方传递控制流。例如,您可以将to Erlang视为一种异常处理机制,其中多个链接进程可以处理进程退出的事件。在这里,控制流只是模糊地类似于动态作用域,因为异常处理程序没有严格的层次结构,而是一个图形。即使进程崩溃是异常的,它也不太接近任何常见的异常定义。

是的,异常处理就是这样工作的

我们今天理解的异常处理是在70年代在CLU语言中发明的,在80年代早期在ML中进一步发展的。从那些扩展到其他语言,如C++,大多只是关于如何构造和匹配异常的变体。
还值得注意的是,异常处理只是最近发明的一种称为的通用机制的特例,这种机制更为丰富,可以表示各种其他控制结构,如协程、生成器、异步/等待、甚至回溯等等。它对异常处理的主要补充是,处理程序可以恢复抛出计算,并传回一个值。与异常处理一样,它的所有应用程序都严重依赖于处理程序的动态范围。

是的,异常处理就是这样工作的

我们今天理解的异常处理是在70年代在CLU语言中发明的,在80年代早期在ML中进一步发展的。从那些扩展到其他语言,如C++,大多只是关于如何构造和匹配异常的变体。
还值得注意的是,异常处理只是最近发明的一种称为的通用机制的特例,这种机制更为丰富,可以表示各种其他控制结构,如协程、生成器、异步/等待、甚至回溯等等。它对异常处理的主要补充是,处理程序可以恢复抛出计算,并传回一个值。与异常处理类似,其所有应用程序都严重依赖于处理程序的动态范围。

请考虑以下代码:

fun add (a, b) = a + b
fun double a = add (a, b)
val _ = double 10
add
返回时,它将控制权返回到调用堆栈上的下一个函数调用,即
double
。我不认为将其视为“动态范围”是有意义的;相反,这只是调用堆栈作为调用堆栈提供的基本功能

类似地,当
add
引发异常(例如
Overflow
)时,它还将控制权返回到
double
。(当然,
double
不会处理任何异常,因此它会隐式地将所有异常重新引发给自己的调用者。)Grossman博士显然认为,标准的ML实现将保留一个动态的局部范围记录