4
\$\begingroup\$

I'm basically redoing a piece of reactive C# code posted in SO code in F#, please, see below. The translation is fairly literal, I've just written the infinite loop as a recursive function and rearranged the conditions for breaking the recursion. Any notes regarding style and so forth, even the most subjective ones, are a fair game, but I would like to present two explicit questions:

As reading svick's comment I realised I'm actually asking advice on how could I refactor the throttleDuration part of code to be actually be inside the throttleFactory, which in turn then would produce the desired doubles. It looks like I'm feeling the effect of trying to think more functionally and in terms of function composition as it feels more natural than in F# than in C#.

In any event, two points of note here:

  • Would this refactoring question be a better fit for Stackoverflow question?
  • Currently in my intended sequence of doubles from throttleFactory to Throttle there is an added twist in form of the q for quitting variable. I believe this could be safely ignored and just assume there would be only valid doubles produced somehow by some kind of a generator. This would also drop out the question about if conditional on context my particular piece of code (of course, not in general sense) unless there's some slick way of doing the generating and checking with active patterns or something.

As writing this now, it also looks like I wouldn't need the whole inputLoop variable in case I'd use just some arbitrary generator, which in turn negates some the ideas I had with regarding rehearsing this (I haven't tried to write actual code as of yet). The thing is, I'm rookie enough with this so as not to know if going this "plain generator or q for quitting also" route would bear fruit and I'm afraid I run out of time trying if I try for too long by myself.

The above mentioned sequence generation (excluding the issue of quitting) is the vague reason I'm suspiciously eying at the ref cell. I leave the rest of my original post as is for reference.

Ignoring the magic numbers, would there be a more idiomatic (or cleaner) way to write the generator or equivalent function?

open System
open FSharp.Reactive
open System.Reactive
open System.Reactive.Linq

[<EntryPoint>]
let main argv =
    let throttleValueGenerator(minInclusiveMillisecondsLowerBound, maxExlusivemillisecondsUpperBound, countOfValues) =
        let rnd = new System.Random()
        Observable.Generate(0, (fun value -> value < countOfValues), (fun value -> value + 1), (fun value -> rnd.Next(minInclusiveMillisecondsLowerBound, maxExlusivemillisecondsUpperBound)), (fun value -> TimeSpan.FromSeconds(float 1)))

    //The idea here is to produce events on one second intervals and whenever throttle is more than one second, no value will be output. 
    let throttleFactory = fun _ -> throttleValueGenerator(100, 2000, 30)
    let sequence = Observable.Interval(TimeSpan.FromSeconds(1.0)).Throttle(throttleFactory)

    printfn "Sequence starts on %A..." DateTime.Now
    let subscription = sequence.Subscribe(fun a -> printfn "%i on %A" a DateTime.Now)

    Console.ReadKey() |> ignore
    printfn "Sequence end on %A." DateTime.Now

    subscription.Dispose()

    0
  • I became to think if it'd be possible to leave out the intermediary feeling ref throttleDuration and perhaps construct the throttleFactory in some slick way by parsing the Console.ReadLine and in case it's double, parse piping/creating an infinite sequence or something from Console.ReadLine() and feeding the values directly into the Throttle function (or to throttleFactory). There mightn't be, but I would like to avoid banging my head too hard when thinking of that, albeit it might be educational.

  • Do those if conditionals look all right from functional style perspective or could active patterns fit here? I read about them in F# for Fun and profit article by Scott Wlaschin (a good site, slick looking code) and they could be usable in situations like this at least in larger code bases.

For the code below, I installed both Rx-Main and FSharp.Reactive.

open System
open FSharp.Reactive
open System.Reactive
open System.Reactive.Linq


[<EntryPoint>]
let main argv =
    let throttleDuration = ref (TimeSpan.FromSeconds(0.5));
    let throttleFactory = fun _ -> Observable.Timer(!throttleDuration)
    let sequence = Observable.Interval(TimeSpan.FromSeconds(1.0)).Throttle(throttleFactory);
    let subscription = sequence.Subscribe(fun a -> printfn "%i" a)

    let rec inputLoop() =
        printfn "Enter throttle duration in seconds or 'q' to quit"

        let input = Console.ReadLine().Trim()
        if not(String.Equals(input, "q", StringComparison.InvariantCultureIgnoreCase)) then
            let success, value = System.Double.TryParse input
            if success then
               throttleDuration := TimeSpan.FromSeconds(value);
            inputLoop()

    inputLoop() |> ignore
    subscription.Dispose()

    0
\$\endgroup\$
2
  • 1
    \$\begingroup\$ So you want throttleDuration to mutate, but not be mutable? That doesn't make much sense to me. \$\endgroup\$
    – svick
    Jan 25, 2014 at 22:47
  • \$\begingroup\$ That was a good question, it made me clarify my thoughts (in addition of sleeping over it). I updated my post to hopefully convey better what I was really thinking (I think) when I wrote it. \$\endgroup\$
    – Veksi
    Jan 26, 2014 at 8:45

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.