Weird behavior with Maps(A nullable expression can't be used as a condition) - dictionary

Map<String,bool> map= { "key1":true, "key2":false };
/*
* Flags following compilation error:
* A nullable expression can't be used as a condition.
* Try checking that the value isn't 'null' before using it as a condition.
*/
if(map["key1"]) {
//do sth
}
/*So I try checking value isn't null as specified in error
*Still flags same compilation error
*/
if(map!=null && map["key1"]) {
//do sth
}
//This works
if(map["key1"] == true) {
//do sth
}
}
Based on the following snippet, may I know why both the 1st and 2nd if blocks fail but not the 3rd?

You misunderstood the error message.
A nullable expression can't be used as a condition.
means that you can't do:
bool? condition;
if (condition) {
...
}
Map<K, V>'s operator[] returns a V?. It returns a nullable type as a way of indicating failure when the key isn't found, and you need to check that the returned value isn't null, not that map itself is not null. For example:
if (map["key"] ?? false) {
...
}
Your third approach (which checks == true) works because it will perform a null == true equality check if the lookup returns null. However, you should prefer using ?? false since it conveys the intent better, and equality checks against true or false are usually a code smell.

The [] operator on Map can return null which makes it nullable which is explained in details here: https://dart.dev/null-safety/understanding-null-safety#the-map-index-operator-is-nullable
So your first example is invalid since null is not a bool. So you cannot directly use the value from the [] operator for a Map.
Your second example is invalid for the same reason since map["key1"] is bool?.
Third example works since null == true is always false. So it is fully valid to make a comparison which involves something which can be null.

Related

Reflection struct field.Set with a Flag pointer value

I have a bunch of flags parsed, and I'm then trying to assign those values to fields in a struct, but I'm struggling to get a parsed flag value set into the struct because I can't type assert it or cast it.
Here is a snippet of the code I have. It's not important to worry too much about the IterFields function, basically the third argument is called for each field in the struct...
Note: there are comments in the code below which highlight the error(s).
flag.Parse()
IterFields(st, v, func(field reflect.Value, sf reflect.StructField) {
flag.VisitAll(func(f *flag.Flag) {
if f.Name == strings.ToLower(sf.Name) || f.Name == sf.Tag.Get("short") {
fmt.Printf("%+v, %T\n", f.Value, f.Value)
// PRINTS: true, *flag.boolValue
if v, ok := f.Value.(bool); ok {
fmt.Println("ok")
} else {
fmt.Println("not ok")
}
// ERROR: impossible type assertion: bool does not implement flag.Value (missing Set method)
field.Set(reflect.ValueOf(f.Value))
// PANIC: value of type *flag.boolValue is not assignable to type bool
}
})
})
f.Value is an interface type flag.Value abstracting all kinds of flag values. As your code indicates, it's not of type bool but some non-exported *flag.boolValue. You shouldn't be concerned about its dynamic type.
You may use the Value.String() method to get its value as a string, which will be either "false" or "true" for bool types, you may use simple comparison to obtain a bool from it like f.Value.String() == "true".
But a better approach would be: all flag.Value values originating from the flag package also implement flag.Getter which also has a Get() method that will directly return a bool value in case of a bool flag (wrapped in interface{} of course). Just use that:
field.Set(reflect.ValueOf(f.Value.(flag.Getter).Get()))
The above works for fields of any type (given that the flag's value type is assignable to the field's type).
For bool fields only, alternatively you may also use:
field.SetBool(f.Value.(flag.Getter).Get().(bool))

How to get class of Any? variable in Kotlin?

I want my equals to compare class too and I wrote
override fun equals(other: Any?): Boolean {
return this::class == other::class && ...
}
unfortunately it swears
Expression in a class literal has a nullable type 'Any?', use !! to make the type non-nullable
But I want to compare with nulls too. What about glorious "null safety"? They forgot it for reflection? I didn't find ?:: operator or something.
Think about this. The class is actually not different between a String and a String?, it's only the type that differs. You cannot invoke that operator on nullable types since it could mean you invoke it on null which would lead to a NullPointerException:
val x: String? = null
x!!::class //throws NPE
With the help of the scope function let you can ensure it isn't null and use the class literal syntax:
return other?.let { this::class == other::class } ?: false
The Elvis operator ?: is used to handle the null case by making the expression false (not equal).

Idiomatic way to access properties of union type

What is the idiomatic way to access properties of union type that may be missing in one of the types merged in the union?
type DataColumn = {
value: number;
};
type CalculatedColumn = {
calculation: string;
};
type Column = DataColumn | CalculatedColumn;
function getValue(c: Column) {
return c.value || c.calculation;
}
Flow typecheck results in the following error:
13: return c.value || c.calculation;
^ property `calculation`. Property not found in
13: return c.value || c.calculation;
^ object type
#dfkaye pointed out on twitter that if there is an error thrown for the "default" case, it works:
function e() {
throw new Error('foo');
}
function getValue(c: Column) {
return c.value || c.calculation || e();
}
Can somebody explain:
Why it works? Is it intentional, or a side effect?
Why is it necessary? Column type has always either value or calculation, so error case should never happen.
Is there a better, more idiomatic way?
Is this a safe approach, or is it likely to break in future?
PS: Seems like in TypeScript it can be done using type assertions.
The idiomatic way is to use disjoint unions. This passes with no errors:
type DataColumn = {
kind: 'data';
value: number;
};
type CalculatedColumn = {
kind: 'calculated';
calculation: string;
};
type Column = DataColumn | CalculatedColumn;
function e() {
throw new Error('foo');
}
function getValue(c: Column) {
return c.kind === 'data' ? c.value : c.calculation;
}
getValue({kind: 'data', value: 123});
getValue({kind: 'calculated', calculation: 'foo'});
I'm not actually sure why the case you described doesn't work. I can't think of any reason it would be unsound. But disjoint unions definitely work.
Why it works? Is it intentional, or a side effect?
It's most likely a bug, Flow simple ignores all branches but last:
function getValue(c: Column) {
return c.value || c.calculation || undefined;
}
Why is it necessary? Column type has always either value or calculation, so error case should never happen
This is where you are wrong. If value has a type { value: number } it means that it can have any other property of any type, including calculation of type string or may be of some other type.
Is there a better, more idiomatic way?
Yes, see Nat Mote's answer
Is this a safe approach, or is it likely to break in future?
It's not safe in principle, so it's very likely to break in the future
Seems like in TypeScript it can be done using type assertions.
You can do the same thing in Flow, but it's unsafe:
function getValue(c: Column) {
return ((c: any): DataColumn).value || ((c: any): CalculatedColumn).calculation;
}
Also you should not forget that numbers and string can be falsey.

Groovy NullObject should be null or not?

This example can be easily tested in the groovy console.
var a is evaluated to not null while b is evaluated to null.
Both are instances of org.codehaus.groovy.runtim.NullObject
def b = null
println b.getClass()
println b == null
def a = null.getClass().newInstance()
println a.getClass()
println a == null
Does anyone knows why?
This is a tricky thing when dealing with reflection code.
Actually I am wondering if this is not a bug. As an explanation... NullObject is a runtime/intermediate kind of Object. If you do anything on null, then NullObject is used. This, and the the implementation of NullObject#equals speaks for a==null returning true. It returns fails, because there is some internal code before that, that is for example determining if compareTo is called instead of equals and such things. Now this piece of code starts with
if (left == right) return true;
if (left == null || right == null) return false;
so null==null will return true, but NullObject==null will return false. On the other hand NullObject should not leak out if possible. Maybe we should fix newInstance() to return null.
I filled http://jira.codehaus.org/browse/GROOVY-5769 for this
In the equals method of NullObject, it only returns true if you are comparing it to null
As an instance of NullObject is not strictly null, it returns false...
Whether NullObject should return true if you call equals against another NullObject is probably a question best asked on the mailing list... I'll have a look and see if I can find any previous question.

Simplest way to check if a string converted to a number is actually a number in actionscript

Not sure if this makes sense, but I need to check if a server value returned is actually a number. Right now I get ALL number values returned as strings
ie '7' instead of 7.
What's the simplest way to check if string values can actually be converted to numbers?
The easiest way to do this is to actually convert the string to a Number and test to see if it's NaN. If you look at the Flex API reference, the top-level Number() function says it will return NaN if the string passed to the method cannot be converted to a Number.
Fortunately, Flex (sort of) does this for you, with the isNaN() function. All you need to do is:
var testFlag:Boolean = isNaN( someStringThatMightBeANumber );
If testFlag is false, the string can be converted to a number, otherwise it can't be converted.
Edit
The above will not work if compiling in strict mode. Instead, you will need to first convert to Number and then check for NaN, as follows:
var testFlag:Boolean = isNaN( Number( someStringThatMightBeANumber ) );
Haven't tested this, but this should work:
if( isNaN(theString) ) {
trace("it is a string");
} else {
trace("it is a number");
}
If you are using AS3 and/or strict mode (as pointed out by back2dos), you will need to convert to number first in order for it to compile:
if( isNaN(Number(theString)) ) {
trace("it is a string");
} else {
trace("it is a number");
}
Most of the answers on this question have a major flaw in them. If you take Number(null) or Number(undefined) or Number(""), all will return 0 and will evaluate to "is a number". Try something like this instead:
function isANumber( val:* ):Boolean {
return !(val === null || val === "" || isNaN(val));
}
RegExp path :
function stringIsAValidNumber(s: String) : Boolean {
return Boolean(s.match(/^[0-9]+.?[0-9]+$/));
}
Here is another way to check if value can be converted to a number:
var ob:Object = {a:'2',b:3,c:'string'};
for( var v:* in ob){
var nr:Number = ob[v];
trace(ob[v]+" "+(nr === Number(nr)))
}
this will trace following:
2 true
3 true
string false
You can notice that in actionscript :
trace(int('7')); // will return 7
and
trace(int('a')); // will return 0
So except for zeros, you can actually now if a string is a number or not
this will try to convert your String to a Number, which essentially is a 64 bit floating point number:
var val:Number = Number(sourceString);
if sourceString is not a valid String representation of a Number, val will be NaN (not a number) ... you have check against that value with isNaN ... because val == NaN will return false for a reason that can't quite understand ... you can use int(val) == val to check, whether it is an integral value ...
greetz
back2dos
Put this into any function where you want only numbers to stayjoy_edit1 is a TextInput Object (spark)
//is a number check
if( isNaN(Number(joy_edit1.text)) ) {
joy_edit1.text = "";
return void;
}
function isANumber(__str:String):Boolean
{
return !isNaN(Number(__str));
}
You should use the native solution of Adobe:
parseInt and parseFloat methods.
Also read the isNaN description:
Returns true if the value is NaN(not a number). The isNaN() function
is useful for checking whether a mathematical expression evaluates
successfully to a number. The most common use of isNaN() is to check
the value returned from the parseInt() and parseFloat() functions. The
NaN value is a special member of the Number data type that represents
a value that is "not a number."
Here is a simple implementation:
function isANumber(value:String):Boolean {
return !isNaN(parseFloat(value));
}
typeof('7') == 'string'
typeof(7) == 'number'
Does that help?

Resources