2012-05-03 24 views
5

To jest naprawdę dziwne i obawiam się, że właśnie zrobiłem coś głupiego, ale nie mogę tego rozgryźć.F # przekazywanie do funkcji, uzyskanie wartości null jako wartości parametru

olewam None do funkcji some jako pierwszy parametr, ale podczas wykonywania funkcji, wartość parentNode jest null (ja nie dotyczy to drukowania null dla None wartość parametru funkcja jest null nie None). W efekcie otrzymuję zerowy błąd referencyjny w wierszu funkcji drukowania, ponieważ parentNode ma wartość null. Próbowałem zduplikować argumenty i zmienić kolejność, ale to nie pomogło. Mam podejrzenie, że ma to coś wspólnego z currying, ale jestem zagubiony ...

Musiałem zastąpić rzeczywistą wartość adresu URL pustym ciągiem w przypadku problemów firmowych, ale jest to adres URL do xsd czy to pomaga

Oto kod:

#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

W którym wierszu występuje wyjątek odwołania o wartości zerowej? 'sprintf"% O "null' powinno działać dobrze, i nie widzę żadnego innego odniesienia do' parentNode', czy jesteś pewien, że jest to skąd pochodzi błąd? – Guvante

Odpowiedz

4

Niestety, jest to sposób F # drukuje None:

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

można łatwo napisać zwyczaj sprintf funkcja option typu, na przykład:

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

To dobrze i oczekiwano. Problem polega na tym, że pierwszy parametr nie otrzymuje "none", ale otrzymuje zero. Zaktualizowałem moje pytanie, aby wyjaśnić: – Brad

4

Option<'T> (source on Github) wykorzystuje się atrybut [<CompilationRepresentation([CompilationRepresentationFlags.UseNullAsTrueValue)>] co powoduje sygnalnych obudowę (None w tym przypadku), które reprezentuje null w okresie czasu.

+0

Dlaczego to działa:> printfn "% O" Brak ;; ? Czy ten błąd powinien być również wyświetlany z odwołaniem zerowym? A co z instrukcjami meczowymi? Czy mogę dopasować na None, null lub both? – Brad

+1

@Brad: Ponieważ 'printf' sprawdza wartość NULL i drukuje" "przed próbą wywołania' ToString() '. Działa to również: 'printfn"% O "null'. – Daniel

+0

@Brad: Tak, możesz dopasować na 'Brak' /' null'. – Daniel

Powiązane problemy