Error: A value of type 'num?' can't be assigned to a variable of type 'num' because 'num? - flutter

I found this error while running the dart project
Error: A value of type 'num?' can't be assigned to a variable of type 'num' because 'num?'
import 'dart:io';
void main() {
print("Enter your birth-year");
var n = num.tryParse(stdin.readLineSync() ?? "");
if(n=="") {
print("Bad Year");
}
var age = DateTime.now().year-n;
print(" ==> You are $age year old!");
}

As you can read in the documentation of num.tryParse, the method has an return type of num?. This implies that your variable n is also of the type num? (Nullable num).
So the error points you to the line, where you want to subtract an nullable number from DateTime.now().year, which is not allowed.
You can workaround this limitation by using the ?? (Null coalescing) operator and checking for null and if your n is null subtract 0.
var age = DateTime.now().year - (n ?? 0) ;
Another solution is, just using an if checking for null followed by an else block, like:
if(n == null) {
print("Bad Year");
}
else {
var age = DateTime.now(). year - n ;
print(" ==> You are $age year old!");
}
Taking up your comment:
i added ! after n and works fine... that is the same solution?
Adding the null-assertion operator (!) to the n in DateTime.now().year - n! is not the same solution, but it is a possible solution. And as you already mentioned it compiles and work.
But be careful:
You are telling the compiler that you are sure, that n will never be null.
With your current code you will get an runtime error, when the user enters a letter or nothing. Then the parsing of that string fails and your n is null. And now you want to subtract null from the DateTime.now().year, which is again not allowed.
You can read more about Null-Safety on https://dart.dev/codelabs/null-safety .
Side note:
The following check is not correct:
if(n=="") {
print("Bad Year");
}
If an incorrect number was entered, your n is null and this is not equal to an empty string. To get your if clause work, simply use a null check. I also recommend to add a return after the output, otherwise your person gets quite old.
if(n == null) {
print("Bad Year");
return;
}

Related

dart null safty issue when try to add value to map element

I am using Dart but i am facing null safty issue with following code
RxMap<Product,int>cartItems=Map<Product,int>().obs;
void updateCart(Product product,String type){
if(type=="plus") {
cartItems.value[product]++;
}
else {
cartItems.value[product]--;
}
}
i got the following error message
the method '+' can't be unconditionally invoked because the receiver can be 'null'
i tried to add null check to the target as following
cartItems.value![product]++;
You can give a default value if null.
cartItems.value[product]??0 +1
Or force assert to non null value like this.It may throw exception if element not present in HashMap
cartItems.value[product]!+1
In your question you are asserting not null for HashMap not the value of the HashMap.
The problem is that cartItems.value is a Map and it's possible that cartItems.value[product] is null. In this case you can't add or remove 1 to null.
So you should do like the following:
if (type == "plus") {
cartItems.value[product] = (cartItems.value[product] ?? 0) + 1;
} else {
cartItems.value[product] = (cartItems.value[product] ?? 0) - 1;
}
Using (cartItems.value[product] ?? 0) you're saying that if cartItems.value[product] is null 0 is used instead.
Also note that in the else clause, when cartItems.value[product] == null, you're trying to remove 1 to something that doesn't exist, so in that case it may be best to throw an exception:
int? currentValue = cartItems.value[product];
if (currentValue == null) {
throw Exception('Trying to remove on a null object');
}
cartItems.value[product] = currentValue - 1;

returnMap[date]++; error : The method '+' can't be unconditionally invoked because the receiver can be 'null'

Hello I try to make null safety migration, but I have an error with ++ from returnMap[date]++; . I don't know how to write correctly in null stafety. Thank you
Here is my code
thank you
for (var i = x; i < list_conso.length; i++) {
DateTime parsedDate = DateTime.parse(list_conso[i]);
String date = "${parsedDate.year}-${parsedDate.month}-${parsedDate.day}";
date = DateFormat('yyyy-MM-dd').format(parsedDate);
if (returnMap.containsKey(date)) {
returnMap[date]++; //The method '+' can't be unconditionally invoked because the receiver can be 'null'
} else {
returnMap[date] = 1;
}
}
Since you have checked that returnMap contains date, you can use:
returnMap[date]!++;
The exclamation mark tells the compiler you are sure that returnMap[date] exists and is not null.

Conditional Operators (??) issues in dart

void main() {
print("Conditional Operators:");
// small if else
var a1 = 100;
var b2 = 20;
var istrue = (a1 < b2) ? 'True' : 'False';
print(istrue);
// check if null or print name
var name1;
var check = name1 ?? "This is Null";
print(check);
var name = "Abdulelah";
var checknot = name ?? "This is Null";
print(name);
}
I don't how i fix this problem in line 16
yellow error said:
The left operand can't be null, so the right operand is never executed.
Try removing the operator and the right operand.dartdead_null_aware_expression
The variable "name" won't be NULL because you give to him the value "Abdulelah", so the right part ?? "This is NULL" won't be executed, remove this right part and the warning will disappear.
Using ?? we provide default value in null case.
a = x ?? y
The above example shows that if x return/becomes null, y will be initialized on a. The fact becomes.
if x is not null, then a = x
if x is null, then a = y
Instead of using if, else we use ?? to provide null handler value.
The editor is acting smart here because it knows that name is not null, so the yellow message is saying you don't need to provide default value because left expression will never be null.
To create null variable, you need to use
DataType? variableName;
In this case you are initializing String and you can do
String? name = "Abdulelah";
But this is not needed unless you want to initialize null value on name variable.
You can check
Difference between var and dynamic type in Dart?
and dart.dev for more.

Flutter Parse Method Explanation

I have a String date in format Month-Day-4DigitYear that I want to convert to DateTime in Flutter. I'm a novice coder, and I'm struggling to understand the api.flutter.dev Parse method example.
Below is the example. I just have a few issues. Android Studio throws multiple errors when I just create a class and put in this function. I think I understand the non-nullable issue, so I delete the ! and ? marks everywhere.
My issues are: what are _parseFormat, _brokenDownDateToValue, _withValue ?
All give errors and just declaring the first two and deleting the _withValue doesn't seem to do the trick, although removes all errors. It's like they've left out a key portion that I'm missing or there is a package I need to import the neither I nor Android Studio knows about. Can anyone decrypt this? I get very frustrated with flutter's documentation, as it always seems to give 80% of required info, assuming you already are clairvoyant on all other topics except this single one they are discussing. Gotta be a pro before reading the manual.
// TODO(lrn): restrict incorrect values like 2003-02-29T50:70:80.
// Or not, that may be a breaking change.
static DateTime parse(String formattedString) {
var re = _parseFormat;
Match? match = re.firstMatch(formattedString);
if (match != null) {
int parseIntOrZero(String? matched) {
if (matched == null) return 0;
return int.parse(matched);
}
// Parses fractional second digits of '.(\d+)' into the combined
// microseconds. We only use the first 6 digits because of DateTime
// precision of 999 milliseconds and 999 microseconds.
int parseMilliAndMicroseconds(String? matched) {
if (matched == null) return 0;
int length = matched.length;
assert(length >= 1);
int result = 0;
for (int i = 0; i < 6; i++) {
result *= 10;
if (i < matched.length) {
result += matched.codeUnitAt(i) ^ 0x30;
}
}
return result;
}
int years = int.parse(match[1]!);
int month = int.parse(match[2]!);
int day = int.parse(match[3]!);
int hour = parseIntOrZero(match[4]);
int minute = parseIntOrZero(match[5]);
int second = parseIntOrZero(match[6]);
int milliAndMicroseconds = parseMilliAndMicroseconds(match[7]);
int millisecond =
milliAndMicroseconds ~/ Duration.microsecondsPerMillisecond;
int microsecond = milliAndMicroseconds
.remainder(Duration.microsecondsPerMillisecond) as int;
bool isUtc = false;
if (match[8] != null) {
// timezone part
isUtc = true;
String? tzSign = match[9];
if (tzSign != null) {
// timezone other than 'Z' and 'z'.
int sign = (tzSign == '-') ? -1 : 1;
int hourDifference = int.parse(match[10]!);
int minuteDifference = parseIntOrZero(match[11]);
minuteDifference += 60 * hourDifference;
minute -= sign * minuteDifference;
}
}
int? value = _brokenDownDateToValue(years, month, day, hour, minute,
second, millisecond, microsecond, isUtc);
if (value == null) {
throw FormatException("Time out of range", formattedString);
}
return DateTime._withValue(value, isUtc: isUtc);
} else {
throw FormatException("Invalid date format", formattedString);
}
}
My issues are: what are _parseFormat, _brokenDownDateToValue, _withValue ?
These are objects or functions declared elsewhere in the lib which are private (the _ as the first character declares objects and functions as private) and therefore not shown in the documentation.
_parseFormat seems to be a regular expression.
_brokenDownDateToValue seems to be a function.
_withValue is a named constructor.
I think what you want to use is the following if you want to parse your date String to a DateTime object.
var date = "11-28-2020"; // Month-Day-4DigitYear
var dateTime = DateTime.parse(date.split('-').reversed.join());
See https://api.flutter.dev/flutter/dart-core/DateTime/parse.html for the accepted strings to be parsed.
I did find the full code example here.
It didn't use the name _parseFormat, instead just RegExp? And has _withValue and _brokenDownDateToValue declarations.
As I see it, there isn't a proper way to decode their example. The example is insufficient. A dictionary should not create definitions using words that can't be found elsewhere in the dictionary.

How to return a variable in a function in kotlin

I created a function that recieves input and compare it to a list, when find a match it return the match, in this case this match is the attribute of a class that i created.
I understand that the problem is with the return statement, so in the beginning of the function I declare the return as "Any", further more than that I'm kinda lost.
The error is this: A 'return' expression required in a function with a block body ('{...}')
class Class1(var self: String)
var test_class = Class1("")
fun giver(){
test_class.self = "Anything"
}
class Funciones(){
fun match_finder(texto: String): Any{
var lista = listOf<String>(test_class.self)
var lista_de_listas = listOf<String>("test_class.self")
var count = -1
for (i in lista_de_listas){
count = count + 1
if (texto == i){
lista_de_listas = lista
var variable = lista_de_listas[count]
return variable
}
}
}
}
fun main(){
giver()
var x = "test_class.self"
var funcion = Funciones()
var y = funcion.match_finder(x)
println(y)
}
To explain you what the problem is, let's consider the following code:
class MyClass {
fun doSomething(): String {
val numbers = listOf(1, 2, 3)
for (number in numbers) {
if (number % 2 == 0) {
return "There is at least one even number in the list"
}
}
}
}
If you try compiling it you'll get the same error message as in your question: A 'return' expression required in a function with a block body ('{...}'). Why is that?
Well, we defined a function doSomething returning a String (it could be any other type) but we're returning a result only if the list of numbers contains at least one even number. What should it return if there's no even number? The compiler doesn't know that (how could it know?), so it prompts us that message. We can fix the code by returning a value or by throwing an exception:
class MyClass {
fun doSomething(): String {
val numbers = listOf(1, 2, 3)
for (number in numbers) {
if (number % 2 == 0) {
return "There is at least one even number in the list"
}
}
// return something if the list doesn't contain any even number
return "There is no even number in the list"
}
}
The same logic applies to your original code: what should the function return if there is no i such that texto == i?
Please also note that the solution you proposed may be syntactically correct - meaning it compiles correctly - but will probably do something unexpected. The for loop is useless since the if/else statement will always cause the function to return during the first iteration, so the value "There is no match" could be returned even if a match actually exists later in the list.
I searched online, if someone has the same problem, the correct code is as follows:
class Funciones(){
fun match_finder(texto: String): Any{
var lista = listOf<String>(test_class.self)
var lista_de_listas = listOf<String>("test_class.self")
var count = -1
var variable = " "
for (i in lista_de_listas){
count = count + 1
if (texto == i){
lista_de_listas = lista
var variable = lista_de_listas[count]
return variable
} else {
return "There is no match"
}
}
return variable
}
}