I am building a parallel unit test runner using MailBoxProcessor.
I need to queue up print statements for a test, so I can print them once a test is finished. I know how to send a string and build up a list so I can print them, but that forces me to use sprintf and pipe it into my print function and is not as clean as I would like.
[1..200]
|> List.iter (fun i ->
sprintf "Test %i" i &&& fun ctx ->
ctx.printfn <| sprintf "A guid %A" (ng())
ctx.printfn <| sprintf "I am test %i" i
ctx.printfn <| sprintf "A guid %A" (ng()))
You can see the full code here:
https://github.com/lefthandedgoat/prunner/blob/master/Program.fs#L36-L41
And see that ctx is an object with a printfn method that takes a string and posts it to a single mailbox that queues up messages until a tests is done, then loops over them and prints them.
My goal is to have the ctx.printfn look like this
[1..200]
|> List.iter (fun i ->
sprintf "Test %i" i &&& fun ctx ->
ctx.printfn "A guid %A" (ng())
ctx.printfn "I am test %i" i
ctx.printfn "A guid %A" (ng()))
Your question isn't entirely clear, but you may be able to achieve your goal via kprintf:
member x.printfn fmtStr =
Printf.kprintf (fun msg -> reporter.Post(Print(msg, x.TestId))) fmtStr
Related
I have a project using NLog and there is a wrapper around the logger, in order to turn logging off in some areas:
member this.SetQuiet q = quiet <- q
member this.Trace format = Printf.kprintf (fun s -> if not quiet then logger.Trace(s)) format
member this.Debug format = Printf.kprintf (fun s -> if not quiet then logger.Debug(s)) format
member this.Info format = Printf.kprintf (fun s -> if not quiet then logger.Info(s)) format
member this.Warn format = Printf.kprintf (fun s -> if not quiet then logger.Warn(s)) format
member this.Error format = Printf.kprintf (fun s -> if not quiet then logger.Error(s)) format
member this.Fatal format = Printf.kprintf (fun s -> if not quiet then logger.Fatal(s)) format
this works quite well, but I have an issue:
logger.Info "hello"
logger.Info <| "hello"
will work properly, whereas:
"hello" |> logger.Info
will not compile with this error:
typecheck error The type 'string' is not compatible with the type 'Printf.StringFormat<'a,string>'
can someone explain me why this fails? the order kprintf-continuation-format should still be respected here, no?
Is there a workaround for this? the reason is that I'm trying to do a 'tee' to log messages in a non verbose way (the tee just applies a function and then returns the original parameter):
"my messsage"
|> tee logger.Info
|> Result.Ok
That happens because printf and similar methods uses formatting. It allows type-safe usage of these method. For example printfn "%d" enforces integer as parameter
printfn "%d" 3
printfn "%d" 3.14 // error
printfn "%s %f" enforces string and float.
printfn "%s %f" "Hello" 3.14
printfn "%s %f" '3' 14 // error
This means that you should change methods this way (added "%s")
member this.Trace format = Printf.kprintf (fun s -> if not quiet then logger.Trace(s)) "%s" format
I have a lot of modules that upon starting the program are supposed to add certain things to a single Dictionary found in a higher level module. However, it appears that expressions and constants within a module are packed into static constructors when compiling to a Console App, so these aren't evaluated unless explicitly referenced/when the program thinks they are needed.
There have been a few questions on here regarding initializing modules, and the consensus has been that it is not possible to force. However, I have not seen any of them explore reflection in this regard. In C# I know you are able to invoke the static constructor of a type, so I have attempted the same with F# modules.
My attempts have involved adding a custom attribute (MessageHandlerAttribute) to each module containing such an expression that I want evaluated upon starting the program, and then running this:
let initAllMessageHandlerModules =
Assembly.GetExecutingAssembly().GetTypes()
|> Array.choose (fun typ ->
typ.CustomAttributes
|> Seq.tryFind (fun attr -> attr.AttributeType = typeof<MessageHandlerAttribute>)
|> Option.map (fun _ -> typ))
|> Array.iter
(fun typ -> try typ.TypeInitializer.Invoke(null, null) |> ignore with | ex -> printfn "%A" ex)
But this gives me the following error:
System.NullReferenceException: Object reference not set to an instance of an object.
I have also tried to swap the final lambda function with this:
(fun typ -> try System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typ.TypeHandle) |> ignore with | ex -> printfn "%A" ex)
But this appears to do nothing. Is it possible to achieve this?
Use type.GetConstructor instead of type.TypeInitializer.
(fun typ -> try typ.GetConstructor(BindingFlags.Instance ||| BindingFlags.Public, null, CallingConventions.Standard, Array.empty<Type>, Array.empty<ParameterModifier>).Invoke(null, null) |> ignore with | ex -> printfn "%A" ex)
Here are some more examples
I have a code which looks like this:
this.GetItemTypeIdsAsListForOneItemTypeIdTreeUpIncludeItemType itemType.AutoincrementedId
|> Array.map (fun i -> i.AutoincrementedId)
|> Array.map (BusinessLogic.EntityTypes.getFullSetOfEntityTypeFieldValuesForItemTypeAid item.Autoincrementedid)
|> Array.fold Array.append [||]
|> Array.map (fun fv -> { fv with ReferenceAutoId = aid } )
|> Array.toSeq
|> Seq.distinctBy (fun fv -> fv.Fieldname)
|> Seq.toArray
Sometimes such code gets the unusual result which I need to explain. Usually there is not error in the code. There is an error in the data. And I need to explain why this backet of data is incorrect. What is the best way to do it ?
I just want to look at the list on each step of this expression.
Something like:
func data
|> func2 && Console.WriteLine
|> func3 && Console.WriteLine
....
Get input, split it on two. Pass one of the output to the next function, and second output to Console.
For a quick and dirty solution, you can always add a function like this one:
// ('a -> unit) -> 'a -> 'a
let tee f x = f x; x
If, for example, you have a composition like this:
[1..10]
|> List.map string
|> String.concat "|"
you can insert tee in order to achieve a side-effect:
[1..10]
|> List.map string
|> tee (printfn "%A")
|> String.concat "|"
That's not functional, but can be used in a pinch if you just need to look at some intermediate values; e.g. for troubleshooting.
Otherwise, for a 'proper' functional solution, perhaps application of the State monad might be appropriate. That will enable you to carry around state while performing the computation. The state could, for example, contain custom messages collected along the way...
If you just want to 'exit' as soon as you discover that something is wrong, though, then the Either monad is the appropriate way to go.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
When passing a function to another function which should calculate the result and then pass that value as an argument to another function, I've discovered that I could "compose" the following code in 5 different ways.
let testnum testFun =
testFun 4
printfn "result: %b" (testnum (=) 0)
printfn "result: %b" <| testnum (<) 0
printfn "result: %b" (testnum <| (>=) 0)
testnum <| (=) 0 |> printfn "result: %b"
printfn "resutl: %b" << testnum <| (<>) 0
I do like the style without parentheses more but now I'm wondering, is there a preferred style assuming my goal is readability and supportability of my code?
For your example I would have picked the first one:
printfn "result: %b" (testnum (=) 0)
The second one is passable:
printfn "result: %b" <| testnum (<) 0
The others are too contrived, they look like exercise in obfuscation.
I do use "backward" pipe operator exclusively in two situations:
when I have a type constructor that would need nested parentheses otherwise, so Some <| Foo ("bar", "baz") instead of Some (Foo ("bar", "baz"))
when I want to pass a single anonymous function as a last argument - it communicates nicely where the action is at:
lock sync <| fun () ->
...
For what is worth, if there are multiple anonymous functions passed as arguments, I would usually parenthesize each one of them instead (the notable exception being when one of them is a few characters long one liner and the other has multiple lines - then I would still go with the above syntax).
As for pipelining, I would usually go with |> for longer pipelines, and use function composition >> for shorter ones, when I don't need to refer to the argument again in the body of the function.
I don't think I would ever put |> and <| in the same line without parenthesizing one of them. It just looks odd.
Prefer pipe |>, this help with inference and readability
(=) 3 |> testnum |> printfn "result: %b"
you can easy break it on multiple lines
(=) 3
|> testnum
|> printfn "result: %b"
if arguments are few, you can pass them directly
testnum (=) 4 |> printfn "result: %b"
but use pipe |> or composition >> like g x |> f or x |> g |> f instead of nested function call f(g(x)), is more idiomatic. This also help with inference, for example instead of the . operator
open System.Linq
let double x = x * 2
let double1 items = items |> Seq.map double
[1;2;3] |> double1 |> printfn "%A"
//this doesn't compile,
//error: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed ..
//
// let double2 items = items.Select(double)
// [1;2;3] |> double2 |> printfn "%A"
let double3 (items:seq<_>) = items.Select(double)
[1;2;3] |> double3 |> printfn "%A"
example: https://dotnetfiddle.net/K0u3NQ
I keep running into the following problem:
(System.Console.ReadLine ()).Split [|'('; ')'|]
|> Array.filter (fun s -> not (System.String.IsNullOrEmpty (s)))
|> Array.map (fun s -> s.Split [|','|])
|> Array.map (fun s -> Array.map (fun t -> t.Trim ()) s) (* t.Trim () is underlined with a red squiggly line *)
|> [MORE CODE]
The error associated with the red squiggly line is:
Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
But when the mouse pointer hovers over t, IntelliSense correctly says that t is of type string.
I can bypass the error by writing fun (t : string) -> [CODE], but I wonder why Visual Studio draws the squiggly line at all when it is already detecting the type of the variable correctly. Is this a simple bug in the trial build, or am I misunderstanding something about F#'s type inferencing?
Thanks in advance for your responses.
There is some gap between F# intellisense and F# type checker.
The type checker works from left to right in order. Your problem can be fixed be changing:
fun s -> Array.map (fun t -> t.Trim()) s
to
fun s -> s |> Array.map (fun t -> t.Trim())
Since type of s is available before using Array.map, the type checker is able to infer type of t.
Remarks:
This error usually occurs when using instance methods. You could replace these methods by static functions with extra type annotation and refactor to make your code more composable:
let split arr (s: string) = s.Split arr
let trim (s: string) = s.Trim()
System.Console.ReadLine()
|> split [|'('; ')'|]
|> Array.filter (not << System.String.IsNullOrEmpty)
|> Array.map (split [|','|])
|> Array.map (Array.map trim)