In C# you can annotate methods with async like this:
class Foo
{
public async void Bar()
{
}
}
This is different to an F# async; I believe that in F# these are called tasks.
So, how do I write a C#-style async member function in F#?
// Not real code
type Foo () =
member async this.Bar () =
()
The solution must compile to IL with the same public interface as the C# above.
A C# async method is just a method returning a value of type Task<T>. The C# compiler uses the async keyword to determine that you are allowed to use await inside the code block, but as far as I know, it is not represented in any way in the compiled code.
You say "the solution must compile to the same IL" - that's not going to be easily possible, because F# implements asynchronous operations differently. However, you can get it to compile to IL that has the same public interface using something like this:
type Foo () =
member this.Bar () = Async.StartAsTask <| async {
// yadda yadda
}
The asynchronous operation is implemented using standard F# async workflow, so under the cover, this creates an F# Async<T>, but the Async.StartAsTask operation turns that into a Task<T> type, which is what C# expects.
EDIT: Another alternative is to use the TaskBuilder computation expression, which lets you directly create .NET tasks using something like this:
type Foo () =
member this.Bar () = task {
// yadda yadda
}
Async.StartAsTask should do it. This will give you Threading.Tasks.Task<'a>
let bar =
async{
return ()
}
|>Async.StartAsTask
Related
I have a future that has a generic parameter, which is a superclass (A) of another class (B extends A). I know for a fact that the instance of the value of the Future is of the subtype. Why can't I downcast the Future<A> to Future<B> in dart? If I unwrap the Future once and then wrap it again using async/await, it works.
Here's an example:
class A {}
class B extends A{}
void main() {
Future<A> getFuture() async { return B();}
Future<B> getBasA() { return getFuture() as Future<B>;}
Future<B> getBasAasync() async { return (await getFuture()) as B;}
print(getBasAasync()); // Works
print(getBasA()); // Throws at runtime
}
For the curious and as a motivation for the question, here's a closer-to-world example. I have a stream that emits data packets, which I filter and then get the first like this:
Future<T> getResponse<T extends ReceivedPacket>() =>
getStream<ReceivedPacket>().firstWhere((packet) => packet is T) as Future<T>; //throws
Future<T> getResponse<T extends ReceivedPacket>() async { //works
return (await getStream<ReceivedPacket>().firstWhere((packet) => packet is T)) as T;
}
PS: I've tried it out in Typescript (will happily compile and run) and C# (won't compile, but I have very limited C# knowledge). I understand that the answer to this question might be "because this is how the dart type system works". I'm just confused, because I'd have expected it either to fail at compile time like C# or work at runtime, too, like typescript.
You declared getFuture() as returning Future<A> but with the async keyword, so Dart automatically transforms return B(); to (essentially) return Future<A>.value(B());. The returned Future was never a Future<B> and therefore cannot be downcast to it.
Creating the Future explicitly would do what you expect:
Future<A> getFuture() { return Future<B>.value(B()); }
You could argue that Dart when transforms return x; in async functions, it should create a Future<T> where T is the static type of x instead of inferring it from the function's return type. As lrn explained in comments, that can't be done because you might have:
class C extends A {}
Future<A> getFuture() async {
await Future.delayed(const Duration(seconds: 1));
if (Random().nextBool()) {
return B();
} else {
return C();
}
}
The caller must get a Future back immediately, but it won't be known whether its value will be a B or C until the Future eventually completes.
I'd have expected it either to fail at compile time like C#
I too have very limited experience with C#, but I think that C# gives you a compilation error because C# does not consider Generic<SubType> to be a subtype of Generic<SuperType> whereas Dart does.
In C#, I can implement a generic interface twice on one class, using two different type-parameters:
interface IFoo<T> { void Foo(T x); }
class Bar : IFoo<int>, IFoo<float>
{
public void Foo(int x) { }
public void Foo(float y) { }
}
I would like to do the same thing in F#:
type IFoo<'a> = abstract member Foo : 'a -> unit
type Bar() =
interface IFoo<int> with
[<OverloadID("int")>]
member this.Foo x = ()
interface IFoo<float> with
[<OverloadID("float")>]
member this.Foo x = ()
But it gives a compiler error:
This type implements or inherits the same interface at different generic instantiations 'IFoo<float>' and 'IFoo<int>'. This is not permitted in this version of F#.
I can't find any discussion of this issue on the web. Is such use frowned upon for some reason? Are there plans to allow this in an upcoming release of F#?
Right now I don't know of plans to allow this.. The feature has been planned and is, at least partially (see comments) implemented in F# 4.0.
I think the only reasons its currently disallowed are that it's non-trivial to implement (especially with F# type inference), and it rarely arises in practice (I only recall one customer ever asking about this).
Given an infinite amount of time and resources, I think this would be allowed (I can imagine this being added to a future version of the language), but right now it does not seem like this is a feature worth the effort of supporting. (If you know a strong motivating case, please mail fsbugs#microsoft.com.)
EDIT
As an experiment for the curious, I wrote this C#:
public interface IG<T>
{
void F(T x);
}
public class CIG : IG<int>, IG<string>
{
public void F(int x) { Console.WriteLine("int"); }
public void F(string x) { Console.WriteLine("str"); }
}
and referenced it from F# (with comments suggesting the results)
let cig = new CIG()
let idunno = cig :> IG<_> // type IG<int>, guess just picks 'first' interface?
let ii = cig :> IG<int> // works
ii.F(42) // prints "int"
let is = cig :> IG<string> // works
is.F("foo") // prints "str"
so this is what typically happens on this 'boundary' stuff with F# - F# can consume this stuff ok, even if you can't author the same stuff from within the language.
There is a reasonable although not elegant way to do it, create a new type for each interface here is an example of consuming multiple events from an ESB (nSvcBus) which requires that each event corresponds to an implemented interface. The first type below contains the generic 'handler' code, the other types just implement the interface and call to the generic handler
type public nSvcBusEvents() =
member this.HandleEvents(msg:IEvent) = ()
//handle messages ie: let json = JsonConvert.SerializeObject(msg)
type public ActionLoggedHandler() =
interface IHandleMessages<Events.ActionLoggedEvent> with
member this.Handle(msg : ActionLoggedEvent) =
nSvcBusEvents().HandleEvents(msg)
type public ActionCompletedHandler() =
interface IHandleMessages<Events.ActionCompletedHandler> with
member this.Handle(msg : ActionCompletedHandler) =
nSvcBusEvents().HandleEvents(msg)
type public ActionFailedHandler() =
interface IHandleMessages<Events.ActionFailedHandler> with
member this.Handle(msg : ActionFailedHandler) =
nSvcBusEvents().HandleEvents(msg)
In Dart, is it possible for a function to have a prototype associated with it?
Example Javascript code:
doStuff.prototype.isDefined = true; //is there anything like Javascript's function prototypes in Dart?
function doStuff(){
console.log("The function doStuff was called!");
}
Is it possible to do the equivalent of this in Dart (i.e., create a list of properties for each function?)
Two things to address here:
First, Dart doesn't have prototypes or prototypal inheritance, and instead uses classical inheritance. Rather than a prototype, objects have a class, and instead of a prototype chain, objects have superclasses.
Second, for your specific case, I think we'd have to see more of what you need to do to figure out the idiomatic way to do it in Dart. It should soon be possible to emulate functions with objects so that you can invoke an object and still have state and other methods associated with it.
See this article for more: http://www.dartlang.org/articles/emulating-functions/
When that capability lands you'll be able to do this:
class DoStuff {
bool isDefined = true;
call() => print("The function doStuff was called!");
}
var doStuff = new DoStuff();
main() => doStuff();
Which works if you have a fixed set of metadata about your function that you need to keep track of. It's slightly different from JavaScript because each instance of the function in Dart will have its own state for isDefined. I'm not sure if it's possible or easy to get multiple instances of the function in JavasScript, but you might need to make isDefined static so that the value is shared across all instances.
Dart does not allow you to add or remove member variables from an instance of a class at runtime. Rewriting your example in Dart it might look something like this:
class doStuff {
bool isDefined;
doStuff() {
isDefined = true;
}
void stuff() {
print('The function stuff was called!');
}
}
main() {
new doStuff().stuff();
}
If you wanted to add a property bag to a class in Dart you would write:
class PropertyObject {
Map<String, Dynamic> properties;
PropertyObject() {
properties = new Map<String, Dynamic>();
}
Dynamic operator[](String K) => properties[K];
void operator[]=(String K, Dynamic V) => properties[K] = V;
}
main() {
PropertyObject bag = new PropertyObject();
bag['foo'] = 'world';
print('Hello ${bag['foo']}');
}
Note that you can't access map properties using the '.' operator.
Given an F# type:
type Foo() =
member this.Prop with get() = ()
interface IDisposable with
member this.Dispose() = ()
In C#, I create the object, but I can't call Dispose():
var x = new Foo();
x.Dispose(); // compile error, x does not contain a definition of Dispose
However, I can write:
((IDisposable)x).Dispose(); // works, but I don't like the cast
Is there any way to avoid the cast in C#? Is this related to the way F# doesn't automatically let you call .Dispose() on the Foo type from within F#?
Interface implementations in F# are explicit by default. Hence the methods are not visible unless seen from the type converted to the interface (some form of casting).
To work around this expose an instance method which has the same signature as the interface version. Then have the interface on forward to the instance function. For example
type Foo() =
member this.Prop with get() = ()
member this.Dispose() = ()
interface IDisposable with
member this.Dispose() = this.Dispose()
How about, for this particular interface:
using (var x = new Foo()) {
...
}
In C#, I can implement a generic interface twice on one class, using two different type-parameters:
interface IFoo<T> { void Foo(T x); }
class Bar : IFoo<int>, IFoo<float>
{
public void Foo(int x) { }
public void Foo(float y) { }
}
I would like to do the same thing in F#:
type IFoo<'a> = abstract member Foo : 'a -> unit
type Bar() =
interface IFoo<int> with
[<OverloadID("int")>]
member this.Foo x = ()
interface IFoo<float> with
[<OverloadID("float")>]
member this.Foo x = ()
But it gives a compiler error:
This type implements or inherits the same interface at different generic instantiations 'IFoo<float>' and 'IFoo<int>'. This is not permitted in this version of F#.
I can't find any discussion of this issue on the web. Is such use frowned upon for some reason? Are there plans to allow this in an upcoming release of F#?
Right now I don't know of plans to allow this.. The feature has been planned and is, at least partially (see comments) implemented in F# 4.0.
I think the only reasons its currently disallowed are that it's non-trivial to implement (especially with F# type inference), and it rarely arises in practice (I only recall one customer ever asking about this).
Given an infinite amount of time and resources, I think this would be allowed (I can imagine this being added to a future version of the language), but right now it does not seem like this is a feature worth the effort of supporting. (If you know a strong motivating case, please mail fsbugs#microsoft.com.)
EDIT
As an experiment for the curious, I wrote this C#:
public interface IG<T>
{
void F(T x);
}
public class CIG : IG<int>, IG<string>
{
public void F(int x) { Console.WriteLine("int"); }
public void F(string x) { Console.WriteLine("str"); }
}
and referenced it from F# (with comments suggesting the results)
let cig = new CIG()
let idunno = cig :> IG<_> // type IG<int>, guess just picks 'first' interface?
let ii = cig :> IG<int> // works
ii.F(42) // prints "int"
let is = cig :> IG<string> // works
is.F("foo") // prints "str"
so this is what typically happens on this 'boundary' stuff with F# - F# can consume this stuff ok, even if you can't author the same stuff from within the language.
There is a reasonable although not elegant way to do it, create a new type for each interface here is an example of consuming multiple events from an ESB (nSvcBus) which requires that each event corresponds to an implemented interface. The first type below contains the generic 'handler' code, the other types just implement the interface and call to the generic handler
type public nSvcBusEvents() =
member this.HandleEvents(msg:IEvent) = ()
//handle messages ie: let json = JsonConvert.SerializeObject(msg)
type public ActionLoggedHandler() =
interface IHandleMessages<Events.ActionLoggedEvent> with
member this.Handle(msg : ActionLoggedEvent) =
nSvcBusEvents().HandleEvents(msg)
type public ActionCompletedHandler() =
interface IHandleMessages<Events.ActionCompletedHandler> with
member this.Handle(msg : ActionCompletedHandler) =
nSvcBusEvents().HandleEvents(msg)
type public ActionFailedHandler() =
interface IHandleMessages<Events.ActionFailedHandler> with
member this.Handle(msg : ActionFailedHandler) =
nSvcBusEvents().HandleEvents(msg)