I saw a Dart screencast about Futures and how to handle them. It said there are two ways of handling some Futures that mixed with sync code. This is the example code:
import 'dart:async';
Map sanitizeParams(Map p) {/*.....*/}
Future sendToServer(Map p) {/*.....*/}
Future sendParams(Map params) => sendToServer(sanitizeParams(params));
Above is the less preferred way, and here is the code that is better (according to the one who made the screencast) :
import 'dart:async';
Map sanitizeParams(Map p) {/*.....*/}
Future sendToServer(Map p) {/*.....*/}
Future sendParams(Map params) =>
new Future.value(params)
.then(sanitizeParams)
.then(sendToServer);
Why is the second one preferred?
First reason is readability: sanitizeParams needs to happen before sendToServer but it reads in different order, which is preferably avoided when working with futures.
The more important reason is that if sanitizeParams throws an exception then sendParams won't return a future but throw instead, and this makes it harder to compose it with other futures. The second example avoids this by first making the arguments available as Future (Future.value) and then chaining other functions on that.
IIRC, this is explained in the screencast.
Related
my linter is telling me this await is unnecessary:
Unnecessary await keyword in return.
I thought if you're calling a function inside an async function and you want to get/return the value, rather than the future you had to use await to designate you want the value, not the future.
Am I missing something here?
As the documentation for that recommendation points out, you can take off the async and just return the Future, rather than using await:
Future<Dictionary> get _localDir => getApplicationDocumentsDirectory();
This is called "eliding async/await". Stephen Cleary wrote an article about it (written for C#, but largely applicable for any language that uses async and await), which you may find helpful: Eliding Async and Await
In short, it's more efficient to do this in situations when you can:
By not including these keywords, the compiler can skip generating the async state machine. This means that there are fewer compiler-generated types in your assembly, less pressure on the garbage collector, and fewer CPU instructions to execute.
I got a strong background in C# and Javascript and there is nothing I am not getting on Dart with Futures :
Say I got a Future like this :
scoreFile.exists().then((r) => {
if (r){
List<ScoreRow> previousScores = await scoreFile.readAsString();
scores = jsonDecode(previousScores);
}
});
I know this is not allowed because I need to make my callback a foo() function. But why clutter the space with a code to be used only in this place ? I mean, I really need to create as many little functions as I have callbacks ?
I wouldn't do so with really complex processing, (which would be untestable if not put in a proper function) but for such a simple process ?
Or maybe Dart design is "there is no such thing as simple code not to be tested"
Because from a syntaxical point of view, my function already exists, she is just anonymous : she is stored in braces :)
Thank you for your insight :)
I'm not entirely sure what the problem is here.
Your code mixes async and non-async code, which is usually something to avoid unless absolutely necessary (which it rarely is).
You could perhaps write the code as:
if (await scoreFile.exists()) {
scores = jsonDecode(await scoreFile.readAsString());
}
or you could continue doing what you are doing (fixing syntax and type issues):
scoreFile.exists().then((r) async {
if (r) {
var previousScores = await scoreFile.readAsString();
return jsonDecode(previousScores);
}
}).then((scores) {
// use the scores variable.
});
If you use the then approach, then yes, you will have to make a lot of little callbacks because that's how it works. If you use the async/await syntax, those callbacks will be made for you.
I am attempting to write two versions of the same program:
a performant version; and
a slower version that lets the user know what's happening.
I imagine it's not entirely disimilar to how an IDE might implement a normal/debug mode.
My requirements, in decreasing order of importance, are as follows:
the slow version should produce the same results as the performant version;
the slow version should wrap a subset of public function calls made by the performant version;
the requirement for the slower version should not adversely effect the performance of the performant version;
preferably no code reproduction, but automated reproduction where necessary;
minimal increase in code-base size; and
ideally the slow version should be able to be packaged separately (presumably with a one-way dependence on the performant version)
I understand requirement 6 may be impossible, since requirement 2 requires access to a classes implementation details (for cases where a public function calls another public function).
For the sake of discussion, consider the following performant version of a program to tell a simple story.
class StoryTeller{
void tellBeginning() => print('This story involves many characters.');
void tellMiddle() => print('After a while, the plot thickens.');
void tellEnd() => print('The characters resolve their issues.');
void tellStory(){
tellBeginning();
tellMiddle();
tellEnd();
}
}
A naive implementation with mirrors such as the following:
class Wrapper{
_wrap(Function f, Symbol s){
var name = MirrorSystem.getName(s);
print('Entering $name');
var result = f();
print('Leaving $name');
return result;
}
}
#proxy
class StoryTellerProxy extends Wrapper implements StoryTeller{
final InstanceMirror mirror;
StoryTellerProxy(StoryTeller storyTeller): mirror = reflect(storyTeller);
#override
noSuchMethod(Invocation invocation) =>
_wrap(() => mirror.delegate(invocation), invocation.memberName);
}
I love the elegance of this solution, since I can change the interface of the performant version and this just works. Unfortunately, it fails to satisfy requirement 2, since the inner calls of tellStory() are not wrapped.
A simple though more verbose solution exists:
class StoryTellerVerbose extends StoryTeller with Wrapper{
void tellBeginning() => _wrap(() => super.tellBeginning(), #tellBeginning);
void tellMiddle() => _wrap(() => super.tellMiddle(), #tellMiddle);
void tellEnd() => _wrap(() => super.tellEnd(), #tellEnd);
void tellStory() => _wrap(() => super.tellStory(), #tellStory);
}
This code can easily be auto-generated using mirrors, but it can result in a large increase in the code-base size, particularly if the performant version has an extensive class hierarchy and I want to have a const analogue to const variables of a class deep in the class tree.
Also, if any class doesn't have a public constructor, this approach prevents the separation of the packages (I think).
I've also considered wrapping all methods of the base class with a wrap method, with the performant version having a trivial wrap function. However, I'm worried this will adversely effect the performant version's performance, particularly if the wrap method was to require, say, an invocation as an input. I also dislike the fact that this intrinsicly links my performant version to the slow version. In my head, I'm thinking there must be a way to make the slower version an extension of the performant version, rather than both versions being an extension of some more general super-version.
Am I missing something really obvious? Is there an in-built 'anySuchMethod' or some such? I'm hoping to combine the elegance of the proxy solution with the completeness of the verbose solution.
You could try to put the additional debugging code inside asserts(...). This gets automatically removed when not run in checked mode. See also
Is there a compiler preprocessor in Dart?
How to exclude debug code
How to achieve precompiler directive like functionality
Otherwise just make a global constant (const bool isSlow = true/false;) Use interfaces everywhere and factory constructors which return the slow or the fast implementation of an interface depending on the isSlow value.
The slow version can just extend the fast version to reuse its functionality and extend it by overriding its methods.
This way you don't have to use mirrors which causes code bloat, at least for client side code.
When you build all unnecessary code is removed by tree-shaking, depending on the setting of isSlow.
Using dependency injection helps simplify this way of developing different implementations.
I have been lately programming with the FSharpx library and especially its TaskBuilder. Now I wonder if it should be possible to define a function which takes parameters and takes a result. Such as
let doTask(parameter:int) =
let task = TaskBuilder(scheduler = TaskScheduler.Current)
task {
return! Task.Factory.StartNew(fun() -> parameter + 1)
}
match FSharpx.Task.run doTask(1) with
| _ -> ()
Looking at the source code I see run expects a function taking no parameters and returning a Task<'a>. There doesn't look like being examples on FSharpx TaskTests either.
I'd appreciate if someone could advice how should I get a scenario like this going with FSharpx or if one isn't supposed to use the library like this for a reason I haven't quite grasped as of yet.
<edit: I believe I could wrap doTask as follows
wrapperDoTask() = doTask(101)
match FSharpx.Task.run wrapperDoTask with
| _ -> ()
And it might work. I'm not with a compiler currently, so this is a bit of a handwaving. Does anyone have an opinion on any direction or did I just answer my own question? :)
<edit2:
I think I need to edit this one more time based on MisterMetaphor's answer. Especially his P.S., I think, was well informing. I use FSharpx TaskBuilder to interop with C#, in which, as noted, tasks are returned as hot (with some minor exceptions), already running. This is in connection with my recent question Translating async-await C# code to F# with respect to the scheduler and in relation Orleans (I'll add some tags to beef up the context, maybe someone else is pondering these too).
When thinking in C# terms, what I try to achieve is to await the task result before returning, but without blocking. The behaviour I'm after is especially of that of await not .Result. The difference can be read, for instance, from
Await, and UI, and deadlocks! Oh my!
Don't Block on Async Code.
Trying to think which context or scheduler or behavior or something is going on in terms of C# is somewhat fuzzy for me. Unfortunatelly it looks like I can't ignore all the details when it comes to interop. :)
You need to use Task.run only if you want to wait for the task completion synchronously on the current thread. It takes a single parameter and you can consider that parameter a task factory -- i.e. a means to create a Task<_>. Unlike Async<_>, the Task<_> starts running as soon as it is created. That is not always a desirable behavior.
You could achieve similar results (a blocking wait for task completion) with (doTask 101).Result, but I think Task.run is more idiomatic to F#, in a way that it uses a Result return type to signal an error instead of raising an exception. It might be arguable which is better, depending on situation, but in my experience in simpler cases a special result type is more composable than exceptions.
Another point here is that you should avoid blocking waits (Task.run, .Wait(), .Result) as much as you can. (Ideally, you'd have one of those only at the top level of your program.)
P.S. This if out of scope of the question, but your doTask function looks funny. task { return! Task.Factory.StartNew( ... ) } is equivalent to Task.Factory.StartNew( ... ). What you probably wanted to do is task { return parameter + 1 }.
EDIT
So, in response to OP's question edit :) If you need the await behavior from C#, you just need to use let! .... Like this:
task {
let! x = someTask 1 2 3
return x + 5
}
I'm going over some older Dart code, addressing breaking changes with the latest Dart SDK. This one I can't figure out:
Future<DateTime> get lastsave =>
client.lastsave.transform((int unixTs) =>
new DateTime.fromMillisecondsSinceEpoch(unixTs * 1000, isUtc:true));
=>
The method 'transform' is not defined for the class 'Future<List<int>>'
From what I understand, the purpose of Future.transform() was to apply a synchronous transformation (see e.g. this discussion thread). I.e. convert the async call to a sync call and return the value.
Has Future.transform been replaced with something else?
Must have been quite a while since that code was updated ;)
Just replace transform with then and it should work.
From https://groups.google.com/a/dartlang.org/forum/#!topic/misc/Boch2XH9Tmk
We have also improved the Future class, and made it simpler to use. One simple “then” methods lets you apply asynchronous or synchronous functions to the result of a future, merging the three methods “chain”, “transform” and “then”. Streams and Futures should make asynchronous Dart programs easier to write and read, and should reduce some types of programming errors.