I'm a student who's new in Swift.
While I'm studying about the Optional, I got curious about the keyword nil, so I tried some experiment with it. I'm using Swift version 5.5.
As you can see in the image below, if I assign nil to a optional variable (which I named 'name') and then print it with print(name) and print("(name)") (string interpolation), I got nil on the console in both cases. (Line 5, 9)
But when I print nil without the optional variable, which I printed it with print(nil) and print("(nil)"), I got an error on both cases. (Line 7, 11)
I expected them all to print out nil but they didn't.
I really want to know the difference between those cases.
The issue is that nil isn't just one single value, like null in Java/C#.
nil is syntactic sugar for Optional<Wrapped>.none. There's one different kind of value for every possible Wrapped. E.g. there is Optional<Int>.none and Optional<String>.none, and you can't assign from one to the other, because they're unrelated types.
When you use nil, the value of the Wrapped generic parameter is inferred from context, much like when you do:
let a = Optional<Int>.none // most explicit
let b: Optional<Int> = Optional.none // Generic Wrapped param inferred from the type annotation
let c: Optional<Int> = nil // Same inference
print takes an Any, so that doesn't give any relevant contextual type information. When you say print(nil), it's not clear what the typed of Wrapped should be. You might not care (because Optional<Int>.none and Optional<String>.none both print "nil"), but the type system can't leave it open ended, so it's a type error.
If you added contextual type information, it works, such as using a variable of a known type, or using a coercion:
print(nil as String?)
Interesting question actually. If you look at the Swift documentation:
Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”.
So think of it as nil is the absence of some value. As an example if you have:
var name: String?
name can either be a string value, or the absence of a string value.
So it makes no sense to try and print nil explicitly since you already know that it's the absence of a value, however, it makes sense to print name to check if it has a string value and in that case what it is, or if it has no string value.
The error message in XCode tells you exactly what happens: nil is not compatible with expected argument type Any - the print function expects a non-nil argument, as does the string interpolation with \(),
Related
So I've been following along to a fireship course on dart and I got the error: "Null check operator used on a null value". Was just wondering why? Here is the code:
String? answer;
String result = answer!;
That's working exactly as intended.
The String? answer; declaration introduces a nullable variable with a current value of null.
The answer! expression reads that value, checks whether it's null, throws if the value is null, or evaluates to the non-null value if it isn't null.
Since the value is indeed null, that operation throws the error you see.
The ! is the "null check operator". It's used on the value null. The error message is actually quite precise.
To avoid that, make sure the answer variable has a non-null value when you use the ! operator on it. (Often you won't need the ! for local variables because assigning a non-null value to the variable also promotes the variable's type to non-nullable, but there are cases where the compiler can't see that assignment, for example if it happens in a callback function.)
I'm using this repository to familiarize myself with Amazon's Cognito user system. In the file lib/screens/signup_screen.dart, starting at line 27 there is this piece of code:
TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(labelText: "Email"),
controller: _emailController,
validator: (value) =>
!validateEmail(value) ? "Email is Invalid" : null,
),
However, since we have null safety in Dart since version 2.x, this piece of code fails with the error message: The argument type 'String?' can't be assigned to the parameter type 'String'.
What I got from that is that value may not be equal to null and the code cannot guarantee that as it is. Please correct me if I'm wrong and I'm also hoping someone can explain to me why the code cannot guarantee null safety here. If the textfield is empty, value should be equal to "" instead of null.
Anyhow, I decided to use the ternary operator to fix this issue:
!validateEmail(value == null ? "" : value) ? ...
Which the IDE suggested I correct to:
!validateEmail(value ?? "") ? ...
Dart also suggested to insert a null check as another alternative:
!validateEmail(value!) ? ....
Up till now, I have just been using these fixes as a workaround to produce code fast without trying to understand what's actually going on.
So what's the difference between these methods? Does the ?? in the second method have an integrated == null check and is it exactly the same as writing value == null ? "" : value?
Also, what does the nullcheck value! do? Yes, it checks if value is equal to null, but what does it do for me when value is in fact equal to null?
The ?? is a null-aware operator , 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.
Which is the same as doing a ternary operator but more readable.
The bang operator ! casts aways the nullability of the variable, meaning YOU explicitly say that the value CAN'T be null.
Of course, like any cast, using ! comes with a loss of static safety.
The cast must be checked at runtime to preserve soundness and it may
fail and throw an exception.
For further reading check out the documentation.
You can start learning more about sound null safety in Dart here: Understanding Null Safety
The null assertion value! is equal to casting to a non-nullable type: value as String. It raises an exception if value is null.
The conditional ?? operator acts as you expect: value ?? "" is a shorthand equivalent for value != null ? value : ""
What I got from that is that value may not be equal to null and the code cannot guarantee that as it is.
value might be null, but validateEmail requires that its argument is not null.
can explain to me why the code cannot guarantee null safety here. If the textfield is empty, value should be equal to "" instead of null.
Because that's what TextFormField's constructor specifies. Its validator parameter is declared to be a FormFieldValidator<String>?, and FormFieldValidator<T> is defined to be a String? Function(T? value). In other words, the validator callback is declared to be a function that must accept null as an argument. The compiler does not have semantic knowledge to know whether TextFormField will actually invoke that callback with null instead of an empty string in practice.
So what's the difference between these methods? Does the ?? in the second method have an integrated == null check and is it exactly the same as writing value == null ? "" : value?
?? is one of Dart's null-aware operators; it automatically checks for null for you. As stated in the Dart Language Tour:
expr1 ?? expr2
If expr1 is non-null, returns its value; otherwise, evaluates and returns the value of expr2.
So yes, it is equivalent to expr1 == null ? expr2 : expr1 (except that ?? would evaluate expr1 only once, which matters if evaluation has side effects). You should prefer ?? anyway because it better conveys intent.
Also, what does the nullcheck value! do? Yes, it checks if value is equal to null, but what does it do for me when value is in fact equal to null?
value! will throw an exception (specifically a TypeError) if value turns out to be null at runtime. Do not use ! unless you can logically guarantee that value will not be null.
I'm reading "Programming in Lua" book and I don't understand exercise 2.1:
What is the value of the expression
type(nil)==nil?
(You can use Lua to check your answer.) Can you explain this result?"
When I execute this code I get "false" as result. I could not explain this result, from my point of view correct result should be "true". I tried
type(some_undeclared_variable)==nil
and it also gives me "false".
The function type() always returns a string, the value of type(nil) is the string "nil", which is not the same as nil, they have different type.
I'm using C++ Builder XE6. I'm getting a UnicodeString as a parameter and I wish to check if the string is set to NULL, and not an empty string.
I've tried to do some simple compares to see if the param is null, but seem to be failing. I'm using the == operator which doesn't seem to be working, which makes me think it is overloaded.
I've tried:
if (searchString == NULL)
In the debugger view, it shows the value of { NULL } in the local variables. If I add the variable to the watch list, then it shows it has a property of "Data" which is NULL.
Any ideas on how I can properly do the compare?
There is no such thing as a NULL value for a UnicodeString. A string is a series of characters, but NULL is a pointer (well - actually it is a macro that evaluates to an int, 0, but it is supposed to be used to indicate null pointers if your compiler doesn't support nullptr).
Internally, the data member of UnicodeString is NULL when the string is empty, and non-NULL when the string has at least 1 character.
To check if the string is empty, use the IsEmpty() method, which checks if the data member is NULL or not. There is only one empty state; there is no distinction between "empty" and "null" like some languages have.
The value you see in the debugger is the internal data member of UnicodeString, it is not a part of UnicodeString's interface. When you see NULL in the debugger, you should treat it as being an empty string.
This question already has answers here:
What is an optional value in Swift?
(15 answers)
Closed 8 years ago.
In Swift programming I found some question marks with objects.
var window: UIWindow?
Can anybody explain the use of it?
You can use if and let together to work with values that might be
missing. These values are represented as optionals. An optional
value either contains a value or contains nil to indicate that the
value is missing. Write a question mark (?) after the type of a value
to mark the value as optional.
If the optional value is nil, the conditional is false and the code in
braces is skipped. Otherwise, the optional value is unwrapped and
assigned to the constant after let, which makes the unwrapped value
available inside the block of code.
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/pk/jEUH0.l
For Example:
var optionalString: String? = "Hello"
optionalString == nil
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
In this code, the output would be Hello! John Appleseed. And if we set the value of optionalName as nil. The if conditional result would be false and code inside that if would get skipped.
Question marks after a type refer to Optionals, a way in Swift which lets you indicate the possibility that a value might be absent for any type at all, without the need for special constants.
It's used in the same situations you'd explicitly return nil in Objective-C, when there is no object to be returned, or for values that are not objects, constants such as NSNotFound. Optionals provide a consistent way of achieving this across all data types.
From the Apple provided iBook
You use optionals in situations where a value may be absent. An
optional says:
There is a value, and it equals x
or
There isn’t a value at all
Here’s an example. Swift’s String type has a method called toInt,
which tries to convert a String value into an Int value. However, not
every string can be converted into an integer. The string "123" can be
converted into the numeric value 123, but the string "hello, world"
does not have an obvious numeric value to convert to.
let possibleNumber = "123"
let convertedNumber = possibleNumber.toInt()
// convertedNumber is inferred to be of type "Int?", or "optional Int"
Because the toInt method might fail, it returns an optional Int,
rather than an Int. An optional Int is written as Int?, not Int. The
question mark indicates that the value it contains is optional,
meaning that it might contain some Int value, or it might contain no
value at all. (It can’t contain anything else, such as a Bool value or
a String value. It’s either an Int, or it’s nothing at all.)
There is a whole section on the language reference iBook on Optionals, and they are mentioned several times throughout the book. You should have a thorough look at it, since it's a fundamental concept of Swift programming, and one that is not prevalent in many other languages.
the optional Value of the type .
For Ex :
the optional version of the type casting operator : as? ,mean as use for the type casting with might be optional to cast .