I'm trying to design an interface that abstracts long-running operation that should not be used from UI directly. To abstract it, I've created an abstract class with the only method to perform such an operation:
abstract class MakeSomething {
Result make(Param param);
}
However I can't mark it as async (tried to place in before the signature, before the return type and before the semicolon). Is it possible, and, if yes - how?
async functions almost always must return a Future. (An uncommon exception is async functions may have a void return type to be "fire-and-forget"; in such cases, there is no automatic way for the caller to be notified when the function completes.)
If you want your make function to be asynchronous and to provide a Result to the caller, it must return Future<Result>.
Note that async is not part of the function's type signature; async is a contextual keyword that enables the use of await inside the body of the function. That means that async is not very useful when declaring an abstract interface. The important part is that the function returns a Future, and derived classes can choose whether to implement that function using async/await.
Related
I have a factory class that is generic over T extends SomeClass<A>. But the thing is that A isn't known at the class level but only at the method level. To make myself a bit clearer with some code:
class Factory<T extends SomeClass<A>> { // Don't know A here
T<A> Function<A>(A arg) _constructor; // Function that produces my T's and is generic over A
Factory(this._constructor);
T<String> newString(String arg){ // A is only known here
return _constructor(arg);
}
T<int> newInt(int arg){
return _constructor(arg);
}
}
This obviously isn't legal Dart code, but is something to that effect even possible with Dart's generics, or does it require code generation? I tried to use extension methods, but they don't solve the problem that _constructor has the return type T<A>. And I explicitly don't want to / can't use T constructor<A, T extends SomeClass<A>>(A args).
Edit: I think what I was actually asking for is higher kinded types, which categorically aren't possible in Dart, and there is ongoing discussion on this matter (https://github.com/dart-lang/language/issues/1655). Excuse me if my understanding of the matter is incorrect.
That's not directly possible the way Dart currently works.
Dart's generics are only first order, so you cannot pass what is essentially a function from type to type as a type argument. Only plain types can be type arguments.
What you have here is a generic factory class. The kind of object it creates is defined at the class level (for ease, let's just assume that SomeClass here is Iterable, so it's a collection factory class, and you can choose, e.g., List or Set or Queue as the kind of collection to create), and then the element type of those collections are chosen when you call the factory methods.
That cannot work, because there is no type that the class can store in the class type argument which can allow that usage later.
I'd probably use separate classes and normal inheritance for this:
abstract class Factory {
Iterable<T> Function<T>(T) _constructor;
Factory(Iterable<T> Function<T>(T) constructor)
: _constructor = constructor;
Iterable<String> newString(String arg) => _constructor<String>(arg);
Iterable<int> newINt(int arg) => _constructor<int>(arg);
}
class ListFactory extends Factory {
ListFactory(List<T> Function<T>(T) constructor) : super(constructor);
List<String> newString(String arg) =>
super.newString(arg) as List<String>;
List<int> newInt(int arg) =>
super.newInt(arg) as List<int>;
}
I'm new to dart and came across code like below:
class Foo {
Foo._internal();
static final Foo instance = Foo._internal();
// other stuff
}
I was confused by that the function _internal is called twice(in line2 and line3 respectively).
Later I realized the first one is actually not an invocation but a definition of a constructor.
It's just that the body of the definition is omited(allowing this is really bad a syntax rule of Dart IMHO).
So my question become that in what cases a function of dart can omit body?
Dart provides a lot of syntactic sugar for constructors, including the ability to use a semicolon in place of an empty constructor body. Since initialization lists should be preferred when possible, it's not uncommon for constructors to have empty bodies, so the shorthand is useful. Additionally, redirecting constructors and const constructors aren't allowed to have bodies at all.
Constructors aren't functions, so that shorthand does not apply to functions and methods in general. (As another example of a distinction between constructors and functions, only constructors can be used with new and const.) For methods, distinguishing between no body and an empty body is important:
abstract class AbstractInterface {
void mustBeOverridden();
void optionallyOverridden() {}
}
I agree that a constructor like Foo._internal(); looks weird, but I think it's not a common situation since it requires the intersection of a number of cases to make it look like a method call:
The class uses a named constructor.
That constructor takes no arguments.
That constructor does not use an initializer list.
That constructor does not use a constructor body.
I'm fairly new to Dart and been trying to understand why a calling function needs to return a future? I get why the called function needs to return a future, but not the calling function itself. This doesn't seem to make sense and confuses the logic. For example, say I wanted:
List<String> someFunct() async {
final _res = await someFuture();
return _res.toList();
}
I can't do this without wrapping the calling function's return in a Future that then propagates this async model up the calling tree. The calling function is not a future, so it shouldn't need to return a future.
An asynchronous function is one which doesn't complete its work immediately when it's called. That's why it returns a Future, which is an object which will eventually make the result available.
All functions must return something when they are called. Dart does not support blocking, where a function simply stops in the middle and lets other code run until it's ready to continue, because that requires having separate stacks, and it can't be efficiently compiled to JavaScript. So an asynchronous function must return something immediately, and that something is a future.
Returning the future allows the calling function to wait until the result is available. It has to, if it needs to use the result.
In your example, someFunct wants to return a list which isn't available until later. It cannot simply return a list immediately, because it doesn't have the list yet. So, it must return a Future<List<String>>.
The one case where you don't need to return a future from an otherwise asynchronous function is when the calling function doesn't care about the result, or it gets the result in some other way, say by it being added to a collection when it's ready. Then you can just return void, and not bother with a future.
In the vast majority of cases, your asynchronous functions must return a future, because they want to return something, and that's all they have available before the real result is ready.
I am trying out the new Dart FFI in making wrappers for libsodium. Libsodium needs to be initialized with calling init(). But I don't think the user should be burdened to remember this and I also wouldn't like to check some global state variable.
I know that Go has package init() functions which run when a package gets included. Is there something similar in Dart?
Of course I could just wrap everything up into a class and run init() in the constructor but there isn't much sense in instatiating a class which basically only exposes static methods. Besides, I would like to preserve the procedural style of libsodium.
Of course I could just wrap everything up into a class and run init() in the constructor but there isn't much sense in instatiating a class which basically only exposes static methods. Besides, I would like to preserve the procedural style of libsodium.
You could have a singleton instance and expose library functions as methods on the instance, and you could provide a public getter function that automatically does initialization.
For example, something like:
Libsodium? _instance;
Libsodium get libsodium => _instance ??= Libsodium._();
class Libsodium {
Libsodium._() {
// Do initialization.
}
void foo() {
// ...
}
void bar() {
// ...
}
}
and then callers would need to use it via:
import 'libsodium.dart';
libsodium.foo();
This would hide the class instantiation and wouldn't look any different to callers than if you were to use only top-level functions with a namespace (import 'libsodium.dart' as libsodium).
Dart does not have any way to implicitly run code. No code runs before main, and all code running after main does so because it was invoked directly or indirectly from the main method. So, no.
If you need something initialized, there is a number of options.
You can use a lazily initialized static variable:
var _initialState = _init();
int doSomething(arguments) {
_initialState;
do the something.
}
The reading of _initialState will ensure that init is invoked the first time
it's needed, and not after that. You can even store things in the state for
later use.
The singleton implementation object suggested by #jamesdlin. It basically does the
same thing, then puts the methods on the object instead of being static.
Another variant is to do exactly that, but with a private instance, and have the
public top-level functions forward to the singleton object. Then you get the
procedural API and still ensures that the state object is initialized.
(This may be better for testing, allowing you to have multiple state objects alive
at the same time).
Require people to call init.
I am trying to wrap my head around this. I have to be understanding incorrectly.
Example:
Future A() { ..}
Future B() async{
await A();
print "123";
}
Why does B need to return a Future?
Doesn't await make B() synchronous? i.e., It waits for A to completely finish and then executes the print statement.
Then, What is the necessity for B to return a Future?
async and await don't make async execution sync. There is no way to do that.
All async and await does is to make async code look more like sync code. It is just syntactic sugar. Everything that can be done with async and await can be done without it as well.
Instead of deeply nested .then(...then(...then(...).catchError())).catchError(...) distinct statements, for loops, try, catch, finally can be used which makes code easier to write, read and reason about.
In Dart language an async modifier allows to use an extended syntax in asynchronous functions (and, of course, asynchronous functions which in most cases cannot return result immediately until they not completed, they return a wrapper of the future result which called in Dart a Future).
Using extended syntax means a possibility to write asynchronous operations in the same manner if you wrote a synchronous operations.
In order to be able in a single function use both synchronous and asynchronous operations the extended syntax allows to use operator await.
With operator await the asynchronous operations will look like they are synchronous operations because an operator await perform a work which can be called asynchronously wait until the operation will not completed.