Unable to Understand this Flutter Closure Function Code? - flutter

var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
I dont Understand Two Things :
print(i) is of return-type Void, shouldnt the compiler show "error", because the work of print(i) is to print the item to the console and not return something.
in the line " callbacks.forEach((c) => c()); " how come c() became a function, because it was a parameter inside the lambda function to get values.
the link of the Code :
https://dart.dev/guides/language/language-tour#type-test-operators
under for Loops
PS : I am a beginner to this syntax, so Thank you so much for your Help Guys !

var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
Here, () => print(i) is a closure which takes no arguments and returns void. In the loop, you add these functions to the callback list.
(c) => c() is a closure which takes a dynamic parameter and attempts to call it (i.e. calls c.call()).
Some type safety might be helpful here, for example:
final callbacks = <void Function()>[]; // an empty list of functions that look like () -> void
for (var i = 0; i < 2; i++) {
final void Function() callback = () => print(i);
callbacks.add(callback);
}
callbacks.forEach((void Function() callback) => callback());
In this example, because callbacks has a type of List<void Function()>, the parameter of the function passed to forEach is a void Function(), which means you can call it with c()

Related

why I can't run my code where is the problem of this code?

void main() {
const list = [1, 2, 3, 4];
final odd = where(list, (value) => value % 2 == 1);
print(odd);
}
List<T> where<T>(List<T> items, bool Function(T) f) {
var results = <T>[];
for (var item in items) {
if (f(item)) {
results.add(item);
}
}
return results;
}
this kind of error show in my terminal
lib/exercises/18-implement-where-function.dart:3:44: Error: The operator '%' isn't defined for the class 'Object?'.
'Object' is from 'dart:core'.
Try correcting the operator to an existing operator, or defining a '%' operator.
final odd = where(list, (value) => value % 2 == 1);
void main() {
const list = [1, 2, 3, 4];
final odd = where(list, (value) => value! % 2 == 1);
print(odd);
}
List<T> where<T>(List<T> items, bool Function(T) f) {
var results = <T>[];
for (var item in items) {
if (f(item)) {
results.add(item);
}
}
return results;
}
The operator '%' isn't defined for the type 'Object'.
Try defining the operator '%'
Possible Dart analyzer is not able to infer type.
It's better to wait for the answer from the developers.
A workaround as below:
void main() {
const list = [1, 2, 3, 4];
final odd = where(list, (int value) => value % 2 == 1);
print(odd);
}
List<T> where<T>(List<T> items, bool Function(T) f) {
var results = <T>[];
for (var item in items) {
if (f(item)) {
results.add(item);
}
}
return results;
}
P.S.
I also encounter this issue from time to time in Dart.
On the one hand, the type is not explicitly specified (for parameter value) and must be inferred, on the other hand, it is not clear why it is not inferred from another type (aslo T), which is inferred from the value (in our case. list) wuth the same type parameter (T).
I've run your code on https://dartpad.dev/dart, it's working though. I think there is an issue with your import classes.

ToObservable is not firing in some cases

RX is synchronous by default so we can confirm it
int j = 0;
Observable.Range(1, 2)
.SelectMany(i => {
return new[]{1}.ToObservable()
.Select(i1 => {
new[]{1}.ToObservable().Subscribe(i2 => j = 1);
return 0;
})
;
})
.Subscribe();
j.ShouldBe(1);
however in my code base I have a similar query that does not fire unless i use the Immediate scheduler.
public static IObservable<GitHubIssue> Save(this IObservable<IReadOnlyList<Issue>> source, IGitHubRepository repository){
var objectSpace = repository.ObjectSpace;
return source.SelectMany(list => list.ToObservable().Select(issue => {
var gitHubIssue = objectSpace.CreateObject<GitHubIssue>();
gitHubIssue.Id = issue.Id;
issue.Labels.ToObservable(Scheduler.Immediate).Select(label => {
var gitHubLabel =objectSpace.GetObjectsQuery<GitHubLabel>(true).FirstOrDefault(_ => label.Name == _.Name) ??
objectSpace.NewGitHubLabel(label);
gitHubIssue.Labels.Add(gitHubLabel);
return gitHubLabel;
}).Subscribe();
//previous selector is not executed
i fail to see the relation and why this happens
"RX is synchronous by default" - No, it is not. Each operator has its own default.
Take Observable.Range for example. Here's the implementation for when you don't provide a Scheduler:
public virtual IObservable<int> Range(int start, int count)
{
return Range_(start, count, SchedulerDefaults.Iteration);
}
Which in turn uses:
internal static IScheduler Iteration
{
get
{
return CurrentThreadScheduler.Instance;
}
}
If I take Observable.Timer as an counterpoint, I have this code:
public virtual IObservable<long> Timer(TimeSpan dueTime)
{
return Timer_(dueTime, SchedulerDefaults.TimeBasedOperations);
}
Which uses:
internal static IScheduler TimeBasedOperations
{
get
{
return DefaultScheduler.Instance;
}
}
The fact that you have to put in .ToObservable(Scheduler.Immediate) says you have an operator that doesn't use Scheduler.Immediate by default.
Now, ignoring all of this, what you should never ever do inside an observable pipeline is subscribe to another observable. Never ever. When you do this you are relying on side-effects and that's what's going wrong in your code.
You should always assume that any call to Subscribe runs sometime in the future, so even your assertion that j.ShouldBe(1) shouldn't ever be used after a Subscribe.
Your sample code should be more like this:
int j = 0;
Observable
.Range(1, 2)
.SelectMany(i =>
{
return
new[] { 1 }
.ToObservable()
.Select(i1 =>
{
return 1;
})
;
})
.Subscribe(x =>
{
j = x;
/* j only valid here */
});
/* j NOT valid here */
Rational concrete example of a side-effect:
int j = 0;
Observable
.Delay(Observable.Return(42), TimeSpan.FromSeconds(2.0))
.Do(x => j = x)
.Subscribe();
Console.WriteLine(j);
Ultimately j will be equal to 42, but not when Console.WriteLine(j) is called. Never rely on state outside of the observable that's updated within the observable.

Dart Map increment the value of a key

I'm currently working with a Map in which the values are of type integer but I need to update the value of a key every time an action takes place. Example: if the Map is { "key1": 1 } after the actions takes place it should be {"key1":2} and so on. Here's my code:
void addToMap(Product product) {
if (_order.containsKey(product.name)) {
_order.update(product.name, (int) => _order[product.name]+1);
}
_order[product.name] = 1;
}
Where _order is the Map
You may use the following idiomatic approach in Dart:
map.update(
key,
(value) => ++value,
ifAbsent: () => 1,
);
This uses the built-in update method along with the optional ifAbsent parameter that helps set the initial value to 1 when the key is absent in the map. It not only makes the intent clear but also avoids pitfalls like that of forgetting to place the return statement that had been pointed out in the other answer.
Additionally, you may also wrap up the above method as an Extension to Map<dynamic, int>. This way also makes the call site look much less cluttered, as visible from the following demo:
extension CustomUpdation on Map<dynamic, int> {
int increment(dynamic key) {
return update(key, (value) => ++value, ifAbsent: () => 1);
}
}
void main() {
final map = <String, int>{};
map.increment("foo");
map.increment("bar");
map.increment("foo");
print(map); // {foo: 2, bar: 1}
}
Add return or the map will always get overridden by _order[product.name] = 1;
void addToMap(Product product) {
if (_order.containsKey(product.name)) {
_order.update(product.name, (int) => _order[product.name]+1);
return;
}
_order[product.name] = 1;
}

setTimeout global variable [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
var delayTime = 2000;
for(var i = 0; i<this.textToWrite.length; i++){
setTimeout(
(
function (s){
return function () {
this.writeText += s;
console.log(this.writeText);
}
}(this.textToWrite[i])
), delayTime)
delayTime += 2000;
}
have some problem with this.writeText. It's global variable but when i even comment += s line then i have undefined value... (I set writeText: string = "" globaly) Is this.writeText reference to global variable? How can I access global variables in this example?
I need assing char from textToWrite object to writeText with 2s delay.
The problem can be that you used function word.
setTimeout(
((s) => {
return () => {
this.writeText += s;
console.log(this.writeText);
}
}(this.textToWrite[i])
), delayTime)
Another way is to use it without this if its global variable:
setTimeout(
((s) => {
return () => {
writeText += s;
console.log(this.writeText);
}
}(this.textToWrite[i])
), delayTime)
Only use arrow functions
settimeout(x => {
console.log(x);
}, 1000);
not like this and it will not accept out side parameters
settimeout(funtion(x) {
console.log(x);
}, 1000);

How to use promise in if condition

I am trying following lines of code to get a numeric value when condition is met
this.getMessageThreadsPosition = function (k, sub, callback) {
console.log(sub);
for(var i = 1; i <= k; i++){
commonsMethod.findElementDriver(that.messageSubjectTextPath(i)).then(function(foundelement){
foundelement.getText().then(function(text){
console.log(text);
if(text == sub){
callback(i);
}
});
});
}
};
But it seems that it never goes inside if condition.