How can I check if argument is null, and if not use it in a function? - dart

Is there a shorter, more elegant way to do that?
var? x = null == y ? null : foo(y!);
Something like this, maybe?
int? y = null;
double? x = y?.toDouble() ?? null;
(it should be null safe as well)

No.
There is currently no operation in Dart which takes a value, checks if it is non-null, and if so, does something to it other than calling a method on the object.
What you can do, if you want to, is to introduce an extension like
extension CallWith<T> on T {
R pipeTo<R>(R Function(T) f) => f(this);
}
Then you can write:
y?.pipeTo(foo);

Related

When to use num in Dart

I am new to Dart and I can see Dart has num which is the superclass of int and double (and only those two, since it's a compile time error to subclass num to anything else).
So far I can't see any benefits of using num instead of int or double, are there any cases where num is better or even recommended? Or is it just to avoid thinking about the type of the number so the compiler will decide if the number is an int or a double for us?
One benefit for example
before Dart 2.1 :
suppose you need to define a double var like,
double x ;
if you define your x to be a double, when you assign it to its value, you have to specify it say for example 9.876.
x = 9.876;
so far so good.
Now you need to assign it a value like say 9
you can't code it like this
x = 9; //this will be error before dart 2.1
so you need to code it like
x = 9.0;
but if you define x as num
you can use
x = 9.0;
and
x = 9;
so it is a convenient way to avoid these type mismatch errors between integer and double types in dart.
both will be valid.
this was a situation before Dart 2.1 but still can help explain the concept
check this may be related
Not sure if this is useful to anyone, but I just ran into a case where I needed num in a way.
I defined a utility function like this:
T maximumByOrNull<T, K extends Comparable<K>>(Iterable<T> it, K key(T),) {
return it.isEmpty
? null
: it.reduce((a, b) => key(a).compareTo(key(b)) > 0 ? a : b);
}
And invoking it like this…
eldest = maximumByOrNull(students, (s) => s.age);
… caused trouble when age is an int, because int itself does not implement Comparable<int>.
So Dart cannot infer the type K in the invocation to maximumByOrNull.
However, num does implement Comparable<num>. And if I specified:
eldest = maximumByOrNull(students, (s) => s.age as num); // this
eldest = maximumByOrNull<Student, num>(students, (s) => s.age); // or this
the complaint went away.
Bottom line: it seems num implements Comparable when int and double do not, themselves, and sometimes this causes trouble for generic functions.
A good use case of num are extensions that work with int and double.
As an example I include the extension MinMax on List<num> that provides the getters min and max.
extension MinMax on List<num>{
/// Returns the maximum value or `null` if the list is empty.
num get max {
return (isNotEmpty)
? fold<num>(0, (prev, current) => (prev > current) ? prev : current)
: null;
}
/// Returns the minimum value or `null` if the list is empty.
num get min {
return (isNotEmpty)
? fold<num>(0, (prev, current) => (prev < current) ? prev : current)
: null;
}
}
Using the extension above one can access the min/max values without a need to create specific implementations for the classes int and double.
void main() {
final a = <int>[1,3,5];
final b = <double>[ 0.5, 0.8, -5.0];
print(a.min);
print(b.max);
}
I just ran into a use case when it is useful.
My app stores weight, which was originally defined as a double.
When using with a local database (sqlite) it works fine, since sqlite handles integer and real types.
However, when I converted my app to use Firestore database, I ran into issues with all my double fields. If a decimal value is stored everything works fine. However, when the weight happens to be a whole number, Firestore returns it as an int and suddenly type errors - int is not a subtype of type double - start to appear.
In the above scenario changing the double fields and variables to num was a quite simple solution.

In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them

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 !!
}

How to optionally pass an optional parameter?

Is there an easier (and cleaner) way to pass an optional parameter from one function to another than doing this:
void optional1({num x, num y}) {
if (?x && ?y) {
optional2(x: x, y: y);
} else if (?x) {
optional2(x: x);
} else if (?y) {
optional2(y: y);
} else {
optional2();
}
}
void optional2({num x : 1, num y : 1}) {
...
}
The one I actually want to call is:
void drawImage(canvas_OR_image_OR_video, num sx_OR_x, num sy_OR_y, [num sw_OR_width, num height_OR_sh, num dx, num dy, num dw, num dh])
At least I don't get a combinatorial explosion for positional optional parameters but I'd still like to have something simpler than lot's of if-else.
I have some code that uses the solution proposed in the first answer (propagating default values of named optional parameters, but I lose the ability to check whether or not the value was provided by the initial caller).
I've been burned by this corner of Dart several times. My current guidelines, which I encourage anyone to adopt are:
Do not use default values. Instead, use the implicit default of null and check for that in the body of the function. Document what value will be used if null is passed.
Do not use the ? argument test operator. Instead, just test for null.
This makes not passing an argument and explicitly passing null exactly equivalent, which means you can always forward by explicitly passing an argument.
So the above would become:
void optional1({num x, num y}) {
optional2(x: x, y: y);
}
/// [x] and [y] default to `1` if not passed.
void optional2({num x, num y}) {
if (x == null) x = 1;
if (y == null) y = 1;
...
}
I think this pattern is cleaner and easier to maintain that using default values and avoids the nasty combinatorial explosion when you need forward. It also avoids duplicating default values when you override a method or implement an interface with optional parameters.
However, there is one corner of the Dart world where this doesn't work: the DOM. The ? operator was designed specifically to address the fact that there are some JavaScript DOM methods where passing null is different from passing undefined (i.e. not passing anything).
If you're trying to forward to a DOM method in Dart that internally uses ? then you will have to deal with the combinatorial explosion. I personally hope we can just fix those APIs.
But if you're just writing your own Dart code, I really encourage you to avoid default values and ? entirely. Your users will thank you for it.
Would positional paremeters be an option four your case?
void optional([num x = 1, num y = 1]) {
}
Since you call optional2 with default parameters anyway, this seems like a good replacement without knowing, what the purpose of the function is

Does F# Seq.sort return a copy of the input sequence?

Here is some unexpected (by me) behaviour in F#. I have a simple class that sorts a sequence :
type MyQueue<'a when 'a : comparison> ( values : 'a[] ) =
let vals =
Seq.sort values
member this.First = Seq.nth 0 vals
override this.ToString() =
Seq.fold ( fun s a -> s + a.ToString() + ";" ) "" vals
I have written a slightly contrived unit test (in C#) to test this:
private class TestObject : IComparable
{
public TestObject( double Value )
{
this.Value = Value;
}
public void Update(double NewValue)
{
this.Value = NewValue;
}
public double Value { get ; private set; }
public int CompareTo(object Comparable)
{
return this.Value.CompareTo( (Comparable as TestObject).Value );
}
public override string ToString ()
{
return Value.ToString();
}
}
[Test]
public void TestUpdate_OK()
{
var nums = new double[]{7,4,3,12,11,3,8};
var values = nums.Select( n => new TestObject(n) ).ToArray();
var q = new MyQueue<TestObject>( values );
Console.WriteLine ( q.ToString() );
// update one of the values in the collection - should not re-sort the collection
values[3].Update( 2.0 );
Console.WriteLine ( q.ToString() );
Assert.AreEqual( q.First.Value, 3.0 );
}
the Seq.sort does sort the sequence, and the first output is correct :
3;3;4;7;8;11;12;
However, updating the test (reference type) object causes the sequence to be re-sorted :
2;3;3;4;7;8;11;
I expected that the vals in the MyQueue object would now be unsorted, since the value in the reference object has changed, but the Seq.sort appears to have been performed again. I don't understand, I thought the object of functional programming was to avoid side effects. Why do I get this behaviour?
The cause of this is the statement let vals = Seq.sort values is not actually sorting the values until some code consumes the vals variable i.e what your Seq.fold does in toString method, it consumes the vals sequence and at that time the sorting happens and whatever values are there in the values array at that time, those values are sorted, so basically the sorting is happening at the time when you call toString method.
Also, I won't call it FP :) as you are basically doing OOPs by creating type with private state and that state is accessed by type members.
Your problem is related to how sequences works and not in general applicable to FP.
Does F# Seq.sort return a copy of the input sequence?
Yes. What else could it do – to change the order of a set of value types you need to copy (true in all .NET languages).
(This includes LINQ operators in C# and VB: the lazy aspect is that the copy is only made when the first copied element is needed, and at that point a complete new collection is created.)
You can actually check this directly in the sourcecode for f# here but in short what it does is call Seq.toArray, sort the array in place and return that array back as the sequence.

Is it possible to use the pipeline operator to call a method on a returned object?

Is it possible to call a method on a returned object using the pipeline infix operator?
Example, I have a .Net class (Class1) with a method (Method1). I can currently code it like this:
let myclass = new Class1()
let val = myclass.Method1()
I know I could also code it as such
let val = new Class1().Method1()
However I would like to do be able to pipeline it (I am using the ? below where I don't know what to do):
new Class1()
|> ?.Method1()
Furthermore, say I had a method which returns an object, and I want to only reference it if that method didn't return null (otherwise bail?)
new Class1()
|> ?.Method1()
|> ?? ?.Method2()
Or to make it clearer, here is some C# code:
public void foo()
{
var myclass = new Class1();
Class2 class2 = myclass.Method1();
if (class2 == null)
{
return;
}
class2.Method2();
}
You can define something similar to your (??) operator fairly easily (but operators can't start with a question mark):
let (~??) f x =
if (x <> null) then
f x
Unfortunately, your pipelined code will need to be a bit more verbose (also, note that you can drop the new keyword for calling constructors):
Class1()
|> fun x -> x.Method1()
Putting it all together:
Class1()
|> fun x -> x.Method1()
|> ~?? (fun x -> x.Method2())
Using a custom operator as 'kvb' suggests is definitely an option. Another approach that you may find interesting in this case is to define your own 'computation expression' that automatically performs the check for null value at every point you specify. The code that uses it would look like this:
open System.Windows.Forms
// this function returns (0) null, or (1) btn whose parent is
// null or (2) button whose parent is not null
let test = function
| 1 -> new Button(Text = "Button")
| 2 -> new Button(Text = "Button", Parent = new Button(Text = "Parent"))
| _ -> null
let res =
safe { let! btn = test(2) // specify number here for testing
// if btn = null, this part of the computation will not execute
// and the computation expression immediately returns null
printfn "Text = %s" btn.Text
let! parent = btn.Parent // safe access to parent
printfn "Parent = %s" parent.Text // will never be null!
return parent }
As you can see, when you want to use a value that can potentially be 'null', you use let! inside the computation expression. The computation expression can be defined so that it immediately returns null if the value is null and runs the rest of the computation otherwise. Here is the code:
type SafeNullBuilder() =
member x.Return(v) = v
member x.Bind(v, f) =
if v = null then null else f(v)
let safe = new SafeNullBuilder()
BTW: If you want to learn more about this, it is very similar to 'Maybe' monad in Haskell (or computation working with F# option type).

Resources