Null-aware operator with Lists - dart

In Dart the null-aware operator for methods in combination with the ?? operator does not work well.
Image having a call chain like this:
object.getter.getter.getter.getter
Now when object could be null and I do not want an exception I have to write this:
object?.getter?.getter?.getter?.getter
That is a null check for every getter, even though only object can be null, but then the getter's obviously do not work.
I am okay with this. But now I have a scenario, where I want to return another value if null, but I am working with a list:
list[index][index][index]
How do I use the null-aware operator on the List getter?
This does not work:
list?[index]
and this does not exist for List's in Dart.
list?.get(index)
I want to achieve something like this:
list?[index]?[index]?[index] ?? 0
Where I know that only list will ever be null.
This long code would work:
list == null ? 0 : list[index][index][index]

There is no null-aware operator for the indexing operator ([])
You can use elementAt() instead:
list?.elementAt(index)?.elementAt(index)?.elementAt(index) ?? 0
UPDATE - 2021/05/24
If you are using null-safety, you can now use this:
list?[index]?[index]?[index] ?? 0

Related

confused about the null safety dart

The argument type 'int?' can't be assigned to the parameter type 'num'.
when using darts with 'null safety', this code gets an error but when I use the version of darts without null safety the test runs successfully (without error). My question is how do I change this code so that it doesn't error on darts with null safety?
If you take a look at the documentation of the [] operator on Map:
V? operator [](
Object? key
)
V? here means that the type of the value V will always be nullable. The reason for this is because of the following detail for this operator:
The value for the given key, or null if key is not in the map.
https://api.dart.dev/stable/2.18.1/dart-core/Map/operator_get.html
So the reason for your error is because your code is not prepared for the case of [] returns null in case the key are not in your Map.
There are multiple solutions for this problem which depends on how sure you are about the specific piece of code and what behavior you want in case of failure.
If you are e.g. completely sure that curr will always point to a valid key in the Map you can do: scarScore[curr]! (notice the !). This will add a runtime null-check and crash your application in case the value from the [] operator ends up being null.
Alternative, if you expect some keys to not be in the Map, you can provide default values like prev + (scarScore[curr] ?? 0) where null will then be assumed to be translated to the value 0.
For a detailed explanation for why the [] operator are nullable, you can read: https://dart.dev/null-safety/understanding-null-safety#the-map-index-operator-is-nullable

Why Dart holds *double standard* between `==` and `>=`

I have two int values in Dart, test them equals or not with == previously, it was fine. Now I have to test if first one is greater or equals to the second one, so I changed == to >= instinctively, but it seems Dart was not happy with me doing that
I double checked documentation of Dart, >= should work to test greater or equals operation
IMO, in the end, if >= has something wrong, then the same should come to ==
You are comparing two different operators which comes from different part of the Dart language. The == operator is defined on Object:
https://api.dart.dev/stable/2.15.1/dart-core/Object/operator_equals.html
Which needs to be able to compare every type of object including null. The reason why the == operator does not have Object? as input parameter is because of the following detail in the Dart Language Specification (page 167) under the section "Equality":
Evaluation of an equality expression ee of the form e1 == e2 proceeds as follows:
The expression e1 is evaluated to an object o1.
The expression e2 is evaluated to an object o2.
If either o1 or o2 is the null object (17.4), then ee evaluates to true if both o1 and o2 are the null object and to false otherwise. Otherwise,
evaluation of ee is equivalent to the method invocation o1.==(o2)
...
https://dart.dev/guides/language/specifications/DartLangSpec-v2.10.pdf
So based on third rule, the language itself will make sure that null values are compared correctly and therefore the Object.== method will never see a null object as its input.
The other operator is >= and comes (in your case) from num which int extends from:
https://api.dart.dev/stable/2.15.1/dart-core/num/operator_greater_equal.html
And is specified to accept only num (so int or double) which are a non-nullable type (null is therefore not allowed).
You are then trying to call the num.>= operator with the result from values?.length. This is a problem since values is nullable and can therefore potentially be null. And when you use the ?. operator, you are saying that if values are null, don't care calling .lenght but instead just return null.
So the type of values?.length ends up being int? which is not compatible with num.

How check type reference - dart

If I have a object like this:
class MyClass<K>{...
How I could check type of K? If was a variable was easy,
ex:
(myVar is Object)... //true | false
But in my case, this dont works:
(K is Object) // awalys false
You want == here. Using is is for comparing the type of variable, not a literal type.
This will only check if K is actually Object if you use K == Object. If you pass K as int for instance, it will not be considered to be an Object.
I recommend not using == for comparison of Type objects. It only checks exact equality, which might be useful in a few situations, but in plenty of situations you do want a subtype check.
You can get that subtype check using a helper function like:
bool isSubtype<S, T>() => <S>[] is List<T>;
Then you can check either isSubtype<K, Object> to check if K is a subtype of Object (which is true for everything except Null and types equivalent to Object?, but that can also be checked like null is! K), or isSubtype<Object, K> to check whether K is a supertype of Object.
It has the advantage that you can compare to any type, not just types you can write literals for. For example K == List only works for List<dynamic>. If you need to check whether K is a List<int>, you can do isSubtype<K, List<int>>.
You can get equivalence of types (mutual subtype), without requiring them to be the same type, by doing isSubtype in both directions. For example isSubtype<Object?, dynamic>() and isSubtype<dynamic, Object?>() are both true, but if K is Object? then K == dynamic is false.

Why does pattern matching records in Erlang throw error

Hello i am trying to use record syntax in Erlang to both bind a variable to the enclosing record and to one of its fields and i keep getting this error:
d:/Erlang/AeRlang/rec.erl:19: syntax error before: child
d:/Erlang/AeRlang/rec.erl:17: function isMale/1 undefined
d:/Erlang/AeRlang/rec.erl:17: Warning: function maleChildren/1 is
unused
-module(rec).
-export([makeFam/0]).
-record(man,{name,
age,
children=[]}).
-record(child,{
name,
age,
sex
}).
makeFam()->
#man{name="Adrian",
age=33,
children=[#child{name="Daniel",age=33,sex="Male"},
#child{name="Chris" ,sex="Male"},
#child{name="Anne",age=33,sex="Female"}]
}.
fatherAndSons(Man#man{children=Ch})->{Man,[Elem|| Elem<-Ch,isMale(Elem)]}.
isMale(C#child{_,_,Y})->
case Y of
"Male"->true;
_ ->false
end.
What is wrong in my isMale method.I am binding the enclosing structure #child to the variable C and i am also pattern matching on of its fields.What is the problem ?
P.S: Does it have to do with the fact that in isMale method i did not specify the name of the field of which i binded the variable Y?
For both the fatherAndSons/1 and isMale/1 functions, you're using the wrong syntax for matching a record as a function argument. Here are some corrected versions:
fatherAndSons(Man=#man{children=Ch}) -> {Man, [Elem || Elem <- Ch, isMale(Elem)]}.
isMale(#child{sex="Male"})-> true;
isMale(_) -> false.
In the function head for fatherAndSons/1 we're essentially saying "Man is expected to be a #man record whose children field we'll bind to Ch". The = operator is what does the matching, but you were missing that for the Man binding.
For isMale/1 I'm using two clauses, where the first clause matches all #child records whose sex field matches the string "Male"and the second clause matches anything else. If you want to keep the second clause restricted to matching only #child records, you could instead use:
isMale(#child{sex="Male"})-> true;
isMale(#child{}) -> false.
Either way, note that there's no need to bind the record to a variable in the function head for isMale/1 since you don't need the binding in the function body.
There are some wrongs in the way get sex in your child record. You can change your functions fatherAndSons/1 and isMale/1 like below:
fatherAndSons(Man#man{children=Ch})->{Man,[Elem|| Elem<-Ch,isMale(Elem) == true]}.
isMale(C)->
case C#child.sex of
"Male"->true;
_ ->false
end.
Or just remove your isMale/1 and pattern matching in list comprehension:
fatherAndSons(Man#man{children=Ch})->
{Man, [Elem || Elem <-Ch, Elem#child.sex == "Male"]}.

What is meant by ?? in Dart

I saw this operator in Example of Shared Preferences for Flutter plugin. And I didn't get it.
int counter = (prefs.getInt('counter') ?? 0) + 1;
It is called null-aware operator
Meaning, if and only if prefs.getInt('counter') returns null assign 0 to it and then increment by one.
Here, you can find a great blog post about null-aware operator: http://blog.sethladd.com/2015/07/null-aware-operators-in-dart.html

Resources