When working with a sort function, the implemented node i had created seems to cause some issues.
I have tracked it down to the comparison of Nodes in the Merge function of MergeSort. That being said, the line of code in question is:
if (_tmpArray[i] <= _tmpArray[j])
_tmpArray is defined in the the constructor, but given content value in the merge
Node implementation of operator ==, operator <, operator <= are as follows.
bool operator ==( Node<T> other) => identical(this, other);
bool operator <( Node<T> other){
//other is of same type, T.
if (_value.compareTo(other) == -1){
return true;
}
return false;
}
bool operator <= ( Node<T> other){
return (this == other) || (this < other);
}
It seems that maybe my implementation is wrong. I am doing a test inside of main with a List of size 400, of T = int.
Attached is my Dartpad file: https://dartpad.dartlang.org/612422345f1ac8a27f8e
It seems that the comparison of: _value.compareTo is not correct because T doesnt have compareTo in this case of int being T. When converting the int to "String" which is comparable though compareTo it still shows the same error.
//other is of same type, T.
if (_value.compareTo(other._value) == -1){
// ^^^^^^^ was missing
return true;
}
return false;
Related
Let's say I have:
class Test<T> {
void method() {
if (T is int) {
// T is int
}
if (T == int) {
// T is int
}
}
}
I know I can override == operator but what's the main difference between == and is in Dart if I don't override any operator.
Edit:
Say I have
extension MyIterable<T extends num> on Iterable<T> {
T sum() {
T total = T is int ? 0 : 0.0; // setting `T == int` works
for (T item in this) {
total += item;
}
return total;
}
}
And when I use my extension method with something like:
var addition = MyIterable([1, 2, 3]).sum();
I get this error:
type 'double' is not a subtype of type 'int'
identical(x, y) checks if x is the same object as y.
x == y checks whether x should be considered equal to y. The default implementation for operator == is the same as identical(), but operator == can be overridden to do deep equality checks (or in theory could be pathological and be implemented to do anything).
x is T checks whether x has type T. x is an object instance.
class MyClass {
MyClass(this.x);
int x;
#override
bool operator==(dynamic other) {
return runtimeType == other.runtimeType && x == other.x;
}
#override
int get hashCode => x.hashCode;
}
void main() {
var c1 = MyClass(42);
var c2 = MyClass(42);
var sameC = c1;
print(identical(c1, c2)); // Prints: false
print(identical(c1, sameC)); // Prints: true
print(c1 == c2); // Prints: true
print(c1 == sameC); // Prints: true
print(c1 is MyClass); // Prints: true
print(c1 is c1); // Illegal. The right-hand-side must be a type.
print(MyClass is MyClass); // Prints: false
}
Note the last case: MyClass is MyClass is false because the left-hand-side is a type, not an instance of MyClass. (MyClass is Type would be true, however.)
In your code, T is int is incorrect because both sides are types. You do want T == int in that case. Note that T == int would check for an exact type and would not be true if one is a derived type of the other (e.g. int == num would be false).
Basically, == is equality operator and "is" is the instanceof operator of Dart (If you come from Java background, if not, it basically tells you if something is of type something).
Use == for equality, when you want to check if two objects are equal. You can implement the == operator (method) in your class to define on what basis do you want to judge if two objects are equal.
Take this example:
class Car {
String model;
String brand;
Car(this.model, this.brand);
bool operator == (otherObj) {
return (otherObj is Car && other.brand == brand); //or however you want to check
//On the above line, we use "is" to check if otherObj is of type Car
}
}
Now you can check if two cars are "equal" based on the condition that you have defined.
void main() {
final Car micra = Car("Micra", "Nissan");
print(micra == Car("Micra", "Nissan")); // true
print(micra is Car("Micra", "Nissan")); // true
}
Hence, == is something you use to decide if two objects are equal, you can override and set it as per your expectations on how two objects should be considered equal.
On the other hand, "is" basically tells you if an instance is of type object (micra is of type Car here).
The following line of code has two question marks:
final myStringList = prefs.getStringList('my_string_list_key') ?? [];
What is the meaning?
The ?? double question mark operator means "if null". Take the following expression, for example.
String a = b ?? 'hello';
This means a equals b, but if b is null then a equals 'hello'.
Another related operator is ??=. For example:
b ??= 'hello';
This means if b is null then set it equal to hello. Otherwise, don't change it.
Reference
A Tour of the Dart Language: Operators
Null-aware operators in Dart
Terms
The Dart 1.12 release news collectively referred to the following as null-aware operators:
?? -- if null operator
??= -- null-aware assignment
x?.p -- null-aware access
x?.m() -- null-aware method invocation
Dart offers some handy operators for dealing with values that might be null. One is the ??= assignment operator, which assigns a value to a variable only if that variable is currently null:
int a; // The initial value of a is null.
a ??= 3;
print(a); // <-- Prints 3.
a ??= 5;
print(a); // <-- Still prints 3.
Another null-aware operator is ??, which returns the expression on its left unless that expression’s value is null, in which case it evaluates and returns the expression on its right:
print(1 ?? 3); // <-- Prints 1.
print(null ?? 12); // <-- Prints 12.
(??) null operator, it returns the expression on its left when the it's not null, otherwise it'll return the right expression.
(??=) Null-aware assignment - This operator assigns value to the variable on its left, only if that variable is currently null.
(?.) Null-Aware access This operator prevents you from crashing your app by trying to access a property or a method of an object that might be null.
For example,
String x;
print(x.toUpperCase()); // WILL GIVE AN ERROR
print(x?.toUpperCase()); // OUTPUT WILL BE NULL
(...?) Null-Aware spread operator - This operator prevents you from adding null elements using spread operator.
This is especially useful in the copyWith method which is used in flutter very often to override.
Here is an example below:
import './color.dart';
import './colors.dart';
class CoreState {
final int counter;
final Color backgroundColor;
const CoreState({
this.counter = 0,
this.backgroundColor = Colors.white,
});
CoreState copyWith({
int? counter,
Color? backgroundColor,
}) =>
CoreState(
counter: counter ?? this.counter,
backgroundColor: backgroundColor ?? this.backgroundColor,
);
#override
bool operator ==(Object other) =>
identical(this, other) ||
other is CoreState &&
runtimeType == other.runtimeType &&
counter == other.counter &&
backgroundColor == other.backgroundColor;
#override
int get hashCode => counter.hashCode ^ backgroundColor.hashCode;
#override
String toString() {
return "counter: $counter\n"
"color:$backgroundColor";
}
}
?? is a null-aware operator, the expression means that, if the value of "my_string_list_key" in the prefs instance is null then assign an empty list to myStringList.
I am trying to detect if there is a function call inside an if statement as part of condition; like following:
if (cmp(a, b)){
\\do something
}
I have found I could do this with AST matcher in following manner:
Matcher.addMatcher(ifStmt(hasCondition(callExpr().bind("call_expr")))
.bind("call_if_stmt"),&handleMatch);
But the problem is condition could have shortcuts like &&, ||; like following:
if(a != b && cmp(a,b) || c == 10){
\\ do something
}
Now this condition has binaryoperator && and ||; also have a call expression as part of it. Now how I could detect that there is a call expression inside this if statement? Definitely I don't know how many binary operator as shortcuts will be there, so I am looking for a generalize solution for this, possibly using clange AST matcher.
In the first case, if(cmp(a,b)), the CallExpr node is a direct child of the IfStmt. In the second case, it is a descendant of the IfStmt, but not a child. Instead, it is nested beneath two BinaryOperator nodes. (I found this out by looking at the AST with clang-check -ast-dump test.cpp --.) Adding a hasDescendant traversal matcher will find the more deeply nested CallExpr. Unfortunately, that alone will not find the first case. So we could use anyOf to combine it with the original matcher:
ifStmt(
hasCondition(
anyOf(
callExpr().bind("top_level_call_expr"),
hasDescendant(
callExpr().bind("nested_call_expr")
)
)
)
).bind("call_if_stmt")
If I take test.cpp to have the following code:
bool cmp(int a, int b){return a < b;}
int f(int a, int c){
int b = 42;
if( a != b && cmp(a,b) || c == 10){
return 2;
}
return c;
}
int g(int a, int c){
int b = 42;
if( cmp(a,b)) {
return 2;
}
return c;
}
then I can test this with clang-query test.cpp --:
clang-query> let m2 ifStmt( hasCondition( anyOf(callExpr().bind("top_level_call_expr"),hasDescendant(callExpr().bind("nested_call_expr"))))).bind("call_if_stmt")
clang-query> m m2
Match #1:
/path/to/test.xpp:5:7: note: "call_if_stmt" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/path/to/test.cpp:5:21: note: "nested_call_expr" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~
/path/to/test.cpp:5:7: note: "root" binds here
if( a != b && cmp(a,b) || c == 10){
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Match #2:
/path/to/test.cpp:13:7: note: "call_if_stmt" binds here
if( cmp(a,b)) {
^~~~~~~~~~~~~~~
/path/to/test.cpp:13:7: note: "root" binds here
if( cmp(a,b)) {
^~~~~~~~~~~~~~~
/path/to/test.cpp:13:11: note: "top_level_call_expr" binds here
if( cmp(a,b)) {
^~~~~~~~
2 matches.
If I have a nullable type Xyz?, I want to reference it or convert it to a non-nullable type Xyz. What is the idiomatic way of doing so in Kotlin?
For example, this code is in error:
val something: Xyz? = createPossiblyNullXyz()
something.foo() // Error: "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Xyz?"
But if I check null first it is allowed, why?
val something: Xyz? = createPossiblyNullXyz()
if (something != null) {
something.foo()
}
How do I change or treat a value as not null without requiring the if check, assuming I know for sure it is truly never null? For example, here I am retrieving a value from a map that I can guarantee exists and the result of get() is not null. But I have an error:
val map = mapOf("a" to 65,"b" to 66,"c" to 67)
val something = map.get("a")
something.toLong() // Error: "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Int?"
The method get() thinks it is possible that the item is missing and returns type Int?. Therefore, what is the best way to force the type of the value to be not nullable?
Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO. Also to clarify some really old answers written for alphas of Kotlin that are not accurate for current-day Kotlin.
First, you should read all about Null Safety in Kotlin which covers the cases thoroughly.
In Kotlin, you cannot access a nullable value without being sure it is not null (Checking for null in conditions), or asserting that it is surely not null using the !! sure operator, accessing it with a ?. Safe Call, or lastly giving something that is possibly null a default value using the ?: Elvis Operator.
For your 1st case in your question you have options depending on the intent of the code you would use one of these, and all are idiomatic but have different results:
val something: Xyz? = createPossiblyNullXyz()
// access it as non-null asserting that with a sure call
val result1 = something!!.foo()
// access it only if it is not null using safe operator,
// returning null otherwise
val result2 = something?.foo()
// access it only if it is not null using safe operator,
// otherwise a default value using the elvis operator
val result3 = something?.foo() ?: differentValue
// null check it with `if` expression and then use the value,
// similar to result3 but for more complex cases harder to do in one expression
val result4 = if (something != null) {
something.foo()
} else {
...
differentValue
}
// null check it with `if` statement doing a different action
if (something != null) {
something.foo()
} else {
someOtherAction()
}
For the "Why does it work when null checked" read the background information below on smart casts.
For your 2nd case in your question in the question with Map, if you as a developer are sure of the result never being null, use !! sure operator as an assertion:
val map = mapOf("a" to 65,"b" to 66,"c" to 67)
val something = map.get("a")!!
something.toLong() // now valid
or in another case, when the map COULD return a null but you can provide a default value, then Map itself has a getOrElse method:
val map = mapOf("a" to 65,"b" to 66,"c" to 67)
val something = map.getOrElse("z") { 0 } // provide default value in lambda
something.toLong() // now valid
Background Information:
Note: in the examples below I am using explicit types to make the behavior clear. With type inference, normally the types can be omitted for local variables and private members.
More about the !! sure operator
The !! operator asserts that the value is not null or throws an NPE. This should be used in cases where the developer is guaranteeing that the value will never be null. Think of it as an assert followed by a smart cast.
val possibleXyz: Xyz? = ...
// assert it is not null, but if it is throw an exception:
val surelyXyz: Xyz = possibleXyz!!
// same thing but access members after the assertion is made:
possibleXyz!!.foo()
read more: !! Sure Operator
More about null Checking and Smart Casts
If you protect access to a nullable type with a null check, the compiler will smart cast the value within the body of the statement to be non-nullable. There are some complicated flows where this cannot happen, but for common cases works fine.
val possibleXyz: Xyz? = ...
if (possibleXyz != null) {
// allowed to reference members:
possiblyXyz.foo()
// or also assign as non-nullable type:
val surelyXyz: Xyz = possibleXyz
}
Or if you do a is check for a non-nullable type:
if (possibleXyz is Xyz) {
// allowed to reference members:
possiblyXyz.foo()
}
And the same for 'when' expressions that also safe cast:
when (possibleXyz) {
null -> doSomething()
else -> possibleXyz.foo()
}
// or
when (possibleXyz) {
is Xyz -> possibleXyz.foo()
is Alpha -> possibleXyz.dominate()
is Fish -> possibleXyz.swim()
}
Some things do not allow the null check to smart cast for the later use of the variable. The example above uses a local variable that in no way could have mutated in the flow of the application, whether val or var this variable had no opportunity to mutate into a null. But, in other cases where the compiler cannot guarantee the flow analysis, this would be an error:
var nullableInt: Int? = ...
public fun foo() {
if (nullableInt != null) {
// Error: "Smart cast to 'kotlin.Int' is impossible, because 'nullableInt' is a mutable property that could have been changed by this time"
val nonNullableInt: Int = nullableInt
}
}
The lifecycle of the variable nullableInt is not completely visible and may be assigned from other threads, the null check cannot be smart cast into a non-nullable value. See the "Safe Calls" topic below for a workaround.
Another case that cannot be trusted by a smart cast to not mutate is a val property on an object that has a custom getter. In this case, the compiler has no visibility into what mutates the value and therefore you will get an error message:
class MyThing {
val possibleXyz: Xyz?
get() { ... }
}
// now when referencing this class...
val thing = MyThing()
if (thing.possibleXyz != null) {
// error: "Kotlin: Smart cast to 'kotlin.Int' is impossible, because 'p.x' is a property that has open or custom getter"
thing.possiblyXyz.foo()
}
read more: Checking for null in conditions
More about the ?. Safe Call operator
The safe call operator returns null if the value to the left is null, otherwise continues to evaluate the expression to the right.
val possibleXyz: Xyz? = makeMeSomethingButMaybeNullable()
// "answer" will be null if any step of the chain is null
val answer = possibleXyz?.foo()?.goo()?.boo()
Another example where you want to iterate a list but only if not null and not empty, again the safe call operator comes in handy:
val things: List? = makeMeAListOrDont()
things?.forEach {
// this loops only if not null (due to safe call) nor empty (0 items loop 0 times):
}
In one of the examples above we had a case where we did an if check but have the chance another thread mutated the value and therefore no smart cast. We can change this sample to use the safe call operator along with the let function to solve this:
var possibleXyz: Xyz? = 1
public fun foo() {
possibleXyz?.let { value ->
// only called if not null, and the value is captured by the lambda
val surelyXyz: Xyz = value
}
}
read more: Safe Calls
More about the ?: Elvis Operator
The Elvis operator allows you to provide an alternative value when an expression to the left of the operator is null:
val surelyXyz: Xyz = makeXyzOrNull() ?: DefaultXyz()
It has some creative uses as well, for example throw an exception when something is null:
val currentUser = session.user ?: throw Http401Error("Unauthorized")
or to return early from a function:
fun foo(key: String): Int {
val startingCode: String = codes.findKey(key) ?: return 0
// ...
return endingValue
}
read more: Elvis Operator
Null Operators with Related Functions
Kotlin stdlib has a series of functions that work really nicely with the operators mentioned above. For example:
// use ?.let() to change a not null value, and ?: to provide a default
val something = possibleNull?.let { it.transform() } ?: defaultSomething
// use ?.apply() to operate further on a value that is not null
possibleNull?.apply {
func1()
func2()
}
// use .takeIf or .takeUnless to turn a value null if it meets a predicate
val something = name.takeIf { it.isNotBlank() } ?: defaultName
val something = name.takeUnless { it.isBlank() } ?: defaultName
Related Topics
In Kotlin, most applications try to avoid null values, but it isn't always possible. And sometimes null makes perfect sense. Some guidelines to think about:
in some cases, it warrants different return types that include the status of the method call and the result if successful. Libraries like Result give you a success or failure result type that can also branch your code. And the Promises library for Kotlin called Kovenant does the same in the form of promises.
for collections as return types always return an empty collection instead of a null, unless you need a third state of "not present". Kotlin has helper functions such as emptyList() or emptySet() to create these empty values.
when using methods which return a nullable value for which you have a default or alternative, use the Elvis operator to provide a default value. In the case of a Map use the getOrElse() which allows a default value to be generated instead of Map method get() which returns a nullable value. Same for getOrPut()
when overriding methods from Java where Kotlin isn't sure about the nullability of the Java code, you can always drop the ? nullability from your override if you are sure what the signature and functionality should be. Therefore your overridden method is more null safe. Same for implementing Java interfaces in Kotlin, change the nullability to be what you know is valid.
look at functions that can help already, such as for String?.isNullOrEmpty() and String?.isNullOrBlank() which can operate on a nullable value safely and do what you expect. In fact, you can add your own extensions to fill in any gaps in the standard library.
assertion functions like checkNotNull() and requireNotNull() in the standard library.
helper functions like filterNotNull() which remove nulls from collections, or listOfNotNull() for returning a zero or single item list from a possibly null value.
there is a Safe (nullable) cast operator as well that allows a cast to non-nullable type return null if not possible. But I do not have a valid use case for this that isn't solved by the other methods mentioned above.
The previous answer is a hard act to follow, but here's one quick and easy way:
val something: Xyz = createPossiblyNullXyz() ?: throw RuntimeError("no it shouldn't be null")
something.foo()
If it really is never null, the exception won't happen, but if it ever is you'll see what went wrong.
I want to add that now it exists Konad library that addresses more complex situations for nullable composition. Here it follows an example usage:
val foo: Int? = 1
val bar: String? = "2"
val baz: Float? = 3.0f
fun useThem(x: Int, y: String, z: Float): Int = x + y.toInt() + z.toInt()
val result: Int? = ::useThem.curry()
.on(foo.maybe)
.on(bar.maybe)
.on(baz.maybe)
.nullable
if you want to keep it nullable, or
val result: Result<Int> = ::useThem.curry()
.on(foo.ifNull("Foo should not be null"))
.on(bar.ifNull("Bar should not be null"))
.on(baz.ifNull("Baz should not be null"))
.result
if you want to accumulate errors. See maybe section
Accepted answer contains the complete detail, here I am adding the summary
How to call functions on a variable of nullable type
val str: String? = "HELLO"
// 1. Safe call (?), makes sure you don't get NPE
val lowerCaseStr = str?.toLowerCase() // same as str == null ? null : str.toLowerCase()
// 2. non-null asserted call (!!), only use if you are sure that value is non-null
val upperCaseStr = str!!.toUpperCase() // same as str.toUpperCase() in java, NPE if str is null
How to convert nullable type variable to non-nullable type
Given that you are 100% sure that nullable variable contains non-null value
// use non-null assertion, will cause NPE if str is null
val nonNullableStr = str!! // type of nonNullableStr is String(non-nullable)
Why safe(?) or non-null(!!) assertion not required inside null check if block
if the compiler can guarantee that the variable won't change between the check and the usage then it knows that variable can't possibly be null, so you can do
if(str != null){
val upperCaseStr = str.toUpperCase() // str can't possibly be null, no need of ? or !!
}
Having a simple class as follows is considered a static warning, why?
operator 'negate' should return numeric type
class Vector {
final int x,y;
const Vector(this.x, this.y);
Vector operator +(Vector v) { // Overrides + (a + b).
return new Vector(x + v.x, y + v.y);
}
Vector operator -(Vector v) { // Overrides - (a - b).
return new Vector(x - v.x, y - v.y);
}
Vector operator negate() { // Overrides unary negation (-a).
return new Vector(-x,-y);
}
String toString() => '($x,$y)';
}
main() {
final v = new Vector(2,3);
final w = new Vector(2,2);
assert((-v).x == -2 && (-v).y == -3); // -v == (-2,-3)
}
As of 8/21/2012 the Dart Specification Section 7.1.2 Operators, considers defining negate with a possible nullary type as bad style and should report to the user a static warning.
Defining a nullary method named negate or a binary method named equals
will have the same effect as dening an operator but is considered bad
style, and will cause a static warning.
[...]
It is a static warning if the return type of the user-declared
operator []= is explicitly declared and not void. It is a static
warning if the return type of the user-declared operator equals is
explicitly declared and is not bool. It is a static warning if the
return type of the user-declared operator negate is explicitly
declared and not a numerical type.
We have an open bug for this: http://code.google.com/p/dart/issues/detail?id=3416