Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 以正确的方式处理异常_F# - Fatal编程技术网

F# 以正确的方式处理异常

F# 以正确的方式处理异常,f#,F#,我对f#world很陌生。我编写了一个非常小的应用程序,可以从sap查询数据并将结果显示为输出。当应用程序尝试连接sap时,可能会抛出一些异常,以防出现问题 请看以下代码: type Customer() = let mutable _lastName = String.Empty member self.LastName with get () = _lastName member self.QueryData () = //Some CODES he

我对f#world很陌生。我编写了一个非常小的应用程序,可以从sap查询数据并将结果显示为输出。当应用程序尝试连接sap时,可能会抛出一些异常,以防出现问题

请看以下代码:

type Customer() =
    let mutable _lastName = String.Empty
    member self.LastName with get () = _lastName

    member self.QueryData () =
        //Some CODES here

        let bapi = SapBapi()
        let bapiFunc = bapi.GetBapiFunc(dest, "BAPI_CUSTOMER_GETDETAIL1")
        match bapiFunc with
        | Success bp  ->
            //Some CODES here

            let addressData = bp.GetStructure("PE_PERSONALDATA")
            _lastName <- addressData.GetString("LASTNAME")
            None 
        | RfcCommunication ex ->
            Some(ex :> Exception)
        | RfcLogon ex ->
            Some(ex :> Exception)
        | RfcAbapRuntime ex ->
            Some(ex :> Exception)
type Customer()=
让mutable _lastName=String.Empty
成员self.LastName,get()=\u LastName
成员self.QueryData()=
//这里有一些代码
设bapi=SapBapi()
让bapiFunc=bapi.GetBapiFunc(dest,“bapi\u CUSTOMER\u GETDETAIL1”)
将bapiFunc与
|成功bp->
//这里有一些代码
让addressData=bp.GetStructure(“PE_PERSONALDATA”)
_姓氏
一些(例如:>例外)
|RfcLogon ex->
一些(例如:>例外)
|RfcAbapRuntime ex->
一些(例如:>例外)
如您所见,我使用选项类型处理错误,并将抛出的异常向下转换为基本异常类型

在主要功能中

open CustomerBapi
open System

[<EntryPoint>]
let main argv = 

    let customer = CustomerBapi.Customer()
    let ex = customer.QueryData()

    match ex with 
    | Some ex ->
        printfn "%s" ex.Message
    | None ->
        printfn "%s" customer.LastName

    Console.ReadLine() |> ignore
    0 // return an integer exit code
opencustomerbapi
开放系统
[]
让主argv=
让customer=CustomerBapi.customer()
设ex=customer.QueryData()
匹配
|一些ex->
打印“%s”例如消息
|无->
printfn“%s”customer.LastName
Console.ReadLine()|>忽略
0//返回整数退出代码
这段代码可以工作,但我是否以正确的方式处理异常


我在互联网上读到一篇文章,在f#中处理异常应该返回一个错误代码,这比异常样式更容易。

一般来说,我认为您的解决方案是可以的,但可以改进。

在代码中混合了一些函数式和OO风格。我觉得有点奇怪,您使用异常作为唯一的可选值。通常,客户应该是包含可选性的价值,匹配应该是客户是否有价值

在类型系统中处理错误的典型方法是使用
类型

 type Either<'a,'b> =
     | Left of 'a
     | Right of 'b

关于错误代码的部分听起来非常错误,我想知道你在哪里找到的

您可能想阅读Scott Wlaschin的优秀文章,了解如何用F#函数化地建模错误。如果没有这篇文章的介绍,很难反驳其论点。IMO异常不同于任何类型的返回值(无论是包装在选项中还是有区别的联合类型中),允许故障点和处理点之间的中间代码更干净。在实际应用中,这种中间代码占大多数。理查德:这是真的,但是一个以异常终止的函数会产生副作用,如果你想用纯函数的方式编写F#,你就不希望这样。
// QueryData no longer needs to depend on side effects to work, 
//so you can make it a regular function instead of a method
let result = queryData()

match result with 
| Left ex ->
    // handle exception
    printfn "%s" ex.Message
| Right result ->
    // either set the property, or make customer a record
    // and set the name field here
    customer.LastName <- result
    printfn "%s" customer.LastName