I need something like:
if (variable != null) {
otherVariable = variable;
}
Is there a neater way to write this with NullOperators? All I came up with is:
(variable != null) ? otherVariable = variable : null;
There is currently no special operator in Dart which allows an assignment to be dependent on the assigned value being non-null.
The closest operator is ??= where otherVariable ??= variable; does the opposite of what you want: It assigns variable to otherVariable if otherVariable is null, not if variable is non-null.
You could use ?? and go with otherVariable = variable ?? otherVariable;, which assigns the current value of otherVariable back to itself if variable is null. It still performs an assignment in that case, which might be detectable if otherVariable is a setter.
I'd just go with if (variable != null) otherVariable = variable;. It's currently the shortest code which does exactly what you want: Assign to otherVariable only if variable is not null.
This is the shortest way would be :
otherVariable = (variable != null) ? variable : null;
But in your case, if it is null, then why do you assign it 'null' when variable is already null? You could have done this:
otherVariable = variable;
In both the codes same thing happens. Use the Second code as it is short, and use the first one if you have to replace the 'null' by something else like this:
otherVariable = (variable != null) ? variable : 'default';
Related
In the code below to implement the Singleton design pattern, we approach two different ways.
One of them creates Singleton but the other creates an object each time we call it.
What's the difference between ?? and =?? in the code below written in dart?
class ExampleStateByDefinition extends ExampleStateBase {
static ExampleStateByDefinition? _instance;
ExampleStateByDefinition._internal() {
initialText = 'A new "ExampleStateByDefinition" instance has been created.';
stateText = initialText;
print(stateText);
}
static ExampleStateByDefinition? getState() {
return _instance ?? ExampleStateByDefinition._internal(); //here we use ??
}
}
The above code creates an object each time we call it, so let us look at another variant:
class ExampleStateByDefinition extends ExampleStateBase {
static ExampleStateByDefinition? _instance;
ExampleStateByDefinition._internal() {
initialText = 'A new "ExampleStateByDefinition" instance has been created.';
stateText = initialText;
print(stateText);
}
static ExampleStateByDefinition? getState() {
_instance ??= ExampleStateByDefinition._internal(); //Here we use ??=
return _instance;
}
}
The above code implements Singleton by definition in Design Patterns: Elements of Reusable Object-Oriented Software
The ??= operator is a compound assignment operator.
Just like target += 1 is equivalent to target = target + 1 (but with target only evaluated once, if it's a complicated expression),
target ??= expression is equivalent to target = target ?? expression (but with target only evaluated once and the assignment not even happening if target is non-null).
So, the difference is that the first code probably doesn't work, the second one does.
The code:
return _instance ?? ExampleStateByDefinition._internal();
checks whether _instance is non-null, and if so, it returns the value of _instance. If it is null, it evaluates and returns ExampleStateByDefinition._internal().
No-where in that does it assign to _instance. So, _instance is always going to be null, and the code is probably failing to do what it intended to do—caching a value.
The code:
_instance ??= ExampleStateByDefinition._internal();
return _instance;
or its more streamlined version:
return _instance ??= ExampleStateByDefinition._internal();
will also check if _instance is null and return its value if it isn't.
If _instance is null, it also evaluates ExampleStateByDefinition._internal();, and then it assigns it to _instance, and returns the value.
The next time you come around, _instance will be non-null, and the lazy caching works.
Both ?? and ??= are null-aware operators.
Difference
The difference between the two operators is that the former only evaluates an expression while the latter also assigns the result of the expression.
This is why your first sample returns a new instance each time since you never assign it to your static variable.
??
Use ?? when you want to evaluate and return an expression IFF another expression resolves to null.
The following expression:
exp ?? otherExp;
Is similar to this expression:
((x) => x == null ? otherExp : x)(exp);
??=
Use ??= when you want to assign a value to an object IFF that object is null. Otherwise, return the object.
The following expression:
obj ??= value;
Is similar to this expression:
((x) => x == null ? obj = value : x)(obj);
See Null-aware operators in Dart for reference.
Based on dart tour.
To assign only if the assignment to the variable is null we use ??= operation.
expr1 ?? expr2 if expr1 is not null, return its value; otherwise, evaluates and return the value of expr2.
Cause ?? operation evaluates each time we call the object, it creates a new object.
Is there any way to get this to return "default" without writing out special functions to check the argument and set it?
void main() {
Thing stuff = Thing(text: null);
print(stuff.text);
}
class Thing{
String text;
Thing({this.text: "default"});
}
I have a map coming in from Firebase and sometimes values will be null and I'd like my class to use its default values when it is provided null.
Thing({text}) : this.text = text ?? 'default';
You will need to add this small snippet because default values in constructors only work if there is no value specified.
The ?? null-aware operator will only use the 'default' value if the value that is being passed is actually null (which will also be the case if no value is specified).
I've recently came across this question How do I solve the 'Failed assertion: boolean expression must not be null' exception in Flutter
where the problem comes from a should be invalid code that gets treated as valid.
This code can be summarized as :
int stuff;
if (stuff = null) { // = instead of ==
}
But why does this code compiles ? As the following will not.
int stuff;
if (stuff = 42) {
}
With the following compile error :
Conditions must have a static type of 'bool'.
So I'd expect out of consistency that if (stuff = null) to gives the same error.
null is a valid value for a bool variable in Dart, at least until Dart supports non-nullable types.
bool foo = null;
or just
bool foo;
is valid.
Therefore in the first case there is nothing wrong from a statical analysis point of view.
In the 2nd case the type int is inferred because of the assignment, which is known to not be a valid boolean value.
bool foo = 42;
is invalid.
When you say var stuff; with no initial value it is giving stuff a static type of dynamic. Since dyamic might be a bool, it's legal to assign null to a variable of type dynamic, and it's legal to use a possibly null bool in a conditional, the compiler doesn't flag this. When you say int stuff; the compiler knows that stuff could not be a bool. The reported error in that case is cause by the static type of stuff, not the assignment to null.
Edit: Got the real answer from someone who knows how to read the spec.
The static type of an assignment expression is the right hand side of the assignment. So the expression stuff = null has the static type of Null which is assignable to bool.
The reasoning is that the value of an assignment is the right hand side, so it makes sense to also use it's type. This allows expressions like:
int foo;
num bar;
foo = bar = 1;
Commonly assignment operation returns the value that it assigns.
int a = 0;
print(a = 3);//Prints 3
So,
When stuff = null,
'stuff = null' returns null. if statement needs a boolean .null is a sub-Type of boolean.
if(null){}
is valid
When stuff = 42,
'stuff = 42' returns 42. if statement needs a boolean .42 is not a sub-Type of boolean.
if(42){}
is not valid
I have a varible containing an object which might be null. When trying to call a method I have to check for null. I want the result to be false if the variable is null. What is considered good and readable style to to this?
e.g.
class MyClass {
bool boolMethod() {
return true;
}
}
void main() {
MyClass mc = new MyClass();
MyClass mcnull = null;
bool val1 = mc?.boolMethod();
bool val1null = mcnull?.boolMethod();
bool val2 = mc != null && mc.boolMethod();
bool val2null = mcnull != null && mcnull.boolMethod();
}
Especially when used in if-statements I consider the first version much more readable:
if (mc?.boolMethod())...
versus
if (mc != null && mc.boolMethod())...
But IntelliJ gives me the hint The value of the '?.' operator can be 'null' which isn't appropriate as an operand of a locaical operator. (null_aware_in_logical_operator). Ok - this is right because when the variable is null then I use the null as a boolean value. But it's ok in my case and I try to avoid suppressing warnings.
What is the suggested way? Other ideas?
I think a common pattern is
bool val1 = (mc?.boolMethod() ?? false);
The parens aren't required here but if such expressions are embedded into more complex expressions they are often necessary to get the expected behavior because of the low priority of ??
I have an int value defined in one of my method:
int value = [self someMethodThatGetsAnINT];
Later on I have some "ifs" that check upon this value.
How to I express: if (value == nil)?
When I try do this intuitive code writing I get a warning saying:
Semantic Issue: Comparison between pointer and integer ('int' and 'void *')
nil is just a 0 :) Try this :
if (0 == value)
However, why would you be testing nil against an int - something sounds funny here :)
If you really want a nil value returned, you should probably be using NSNumber as your return type instead of int. NSNumber is an class that wraps scalar values in objective-c. You can put an integer in it when you have a valid return value, or return nil when you don't.
you can probably use if (value == (int)nil) but really a function that returns an int shouldn't return nil as nil is not an integer (although it may be represented similarly).
this may help clear it up a little