I have an observable chain, the initial observable is from network, and will be fired every time message is ready to be read. The next handler then read the message and deserialize it. Now I have a fork of the observable, one is message handler and the other is logging the message.
The problem is that because I'm using observable I will actually try to read the message twice.
I understand that using Event instead of Observable will solve the issue, however I will then have a garbage collection issue that might cause sockets to not being collected.
One solution I thought of is to insert some kind of separator which end one chain of observables and creates a new one, does such a function already exist as part of fsharp or other library library.
Are there other solutions to the problem?
Edit:
Code example that doesn't work correctly
let messagesStream =
socket.observable |>
Observable.map (fun () -> socket.read ()) |>
Observable.map (fun m -> deserialize m)
messagesStream |> Observable.add (fun m -> printf m)
messagesStream |> Observable.add (fun m -> handle m)
The easiest way to add some logging is to use Observable.iter as follows:
let messagesStream =
socket.observable
|> Observable.map (fun () -> socket.read ())
|> Observable.map (fun m -> deserialize m)
|> Observable.iter (printfn "%A")
messagesStream |> Observable.add (fun m -> handle m)
It sounds like you could create one observable that handles the reading of the message from the network and deserializes it. Assuming this is done with standard Rx operators, that should return an observable that pushes new, deserialized network messages.
You can have 2 subscribers to that observable, one that reacts to new messages with whatever business logic you would like and the second subscriber logging the messages.
That should eliminate the side effect of reading multiple times from the network. Pushing 2 copies of the deserialized message should not incur a side effect.
Related
I'm having trouble understanding how to manage multiple observables that depend on each other. I want to define a function with the following signature:
clock:IObservable<unit> -> obs:IObservable<'a> -> IObservable<'a>
So that events from obs can only be emitted once per clock tick, and excess events from obs are discarded.
I have tried mapping the two observables and then merging them into one stream, but it is not the solution.
The built-in F# library for Observables comes with only a few basic functions, so this is not something you can easily do using the built-in primitives. You can probably use a function from the full Rx library, which has a nice F# wrapper and comes with huge number of operations (but that makes it a bit hard to figure out which one is the one that you need).
An alternative purely F# approach would be to use agent-based programming. This lets you nicely handle complex concurrency patterns. The following implements an agent that has Tick and Event as two kinds of messages. It remembers the last Event and when Tick happens, it trigges the returned observable with the last Event value:
open System
type WhenTickMessage<'T> =
| Tick
| Event of 'T
let whenTick (clock:IObservable<_>) (event:IObservable<_>) =
let result = new Event<_>()
let agent = MailboxProcessor.Start(fun inbox ->
let rec loop event = async {
let! msg = inbox.Receive()
match msg with
| Tick ->
event |> Option.iter (fun e -> result.Trigger(e))
return! loop None
| Event e ->
return! loop (Some e) }
loop None)
clock.Add(fun _ -> agent.Post Tick)
event.Add(fun e -> agent.Post (Event e))
result.Publish
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
In this SO post, adding
inSeq
|> Seq.length
|> printfn "%d lines read"
caused the lazy sequence in inSeq to be read in.
OK, I've expanded on that code and want to first print out that sequence (see new program below).
When the Visual Studio (2012) debugger gets to
inSeq |> Seq.iter (fun x -> printfn "%A" x)
the read process starts over again. When I examine inSeq using the debugger, inSeq appears to have no elements in it.
If I have first read elements into inSeq, how can I see (examine) those elements and why won't they print out with the call to Seq.iter?
open System
open System.Collections.Generic
open System.Text
open System.IO
#nowarn "40"
let rec readlines () =
seq {
let line = Console.ReadLine()
if not (line.Equals("")) then
yield line
yield! readlines ()
}
[<EntryPoint>]
let main argv =
let inSeq = readlines ()
inSeq
|> Seq.length
|> printfn "%d lines read"
inSeq |> Seq.iter (fun x -> printfn "%A" x)
// This will keep it alive enough to read your output
Console.ReadKey() |> ignore
0
I've read somewhere that results of lazy evaluation are not cached. Is that what is going on here? How can I cache the results?
Sequence is not a "container" of items, rather it's a "promise" to deliver items sometime in the future. You can think of it as a function that you call, except it returns its result in chunks, not all at once. If you call that function once, it returns you the result once. If you call it second time, it will return the result second time.
Because your particular sequence is not pure, you can compare it to a non-pure function: you call it once, it returns a result; you call it second time, it may return something different.
Sequences do not automatically "remember" their items after the first read - exactly same way as functions do not automatically "remember" their result after the first call. If you want that from a function, you can wrap it in a special "caching" wrapper. And so you can do for a sequence as well.
The general technique of "caching return value" is usually called "memoization". For F# sequences in particular, it is implemented in the Seq.cache function.
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.
Let's take this code:
open System
open System.IO
let lines = seq {
use sr = new StreamReader(#"d:\a.h")
while not sr.EndOfStream do yield sr.ReadLine()
}
lines |> Seq.iter Console.WriteLine
Console.ReadLine()
Here I am reading all the lines in a seq, and to go over it, I am using Seq.iter. If I have a list I would be using List.iter, and if I have an array I would be using Array.iter. Isn't there a more generic traversal function I could use, instead of having to keep track of what kind of collection I have? For example, in Scala, I would just call a foreach and it would work regardless of the fact that I am using a List, an Array, or a Seq.
Am I doing it wrong?
You may or may not need to keep track of what type of collection you deal with, depending on your situation.
In case of simple iterating over items nothing may prevent you from using Seq.iter on lists or arrays in F#: it will work over arrays as well as over lists as both are also sequences, or IEnumerables from .NET standpoint. Using Array.iter over an array, or List.iter over a list would simply offer more effective implementations of traversal based on specific properties of each type of collection. As the signature of Seq.iter Seq.iter : ('T -> unit) -> seq<'T> -> unit shows you do not care about your type 'T after the traversal.
In other situations you may want to consider types of input and output arguments and use specialized functions, if you care about further composition. For example, if you need to filter a list and continue using result, then
List.filter : ('T -> bool) -> 'T list -> 'T list will preserve you the type of underlying collection intact, but Seq.filter : ('T -> bool) -> seq<'T> -> seq<'T> being applied to a list will return you a sequence, not a list anymore:
let alist = [1;2;3;4] |> List.filter (fun x -> x%2 = 0) // alist is still a list
let aseq = [1;2;3;4] |> Seq.filter (fun x -> x%2 = 0) // aseq is not a list anymore
Seq.iter works on lists and arrays just as well.
The type seq is actually an alias for the interface IEnumerable<'T>, which list and array both implement. So, as BLUEPIXY indicated, you can use Seq.* functions on arrays or lists.
A less functional-looking way would be the following:
for x in [1..10] do
printfn "%A" x
List and Array is treated as Seq.
let printAll seqData =
seqData |> Seq.iter (printfn "%A")
Console.ReadLine() |> ignore
printAll lines
printAll [1..10]
printAll [|1..10|]