管道序列中的异常处理

2024-05-08

我正在开发一个基本的 2D CAD 引擎,管道操作符显着改进了我的代码。基本上,有几个函数从空间中的点 (x,y) 开始,并在多次移动操作后计算最终位置:

let finalPosition =
    startingPosition
    |> moveByLengthAndAngle x1 a1 
    |> moveByXandY x2 y2
    |> moveByXandAngle x3 a3
    |> moveByLengthAndAngle x4 a4
    // etc...

这非常容易阅读,我想保持这种状态。各种x1、a1等显然在真实代码中都有一个有意义的名称。

现在新的要求是引入异常处理。围绕整个操作链进行大量尝试/操作是不够的,因为我想知道哪一行导致了异常。我需要知道哪个参数无效,以便用户知道必须更改哪个参数。

例如,如果第一行 (moveByLengthAndAngle x1 a1) 引发异常,我想告诉类似“嘿,-90 是 a1 的无效值!a1 必须在 45 到 90 之间!”。鉴于可以在序列中使用许多相同类型的操作,为每个操作定义不同的异常类型是不够的(在本例中,我无法判断错误是第一次还是最后一次)。

显而易见的解决方案是将链拆分为单个 let 语句,每个语句都在其各自的 try/with 内。然而,这会让我美丽且可读的代码变得有点混乱,不再那么可读了。

有没有办法既能满足这个需求,又不牺牲当前代码的可读性和优雅性?

(注意。现在每个 moveBy 函数都会在出现错误时引发异常,但我可以自由地进行更改,例如返回一个选项、一个更大的元组或其他任何需要的东西)。


Rick 描述的解决方案仅处理评估时引发的异常论点管道中的功能。但是,它不会处理管道函数引发的异常(如所述回答你的另一个问题 https://stackoverflow.com/questions/8263115/why-does-pattern-matching-fail-on-an-exception-in-this-case).

例如,假设您有以下简单的功能:

let times2 n = n * 2
let plus a b = a + b
let fail n = failwith "inside fail"

10 // This will handle exception that happens when evaluating arguments
   |> try plus (failwith "evaluating args") with _ -> 0 
   |> times2                                            
   |> try fail with _ -> 0 // This will not handle the exception from 'fail'!

为了解决这个问题,您可以编写一个函数,将任何其他函数包装在异常处理程序中。你的想法protect函数将接受一个函数(例如times2 or fail)并将返回一个新函数,该函数从管道(数字)获取输入并将其传递给函数(times2 or fail),但会在异常处理程序中执行此操作:

let protect msg f = 
  fun n -> 
    try
      f n 
    with _ ->
      // Report error and return 0 to the pipeline (do something smarter here!)
      printfn "Error %s" msg
      0

现在您可以保护管道中的每个函数,它还将处理评估这些函数时发生的异常:

let n =
  10 |> protect "Times" times2
     |> protect "Fail" fail
     |> protect "Plus" (plus 5)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

管道序列中的异常处理 的相关文章

  • 了解 F# 尾递归

    最近在学习F 我尝试以不同的方式解决问题 像这样 0 1 2 3 4 5 6 7 8 gt 0 1 2 3 4 5 6 7 8 head recursive let rec toTriplet v1 list match list with
  • 基于函数签名的模式匹配

    在 F 中 您可以对函数签名进行模式匹配 我想用一个函数来装饰多个函数 该函数测量函数的执行情况并调用 statsd 我当前的功能是 let WrapFunctionWithPrefix metrics Metric Client IRec
  • 如何从 f# 返回一个空元组到 c#? [复制]

    这个问题在这里已经有答案了 我有这个类型正确的 C 函数 static System Tuple
  • 如何让一条记录实现一个接口?

    如果我有一个界面 type IData abstract member firstName string abstract member lastName string 如何定义符合此接口的记录类型 我尝试了如下所示 gt type Dat
  • 如何使用 WebSharper 在服务器上生成 Google Visualizations 数据

    我的目标是能够在服务器上为 Google Visualizations 生成数据 然后将其作为 java 脚本传递给客户端 以便可以将其呈现为折线图 我下面的示例可以正确编译 但在浏览器中呈现时会产生错误 在服务器上构建 DataCommo
  • 使用 FParsec 解析 int 或 float

    我正在尝试使用 FParsec 解析文件 该文件由 float 或 int 值组成 我面临两个问题 无法找到好的解决方案 1 Both pint32 and pfloat将成功解析相同的字符串 但给出不同的答案 例如pint32将返回3解析
  • 从静态成员访问 let 绑定字段

    有没有办法从静态成员访问 let 绑定字段 下面给出了指示的错误 type Foo x let x x static member test let foo Foo System DateTime Now Month printfn A f
  • 图像分析-光纤识别

    我是图像分析新手 您知道如何以仅获取纤维的方式对该图像进行二值化吗 我尝试过不同的阈值技术等 但没有成功 我不介意应该使用什么工具 但我更喜欢 NET or Matlab PS 我不知道该把答案放在哪里 所以我把它放在StackOverfl
  • 如何在 F# 中打印整个列表?

    当我使用 Console WriteLine 打印列表时 它默认仅显示前三个元素 如何让它打印列表的全部内容 您可以将 A 格式说明符与 printf 一起使用来获得 美化的 列表打印输出 但与对象上的 Console WriteLine
  • 生成尾调用操作码

    出于好奇 我尝试使用 C 生成尾部调用操作码 斐波那契数很简单 所以我的 C 示例如下所示 private static void Main string args Console WriteLine Fib int MaxValue 0
  • 对 F# 中任意嵌套级别的列表求和

    我正在尝试创建一个 F 函数 它将返回列表的总和int任意嵌套 IE 它将适用于list
  • F# 生成日期序列/数组

    在 F 中我可以轻松做到 let a 1 10 那我为什么不能做 let a DateTime Parse 01 01 2012 let b DateTime Parse 01 01 2020 let dateList a b 它给出了一个
  • F#:模式构成?

    我正在尝试编写一个由另外两个模式组成的模式 但我不确定如何去做 我的输入是字符串列表 文档 我有一个与文档标题匹配的模式和一个与文档正文匹配的模式 该模式应该匹配整个文档并返回标题和正文模式的结果 您可以使用以下命令一起运行两个模式 您在问
  • 函数式编程是否避免了状态?

    根据维基百科 http en wikipedia org wiki Functional programming 函数式编程是一种编程范式 它将计算视为数学函数的评估避免状态和可变数据 强调我的 这是真的吗 我个人的理解是 它使状态更加明确
  • 如何在 F# 测量单位上定义扩展成员?

    暂且不说我们是否应该对像角度这样的无单位概念使用测量单位 假设我已经定义了degree and radianF 中的单位 type
  • 如何在 F# 中实现返回 void 的接口成员

    想象一下 C 中的以下接口 interface IFoo void Bar 我如何在 F 中实现这一点 我在 30 分钟的在线搜索中找到的所有示例都仅显示具有返回类型的示例 我认为这在函数式风格中更常见 但在这种情况下我无法避免 这是我到目
  • 适用于 F# 联合类型的简洁通用类型处理程序

    我在我的简洁对象上使用类似于枚举的联合类型 type Confidence Low Medium High type Goal Confidence Confidence 我创建了一个自定义类型处理程序以使其正常工作 type UnionH
  • 完全限定名称、带导入声明的非限定名称解析不同

    这有效 open System let f Action fun gt Unchecked defaultof lt gt But this let f System Action fun gt Unchecked defaultof lt
  • 可移植类库和.NET ConcurrentDictionary

    看着http msdn microsoft com en us library dd287191 v vs 110 aspx http msdn microsoft com en us library dd287191 v vs 110 a
  • F# 在生成和终止进程方面真的比 Erlang 更快吗?

    更新 这个问题包含一个错误 使得基准测试毫无意义 我将尝试一个更好的基准来比较 F 和 Erlang 的基本并发功能 并在另一个问题中查询结果 我正在尝试了解 Erlang 和 F 的性能特征 我发现 Erlang 的并发模型非常有吸引力

随机推荐