Why does the identityHashCode function not work for the built-in type 'int' in Dart? - flutter

The documentation of the identityHashCode says:
And it indeed works for my custom type 'Integer':
class Integer {
int num;
Integer(this.num);
#override
int get hashCode {
return num;
}
#override
bool operator ==(Object other) {
if(other is Integer && this.num == other.num) {
return true;
}
return false;
}
}
void main() {
Integer n1 = Integer(1);
print(n1.hashCode); // print "1"
print(identityHashCode(n1)); // print "650939380", a different value!
}
But for the built-in type 'int', identityHashCode(int) seems to always return the same value as int.hashCode, which is the numerical value itself:
void main() {
int n = 1;
print(n.hashCode); // print "1"
print(identityHashCode(n)); // still print "1", the same value as n.hashCode!
}
Anyone know why this is happening? I'm confused now.😵

int is Built-in type (not a usual class)
In documentation identityHashCode has a note:
This hash code is compatible with [identical], which just means that
it's guaranteed to be stable over time.
For compiler all int values are constants. identical for the same constants shows true. So hashCode of int was made by own value (which also int).
print(identical(1, 1)); // true
According to this comment int (and double) has own condition for comparing in identical function.
By the same numeric value
Here's some code for example representation:
void main() {
int a = 1; // '1' is a constant
int b = 1;
int c = 2; // '2' is a constant
print(identical(a, b)); // true
print(identical(a, c)); // false
print(identical(1, 1)); // true
print(identical(1, 2)); // false <= 1 and 2 are constants
print(identical(a, 1)); // true
print(identical(c, 1)); // false
print(identical(c, 2)); // true
print(identityHashCode(a)); // 1
print(identityHashCode(b)); // 1
print(identityHashCode(c)); // 2
print(identityHashCode(1)); // 1
print(identityHashCode(2)); // 2
}

Related

Dart equality for different types

I want to implement class-like enum
#immutable
abstract class Enum<T> {
final T? value;
#literal
const Enum([this.value]);
List<Object?> get values => value != null ? [value] : const [];
#override
bool operator ==(Object? other) {
if (other is T) {
return value == other;
}
return other is Enum && other.value == value;
}
#override
int get hashCode => super.hashCode;
}
class EnumClass extends Enum<int> {
#literal
const EnumClass(int value) : super(value);
static const zero = const EnumClass(0);
static const one = const EnumClass(1);
// You can have any functions you want
}
so that I can do the following operations
if(EnumClass.zero == 0) {
// This works!
}
but my test failed
void main() {
test('Compare EnumClass.zero with 0', () {
if (EnumClass.zero == 0) {
print('same'); // This is printed
}
expect(EnumClass.zero, 0); // But the test failed
});
}
The comparison with 0 works as expected but the expect function doesn't work.
What should I do to make the test pass?
Note that:
expect(EnumClass.zero, 0);
fails, but:
expect(0, EnumClass.zero);
succeeds. expect(actual, expected) by default uses an equals Matcher, and the implementation for equals checks expected == actual instead of actual == expected.
Arguably it'd be more intuitive if expect(A, B) matched the original order by comparing A == B instead of B == A, but having non-symmetric equality is going to be error-prone and probably is not a good idea anyway.
Also see https://github.com/dart-lang/matcher/issues/94.

12.0 can't be identified as double nor int or numeric in flutter

I have this problem with dart. I created a simple calculator. If the result if a calculation is equal to, for example, -12.9 or 12.9. The app gives the correct answer and no error. But, if the answer given is 12.0 or -12.0, the app crashes. Why is that? I created a function to check if the string is an int or a double. It returns false.
bool isDouble(String number) {
try {
num n = num.parse(number);
if (n % 1 == 0) {
return false;
} else {
return true;
}
} catch (e) {
return false;
}
}
For the numeric, I used the isNumeric function in dart. Please help me.
As Riwen mentioned, any whole number % 1 is 0, even if it's a float. You can check the type of a variable with .runtimeType. I think when you parse the string to num, it automatically converts whole numbers to int, so you cant just check if runtimeType == "double". Also, to remove decimal values, you can just use .floor(), which will round down and convert the variable to an int.
This function seems to work:
bool isDouble(String number) {
if (int.tryParse(number) == null){
if (double.parse(number).isFinite) return true;
}
return false;
}

How to fix both Found 'DD'-anomaly and only one return statement

I have some difficulties when fixing PMD warnings, this was my simplified method:
public String rank(String keyword, int pageSize, int totalPage)
{
String result = "0"; // A: DataflowAnomalyAnalysis: Found 'DD'-anomaly for variable 'result'
if (isNotBlank(keyword))
{
boolean find = false; // B: DataflowAnomalyAnalysis: Found 'DD'-anomaly for variable 'find'
for (int page = 1; page < totalPage; page++)
{
int rank = getRank(keyword, pageSize, totalPage);
if (rank != 0)
{
find = true; // B(1)
result = String.valueOf(rank); // A(1)
break;
}
}
if (!find)
{
result = format("{0}+", totalPage * pageSize - 1); // A(2)
}
}
return result;
}
I tried this and got "OnlyOneReturn" warnings:
public String rank(String keyword, int pageSize, int totalPage)
{
if (isNotBlank(keyword))
{
for (int page = 1; page < totalPage; page++)
{
int rank = getRank(keyword, pageSize, totalPage);
if (rank != 0)
{
return String.valueOf(rank); // OnlyOneReturn
}
}
return format("{0}+", totalPage * pageSize - 1); // OnlyOneReturn
}
return "0";
}
How do I have to write this code please?
A 'DD'-anomaly an a dataflow analysis tells you that you assign a variable more than once without using it between the assignments. So all but the last assignment are unnecessary. It usually indicates that you didn't separate your scenarios properly. In your case you have three scenarios:
If the keyword is blank then the return value is "0".
Otherwise loop through all pages and if getRank() returns a rank other than zero then this is the return value.
Otherwise the return value is "totalPage * pageSize - 1+"
If you implement those scenarios one by one you end up with a method that has not any dataflow or other PMD issues:
public String rank(String keyword, int pageSize, int totalPage) {
String result;
if (isNotBlank(keyword)) {
result = "0";
} else {
int rank = 0;
for (int page = 1; page < totalPage && rank == 0; page++) {
rank = getRank(keyword, pageSize, totalPage);
}
if (rank != 0) {
result = String.valueOf(rank);
} else {
result = format("{0}+", totalPage * pageSize - 1);
}
}
return result;
}
If you take a closer look at the for loop you see that page is only used for looping. It is not used inside the loop. This indicates that the for loop is probably not necessary. getRank(keyword, pageSize, totalPage) should always return the same value as its arguments never change during the loop. So it might be enough to call getRank(...) just once.

Converting boolean integer to string value in javascript

I am reading a boolean integer value from database (0 or 1).
Is there an simple solution to convert a boolean int to boolean string?
When I was saving the value to my database I was able convert the string to an int using a javascript ternary operator.
var i = result ? 1 : 0;
Is it possible to preform the opposite?
My current work-around is:
function boolIntToString(i) {
if (i == 1) {
return true;
}
else {
return false;
}
}
The expression i != 0 evaluates to boolean false if i = 0, or true otherwise, so to get true or false, you could simply write:
var theBool = i != 0;
If you want a string, you can call .toString() on that boolean result. Wrapping this into your function, you get:
function boolIntToString(i) {
return (i != 0).toString();
}
console.log(boolIntToString(1));
Note that your own function returns a boolean, not a string.

Issue with getting 2 chars from string using indexer

I am facing an issue in reading char values.
See my program below. I want to evaluate an infix expression.
As you can see I want to read '10' , '*', '20' and then use them...but if I use string indexer s[0] will be '1' and not '10' and hence I am not able to get the expected result.
Can you guys suggest me something? Code is in c#
class Program
{
static void Main(string[] args)
{
string infix = "10*2+20-20+3";
float result = EvaluateInfix(infix);
Console.WriteLine(result);
Console.ReadKey();
}
public static float EvaluateInfix(string s)
{
Stack<float> operand = new Stack<float>();
Stack<char> operator1 = new Stack<char>();
int len = s.Length;
for (int i = 0; i < len; i++)
{
if (isOperator(s[i])) // I am having an issue here as s[i] gives each character and I want the number 10
operator1.Push(s[i]);
else
{
operand.Push(s[i]);
if (operand.Count == 2)
Compute(operand, operator1);
}
}
return operand.Pop();
}
public static void Compute(Stack<float> operand, Stack<char> operator1)
{
float operand1 = operand.Pop();
float operand2 = operand.Pop();
char op = operator1.Pop();
if (op == '+')
operand.Push(operand1 + operand2);
else
if(op=='-')
operand.Push(operand1 - operand2);
else
if(op=='*')
operand.Push(operand1 * operand2);
else
if(op=='/')
operand.Push(operand1 / operand2);
}
public static bool isOperator(char c)
{
bool result = false;
if (c == '+' || c == '-' || c == '*' || c == '/')
result = true;
return result;
}
}
}
You'll need to split the string - which means working out exactly how you want to split the string. I suspect you'll find Regex.Split to be the most appropriate splitting tool in this case, as you're dealing with patterns. Alternatively, you may want to write your own splitting routine.
Do you only need to deal with integers and operators? How about whitespace? Brackets? Leading negative numbers? Multiplication by negative numbers (e.g. "3*-5")?
Store the numerical value in a variable, and push that when you encounter an operator or the end of the string:
int num = 0;
foreach (char c in s) {
if (isOperator(c)) {
if (num != 0) {
operand.Push(num);
num = 0;
}
operator1.Push(c);
if (operand.Count == 2) {
Compute(operand, operator1);
}
} else {
num = num * 10 + (int)(c - '0');
}
}
if (num != 0) {
operand.Push(num);
}