Quiero añadir la impresión de depuración en mi proyecto con una función que tiene un tipo de firma algo como:¿Cómo gestionar la impresión de depuración en F #
bool -> Printf.TextWriterFormat<'a> -> 'a
es decir, debe tener un bool que indica si estamos o no en modo prolijo modo, y usar eso para tomar la decisión sobre si imprimir o no.
Por ejemplo, digamos dprint : bool -> Printf.TextWriterFormat<'a> -> 'a
entonces me gustaría este comportamiento:
> dprint true "Hello I'm %d" 52;;
Hello I'm 52
val it : unit =()
> dprint false "Hello I'm %d" 52;;
val it : unit =()
La idea es que una marca de línea de comandos se puede utilizar para evitar el control de esta salida. También quiero evitar un costo de tiempo de ejecución en el caso "no detallado". Es posible definir una función que funciona de esta manera usando kprintf
:
let dprint (v: bool) (fmt: Printf.StringFormat<'a,unit>) =
let printVerbose (s: string) =
if v then System.Console.WriteLine(s)
fmt |> Printf.kprintf printVerbose
pero la impresión/ignorando una secuencia de números con List.iter (dprint b "%A") [1..10000]
(b \ in {verdadero, falso}) realiza cantidad 1.5s para ambos valores de b en mi máquina.
me ocurrió con otro método utilizando la reflexión que construye una función apropiada escrito para descartar los argumentos de formato:
let dprint (v: bool) (fmt: Printf.TextWriterFormat<'a>) : 'a =
let rec mkKn (ty: System.Type) =
if FSharpType.IsFunction(ty) then
let _, ran = FSharpType.GetFunctionElements(ty)
FSharpValue.MakeFunction(ty,(fun _ -> mkKn ran))
else
box()
if v then
printfn fmt
else
unbox<'a> (mkKn typeof<'a>)
pero aquí la reflexión parece demasiado caro (incluso más que la que se hace dentro de las bibliotecas estándar complicada definición de printf
a veces).
no quiero ensuciar mi código con cosas como:
if !Options.verbose then
printfn "Debug important value: %A" bigObject5
o cierres:
dprint (fun() -> printfn "Debug important value: %A" bigObject5)
así, ¿hay alguna otra solución?
Esta es una sugerencia muy interesante, gracias. Sin embargo, parece que no se almacena en caché como se esperaba, es lento en el ejemplo de 'List.iter' en mi pregunta. Traté de agregar un diccionario a 'Format' para caché explícitamente las funciones, pero parece que tampoco funciona. Quizás 'unbox' o' typeof' es caro. – rneatherway
@robin, ahora veo un problema con 'mkKn', permítanme editar .. – t0yv0
@robin - Creo que con la corrección anterior, la reflexión solo debe usarse en la primera invocación (por tipo). Sin embargo, todavía existe el costo de invocar cierres al curry no optimizados de la forma '(diversión x y z ->()) x y z', incluido el boxeo introducido por' MakeFunction' .. – t0yv0