Search code examples
exceptionf#actor

How do I reference the current instance in the c'tor in F#?


Questions (3 of them that are related) are bolded below.

I'm trying to create a F# class -- I need to consume it without referencing F#'s assembly from C#.

I have code like this:

type ReceiverExceptionEventArgs(ex:Exception) =
    inherit EventArgs()
    member this.Exception = ex

type ExceptionRaised = delegate of obj * ReceiverExceptionEventArgs -> unit

type Receiver( ... ) =

  let error  = new Event<ExceptionRaised, ReceiverExceptionEventArgs>()

  let a = new Actor<...>(fun inbox -> ...)   

  [<CLIEvent>]
  member __.Error = error.Publish

  /// Starts the receiver which starts the consuming from the service bus
  /// and creates the queue if it doesn't exist
  member x.Start () =
    logger.InfoFormat("start called for queue '{0}'", desc)
    a.Post Start

I'd like to add this after let a = new Actor...:

do a.Error.Add(fun ex -> error.Trigger(this, new ReceiverExceptionEventArgs(ex)))

But I don't have a reference to 'this' on the above line... How would I do it idiomatically in F#?

As a further complication, the actor is starting a number of asynchronous computations that are basically loops; these computations return unit, so I can't just do:

let startPairsAsync pairs token =
  async {
    for Pair(mf, rs) in pairs do
      for r in rs do 
        match Async.Start(Async.Catch(r |> worker), token) with
        | Choice1Of2 () -> ()
        | Choice2Of2 ex -> error.Trigger(null, new ReceiverExceptionEventArgs(ex)) }

because worker r is Async<unit>, so I get This expression was expected to have type 'unit' but was here 'Choice1of2<'a, 'b>' on the first pattern match.


Digression:

Is the idea that I create actors for each worker also? I'd like to have code that is similar to how erlang does 'supervisors' because what I'm working with may fail arbitrarily at almost any point (network)... Supervisors is outside the scope of this question; but would I get better idiomatic exception handling with mutliple Actors rather than Async.Catch?


Solution

  • Regarding this, use

    type MyClass(args) as this =
    

    in the declaration to bind this inside the constructor. (You can use any identifier you like.)

    (See also

    http://lorgonblog.wordpress.com/2009/02/13/the-basic-syntax-of-f-classes-interfaces-and-members/

    )