首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >标准ML异常和资源

标准ML异常和资源
EN

Stack Overflow用户
提问于 2013-06-30 16:35:01
回答 1查看 231关注 0票数 0

当资源在使用过程中出现异常时,我希望释放该资源。

在C++中,这个任务很简单:我把释放放到析构函数中,无论发生什么,它都会被自动调用。在Java中,我们使用了'finally‘子句。在Standard ML中,同样的任务的实践是什么?

我尝试用变量模式'e‘捕获所有异常,并重新引发它:

代码语言:javascript
复制
datatype FileReadResult = FileReadOkay of string | FileReadError

fun read_file (file_path_string : string) : FileReadResult =
    let
        val istream = TextIO.openIn file_path_string
            (* this file is my resource *)
    in
        TextIO.closeIn istream;
        FileReadOkay "" (* the content of the file will go here *)
        handle e => (TextIO.closeIn istream; raise e)
    end
    handle Io => FileReadError

我的编译器(MLton)接受它,但因为我是ML的新手,所以我在这里请求一些保证,以确保这确实是正确的做法|最佳实践。

由于这是一种常见的设计模式,我创建了以下实用函数来表达它:

代码语言:javascript
复制
(* Uses the given resource in the given way while releasing it if any exception occurs. *)
fun use_resource (resource : 'Resource) (releaser : 'Resource -> unit) (usage : unit -> 'Result) : 'Result = 
    let
        val r = usage ()
    in
        releaser resource;
        r
    end
    handle e => (releaser resource; raise e)

此函数与C#中的“using”功能作用相同。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-06-30 20:48:33

是的,这是通常的模式,但有两点需要注意:

  1. 内部的handle只在你的代码中围绕着FileReadOkay "",它永远不会抛出。你想用括号把代码的更大部分括起来,这样处理程序就可以应用于所有的代码。
  2. 你的外部处理程序捕获Io。我认为您在这里指的是IO.Io _,否则您将捕获所有异常(因为Io只是一个随机的新鲜变量)。

如果它经常出现,您也可以尝试将其抽象为一个函数。一些类似的东西

代码语言:javascript
复制
(* withTextFile : string -> (TextIO.instream -> 'a) -> 'a
fun withTextFile name f =
    let
        val is = TextIO.openIn name
    in
        (f is before TextIO.closeIn is)
        handle e => (TextIO.closeIn is; raise e)
    end

(中缀运算符before计算其左手表达式和右手表达式,并返回前者的结果)。像这样使用它:

代码语言:javascript
复制
fun echo file = withTextFile file (fn is => print(TextIO.inputAll is))
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17388606

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档