F # no pasa ninguno a la función, obteniendo nulo como valor de parámetro

Esto es realmente extraño y me temo que acabo de hacer algo tonto, pero no puedo resolverlo.

Estoy pasando None a la función some como el primer parámetro pero cuando la función se ejecuta, el valor de parentNode es nulo (no me preocupa que imprima nulo para None, el valor del parámetro de función ES nulo no None). Termino recibiendo un error de referencia nula en la línea de función de impresión porque parentNode es nulo. Intenté tuplar los argumentos y cambiar el orden, pero eso no ayudó. Tengo la ligera sospecha de que esto tiene algo que ver con el curry, pero estoy perdido...

Tuve que reemplazar el valor real de la URL con una cadena vacía por problemas de la empresa, pero es una URL para un xsd si eso ayuda

Aquí está el código:

#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

preguntado el 03 de mayo de 12 a las 16:05

¿En qué línea obtiene una excepción de referencia nula? sprintf "%O" null debería funcionar bien, y no veo ninguna otra referencia a parentNode, ¿estás seguro de que de ahí viene el error? -

2 Respuestas

Desafortunadamente, es la forma en que F# imprime None:

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

Puede escribir fácilmente una sprintf función para option tipo, por ejemplo:

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

contestado el 03 de mayo de 12 a las 17:05

Eso está bien y se espera. el problema es que el primer parámetro no obtiene "ninguno", se vuelve nulo. Actualicé mi pregunta para aclarar: Brad

Option<'T> (fuente en Github) utiliza el atributo [<CompilationRepresentation([CompilationRepresentationFlags.UseNullAsTrueValue)>] lo que provoca el caso nulo (None, en este caso) para ser representado por null en tiempo de ejecución.

contestado el 03 de mayo de 12 a las 17:05

Por qué funciona esto: > printfn "%O" Ninguno;; ? ¿Debería salir ese error con una referencia nula también? ¿Y qué pasa con las declaraciones de coincidencia? ¿Puedo hacer coincidir Ninguno, nulo o ambos? - Brad

@Brad: Porque printf comprueba si hay valores nulos e imprime " " antes de intentar llamar ToString(). Esto también funciona: printfn "%O" null. - Daniel

@Brad: Sí, puedes hacer coincidir None/null. - Daniel

Tratar: Some(1).Value y (None : int option).Value y también ().ToString() - Ming Tang

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.