I am looking for the alternative of javascript for in in dart:js?
for example:
if('addEventListener' in event) {
event.addEventListener(change);
}
I used is operator, but it's throwing an error in Safari becouse addEventListener does not exist in event.
if(event.addEventListener is Function) {
event.addEventListener(change);
}
Checking whether an object supports a specific method is not something you do in Dart. You should check that the object implements an interface which has that method.
In this example, you probably need:
if (event is EventTarget) {
event.addEventListener("change", change);
}
If you think that the object might support the function, but you don't actually know which interface it gets the function from, then you can do what you try here, using a dynamic lookup, but you need to catch the error you get if the function isn't there.
dynamic e = event; // if it isn't dynamic already.
Object addEventListener;
try {
addEventListener = e.addEventListener;
} on Error {
// ignore.
}
if (addEventListener is Function) {
addEventListener(...);
}
Related
Suppose we need to execute some code when a function finishes, no matter how.
Example:
void myFunc() async {
await myLock.acquire();
if(...) {
myLock.release();
return;
}
...
myLock.release();
}
Many languages have features that allow to achieve this in a more elegant way than just manually calling myLock.release() before every return statement (For example defer in Go). Is something like that also possible in Dart?
Dart does not have RAII. You instead would need to use try-finally.
(Dart did recently (in 2.17) add Finalizers, but those would fire when objects are garbage collected, which might happen at some non-deterministic time, if ever.)
And just for the record, an example of using try/finally:
void myFunc() async {
await myLock.acquire();
try {
if(...) {
return;
}
...
} finally {
myLock.release();
}
}
You'd want to start the try after allocating the resource, so that you don't try to release if allocation throws.
I have a list<Components> components; which is sub-class of Bonus, hence Bonus are Components too.
The .toRect() method is defined in the Bonus class but not in the Components class.
I'm making sure I'm only calling .toRect() in Bonus objects, so there should be no problem, but Dart is keeping me from running the code with the following error:
The method 'toRect' isn't defined for the type 'Component'.
Is there a way to go around this problem without the need to define .toRect() on the Components Class?
void checkForCollision() {
controller.components.where((c) => c is Bonus).forEach((bonus) {
if (this.toRect().contains(bonus.toRect().topLeft) ||
this.toRect().contains(bonus.toRect().topCenter) ||
this.toRect().contains(bonus.toRect().topRight)) {
this.remove = true;
}
});
}
Could do:
.forEach((bonus) {
Bonus bonus = bonus;
.....
or
(controller.components.where((c) => c is Bonus) as List<Bonus>).forEach((bonus) {
Use whereType to filter on types. It's like where that just checks for a type, but it also ensures that the resulting iterable has that element type.
controller.components.whereType<Bonus>().forEach((bonus) {
... bonus.toRect ...
});
The Dart style guide recommends not using a function literal with forEach, use a for-loop instead:
for (var bonus in controller.components.whereType<Bonus>()) {
... bonus.toRect ...
}
If you are doing that anyway, you can also just do:
for (var component in controller.compenents) {
if (component is Bonus) {
.. component.toRect ...
}
}
The type promotion from the is check will ensure that you can call toRect.
This very directly specifies what's going on, without creating unnecessary intermediate iterables.
I am using a redux pattern in my dart application. Inside the reducer the if statement that has the "is" keyword to figure out which action(in the form of a class) is being passed is not working at all.
DictionaryState dictionaryReducer(DictionaryState state, dynamic action){
if(action is RequestingDictionaryEntryAction){
// This if statement should be executed but it is not.
return _requestingDictionaryEntry(state);
}
if(action is ReceivedDictionaryEntryAction){
return _receivedDictionaryEntry(state, action);
}
return state;
}
When calling dictionaryReducer I am passing an action called RequestingDictionaryEntryAction and it is not being recognized as RequestingDictionaryEntryAction, instead the code continues to execute and the function does not return as it is supposed to.
Just off the top of my head, so don't put in too much faith, but your problem might lie in the "dynamic" type of the parameter causing the is operator to fail at compile-time. I would think it could be solved using:
DictionaryState dictionaryReducer(DictionaryState state, dynamic action){
if(action.runtimeType == RequestingDictionaryEntryAction){
return _requestingDictionaryEntry(state);
}
if(action.runtimeType == ReceivedDictionaryEntryAction){
return _receivedDictionaryEntry(state, action);
}
return state;
}
The problem was in the argument I was passing as action. I was not instantiating the class properly. I was passing the class declaration itself instead of an instant of it.
final action = RequestingDictionaryEntryAction instead of
final action = RequestingDictionaryEntryAction();
:D :D
I am calling a function which returns a structure of the type CvBox2D, however I want to check for an error in the function and return NULL if there is an error.
CvBox2D function()
{
...
if(ERROR)
return NULL;
...
}
I am getting an error : cannot convert from 'int' to 'CvBox2D'
Your function return type is CvBox2D, so you can't convert a (NULL) pointer to it.
If you really need to return "nothing" if the check inside the function fails, you can change the return type to a pointer to CvBox2D:
CvBox2D* function()
{
...
}
You will also have to change the way the returned object is created inside your function.
Note that using raw pointers in C++ usually isn't a good idea.
Take a look at std::shared_ptr (available in C++11) if you think you really have to use pointers.
If you want to return some error code, you can do the following:
int function(CvBox2D* output) {
// code...
// Assign to struct.
output->center = ...;
if (error) {
return RC_ERROR_FOO;
}
return RC_OK;
}
Then you call this function using a struct you've already allocated (for example, on the stack):
{
CvBox2D myBox;
int retval = function(&myBox);
if (RC_OK == retval) {
printf("Good! Angle of box: %g", myBox.angle);
} else {
printf("Error: %d", retval);
}
}
Where RC_OK, RC_ERROR_FOO are defined as constant integers, or better, as an enum (if you're using C++).
The other answers solve your problem, but if you want to keep the signature of your function, instead of returning an error code, you should throw an exception.
I'm trying to really get Futures in Dart and I've noticed that just about every example I come across uses handleException to deal with exceptions that complete the Future. Yet the API documentation states "In most cases it should not be necessary to call handleException, because the exception associated with this Future will propagate naturally if the future's value is being consumed. Only call handleException if you need to do some special local exception handling related to this particular Future's value."
So when would I need "special local exception handling"? Could someone explain that in a bit more detail? Is there some code that I honestly can't run easily by letting the exception propagate?
Mads Ager gave me this answer:
Basically, this is the equivalent of having a try-catch in straight-line code:
int doSomethingElse() {
try {
return thisMightFail();
} catch(e) {
return -1;
}
}
void doSomething() {
int value = doSomethingElse();
// operate on value
}
With Futures it is something like this (not tested):
Future<int> doSomethingElse() {
return thisMightFail().transformException((e) => -1);
}
void doSomething() {
doSomethingElse().then((value) {
// operate on value
});
}
So this is for local exception handling instead of global exception handling. If you never use handleException or transformException that would correspond to always dealing with exceptions at the top level in non-async code.