Boggin
Boggin

Reputation: 3416

Use the TResult from the Task<TResult> in F#

I'm publishing events to an Azure Event Hub with an F# script. The equivalent C# code is as follows:

var connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
var eventHubName = "<< NAME OF THE EVENT HUB >>";

await using (var producer = new EventHubProducerClient(connectionString, eventHubName))
{
    using EventDataBatch eventBatch = await producer.CreateBatchAsync();
    eventBatch.TryAdd(new EventData(new BinaryData("First")));
    eventBatch.TryAdd(new EventData(new BinaryData("Second")));

    await producer.SendAsync(eventBatch);
}

I don't think the following is the best idiomatic F# although it works:

let producerClient = EventHubProducerClient(connectionString, eventHubName)
let cancellationToken = CancellationToken()
let eventDataBatch = 
  cancellationToken
  |> producerClient.CreateBatchAsync
let edb = eventDataBatch.Result
edb.TryAdd event
producerClient.SendAsync edb

note: I've not included the code to create the event but it's a JSON string.

How can I avoid the call to Result? This looks like a step that could be much cleaner.

Upvotes: 0

Views: 48

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243051

You can rewrite code that uses C# async/await using the task { .. } computation expression in F#. Inside this, you can use let! in place of await, but also do! for awaiting tasks that do not return result and use! for awaiting IDisposable results.

I'm not sure what library are you using here, but something like this illustrates the syntax:

let connectionString = "<< CONNECTION STRING FOR THE EVENT HUBS NAMESPACE >>";
let eventHubName = "<< NAME OF THE EVENT HUB >>";

let processEvent() = task {
  use producer = new EventHubProducerClient(connectionString, eventHubName)
  use! eventBatch = producer.CreateBatchAsync()
  eventBatch.TryAdd(EventData(new BinaryData("First")))
  eventBatch.TryAdd(EventData(new BinaryData("Second")))
  do! producer.SendAsync(eventBatch) }

If you then call processEvent(), the result will again be Task. You can ignore that (and let the computation run), or wait for the result of that, if you intend to block at the top level.

Upvotes: 3

Related Questions