2012-05-03 60 views
5

這真的很奇怪,我擔心我剛剛做了一些愚蠢的事情,但我無法弄清楚。F#將none傳遞給函數,得到null作爲參數值

我傳遞None的功能some作爲第一個參數,但該功能在執行時的parentNode值爲null(我不關心它打印空爲None,該函數的參數值爲NULL不None )。因爲parentNode爲空,我最終在打印函數行上得到一個空引用錯誤。我嘗試過修改參數並改變順序,但這並沒有幫助。我有一個偷偷摸摸的懷疑,這與柯里有關,但我不知所措...

我不得不用公司問題的空字符串替換真正的url值,但它是一個URL到一個xsd如果這能幫助

下面是代碼:

#light 
open System 
open System.Xml 
open System.Net 
open System.Collections.Generic 

type StartResult = 
    | Parameters of XsdParserParameters 
    | Xsd of Xsd 

and Xsd(text) = 
    let rows = new List<string>() 

    member this.Text 
     with get() = text 

    member this.Rows 
     with get() = rows 

and XsdParserParameters() = 
    let mutable url = "" 

    member this.Url 
     with get() = url 
     and set(value) = url <- value 

    member this.Start() = 
     try 
      use client = new WebClient() 
      let xsd = client.DownloadString(this.Url) 
      StartResult.Xsd(Xsd(xsd)) 
     with e -> 
      StartResult.Parameters(this) 

let processor() = 
    let parameters = XsdParserParameters() 
    parameters.Url <- "" 
    match parameters.Start() with 
    | StartResult.Parameters(xpparams) -> 
     //some error 
     () 
    | StartResult.Xsd(xsd) -> 

     let rec some (parentNode : XmlNode option) (node : XmlNode) = 
      let a =() 

      for subNode in node.ChildNodes do 
       match subNode.LocalName with 
       | "complexType" -> 
        xsd.Rows.Add(
         sprintf 
          "%O~%s~%d~%d~%s~%s~%O" 
          parentNode 
          subNode.Value 
          1 
          1 
          (subNode.Attributes.GetNamedItem("name").Value) 
          "" 
          false) 
        some (Some(subNode)) subNode 
       | "sequence" -> 
        some parentNode subNode 
       | "element" -> 
        xsd.Rows.Add(
         sprintf 
          "%O~%s~%d~%d~%s~%s~%O" 
          parentNode 
          subNode.Value 
          1 
          1 
          (subNode.Attributes.GetNamedItem("name").Value) 
          "" 
          false) 
        some (Some(subNode)) subNode 
       | _ -> 
        () 

     let xdoc = new XmlDocument(); 
     xdoc.LoadXml(xsd.Text) 

     some (None) (xdoc.DocumentElement) 

processor() 

printfn "Done..." 
Console.ReadLine() |> ignore 
+0

你在哪一行得到空引用異常? 'sprintf「%O」null「應該可以正常工作,並且我沒有看到任何其他對'parentNode'的引用,您確定這是錯誤來自哪裏? – Guvante

回答

4

不幸的是,它的方法F#打印出None

> sprintf "%O" None;; 
val it : string = "<null>" 

您可以輕鬆地編寫自定義sprintf功能option類型,例如:

let sprintOption v = 
    if Option.isNone v then "None" else sprintf "%A" v 
+0

這很好,並且是預期的。問題是第一個參數沒有得到「none」,它變爲null。我更新了我的問題以澄清 – Brad

4

Option<'T>source on Github)使用這會導致零元的情況下(None,在這種情況下)將被通過null在運行時所表示的屬性[<CompilationRepresentation([CompilationRepresentationFlags.UseNullAsTrueValue)>]

+0

爲什麼這樣工作:> printfn「%O」無;; ?如果這個錯誤與空引用呢?那匹配報表呢?我可以在None,null或兩者上匹配嗎? – Brad

+1

@Brad:因爲'printf'檢查null並在嘗試調用'ToString()'之前打印「」。這也適用:'printfn'%O「null」。 – Daniel

+0

@布拉德:是的,你可以在'None' /'null'上匹配。 – Daniel

相關問題