The leads you need are probably

[link:msdn.microsoft.com]

and

[link:blogs.msdn.com]

but ask again if you get stuck.

By on 4/16/2010 3:43 AM ()

Hello,

I know about kprintf, but I need some other.

For example if I write next fun: let testPrintf fmt =
Printf.kprintf (fun _ -> ()) fmt

And after that write some like this:

testPrintf "Some trace info for very big object. Obj:%A" reallyVeryBigObject

reallyVeryBigObject will be formatted with format string and will be
passed to (fun _ -> ()).

Such implementation testPrintf only turn off output of result string.

But I want implemntation which completely turn off calculationg result string.

By on 4/16/2010 4:18 AM ()

In principle, you can do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
open Microsoft.FSharp.Reflection

(* given a function type 'a1 -> 'a2 -> ... -> 'aN -> unit, N >= 0, 
   generates a function value which ignores all inputs and returns unit *)
let rec ignorer ty =
  if FSharpType.IsFunction ty then
    let _,rng = FSharpType.GetFunctionElements ty
    let rest = ignorer rng
    FSharpValue.MakeFunction(ty, fun (_:obj) -> rest)
  else
    assert (ty = typeof<unit>)
    box ()
     
let iprintf (_:Printf.TextWriterFormat<'a>) : 'a = unbox (ignorer typeof<'a>)
let ifprintf (_:System.IO.TextWriter) (_:Printf.TextWriterFormat<'a>) : 'a = unbox (ignorer typeof<'a>)

In practice, this is a bit slow to create the function value, so there's a massive difference (a factor of more than 1000) between

1
2
for i in 1 .. 100000 do
  iprintf "%i" i

and

1
2
3
let printFn = iprintf "%i"
for i in 1 .. 100000 do
  printFn i

By contrast, the F# library's printf variants are much more efficient in creating the function values, showing only a factor of 10 or so difference when I use "Printf.kprintf ignore" in place of "iprintf" above. This probably indicates that my code above could be made much more efficient, but I haven't profiled to determine the biggest optimization opportunities.

By on 4/16/2010 8:20 AM ()

Okay, it looks like big savings can be had by replacing the uses of

1
FSharpType.IsFunctionType

and

1
FSharpType.GetFunctionElements

with custom built equivalents, which is what the F# printf functions use. See below for a slightly uglier but ~20x faster implementation of ifprintf:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
open Microsoft.FSharp.Reflection


(* let isFunctionType = FSharpType.IsFunction *)
let funTyC = typedefof<_ -> _>
let isNamedType(ty:System.Type) = not (ty.IsArray ||  ty.IsByRef ||  ty.IsPointer)
let isFunctionType (ty1:System.Type)  = 
  isNamedType(ty1) && ty1.IsGenericType && (ty1.GetGenericTypeDefinition()).Equals(funTyC)


(* let destFunTy = FSharpType.GetFunctionElements |> fun (a,b) -> [|a;b|] *)
let rec destFunTy (ty:System.Type) =
  if isFunctionType ty then 
    ty.GetGenericArguments() 
  else
    match ty.BaseType with 
    | null -> raise <| System.InvalidOperationException("Not a fun type")
    | b -> destFunTy b 


(* given a function type 'a1 -> 'a2 -> ... -> 'aN -> unit, N >= 0, 
   generates a function value which ignores all inputs and returns unit *)
let rec ignorer ty =
  if isFunctionType ty then
    let tys = destFunTy ty
    let rest = ignorer (tys.[1])
    FSharpValue.MakeFunction(ty, fun (_:obj) -> rest)
  else
    assert (ty = typeof<unit>)
    box ()
     
let iprintf (_:Printf.TextWriterFormat<'a>) : 'a = unbox (ignorer typeof<'a>)
let ifprintf (_:System.IO.TextWriter) (_:Printf.TextWriterFormat<'a>) : 'a = unbox (ignorer typeof<'a>)
By on 4/16/2010 8:39 AM ()

Hello,

Many thanks! This is exact what I need.

I think what this is good idea add this implementation to standart F# library.

By on 4/20/2010 10:13 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper