Why can I declare a variable without writing optional mark? - ios

First of all, I believe my question is different with those questions about "what is optional in swift". Because I am asking why I can do this, not what is this.
I am new to swift. When I learn this fabulous language tonight, I got a problem that I never saw this mark-"?" in a programming language. And I searched it for a while. I know what optional binding is now.
But now I got a new question.
When I want to declare a variable that is not optional. I can write this syntax:
var friend: String
But I can't write:
var friend: String = nil
To declare a variable that is nil I can only use optional:
var friend: String? = nil
Let's see the first piece of code. When the new variable friend just be declared, its value is nil, right? Because I didn't assign any value to it. But according to the definition of optional, like the second and the third pieces of code, we can't assign nil to non-optional variables.
So my question is why I can declare a variable without optional mark but has no initial value. This question may be simple, but I really don't know why it happens.
Thanks in advance!

Swift allows you to declare a non-optional variable or constant without initializing it in the declaration, but you will have to assign it a value before using it. The value of the variable or constant is not nil (non-optionals can never be nil)--it simply has no defined value. Basically you are saying you will give it a value later, possibly based on the result of a computation or an if statement.
Swift will give you a compile-time error if you try to use a non-optional variable or constant without first assigning a value to it.

The first value you set is an uninitialized variable with the type of string.
A very common pattern in programming is to have an operation that might or might not return a value. In some languages, like javascript, when coming across a null value our program continues to operate just fine as long as our program is not dependent on that value to continue. In other languages, like java for example, a null value can cause a NullPointerException and crash our program.
Swift's solution to this problem is optionals. By default if we define a variable without a value, the compiler will complain. So, in order to declare a value that may or may not have a value at runtime, we need to add a ? which is known as “wrapping our values in an optional”. This is because we are indeed literally wrapping our value in Swifts optional type, thus giving it value. To get a better picture as to whats going on, we can look at how Swifts Optional enum.
enum Optional<T> {
case None // has no value
case Some(T) // has some value
}

Related

Dart: dynamic vs nullable Object

Is there any difference between dynamic and Object? in dart?
This question may sound a duplicate of this What is the difference between dynamic and Object in dart?. However, I think it is not. I am not talking about semantic difference or any warnings thrown by the dart analyzer, or anything from a coder's perspective. I want to know is there a real difference between both under the hood.
I can assign any data value to both.
When I run the following:
Object? a;
dynamic b;
print(a.runtimeType);
print(b.runtimeType);
I get:
Null
Null
I know dynamic is a keyword, while Object? is a Object class. But does dynamic infer to Object?.
I'm new to Dart lang. So, please enlighten me.
Yes, there is a difference.
The types dynamic and Object? are equivalent wrt. subtyping. Both are "top types" which means that every type is a subtype of them both, even each other.
So, for subtyping there is no difference.
The difference is entirely in what you can do with an expression that has one of those types.
If an expression has type Object?, then the only methods you can call on it are the methods of Object and Null. The only types you can assign the expression to are top types.
If the expression has type dynamic, it is as if the static type system has been turned off.
You are allowed to call any method (like dynamicExpression.arglebargle()) without any warning. If the method isn't there at runtime, it'll throw an error.
And you can assign the value to any type. If the value turns out to not have that type at runtime, it'll throw an error. (This is usually called "implicit downcast" because it works as if an is ExpectedType was added to the expression by the compiler.)
Also, because a dynamic expression is treated as having any method, you cannot call extension methods on it.
It's like dynamic is a type alias for Object? with the extra effect of turning off static type checking.
When you declare a variable as an Object?, during compile-time the compiler knows that type of the variable is Object? and it remains Object? forever. You can assign any type to this variable because every other type either extends the Object or null.
When you declare a variable as a dynamic, during compile-time the compiler does not know the type of the variable and just ignores it. The compiler will check the type only during run-time and will infer the type according to the value you assigned.
dynamic contains Exception. Object can only represent known data types and Null, (excluding Exception)

Why can we not change the variable value if initialises at the time of declaration?

I am learning dart and this behavior of dart is annoying me
var a=10;
a="John"; //it generates an error, because a has integer data-type and we can't assign
//string or the value of any other data type because we have assigned an
//integer value
but at the same time, dart allows us to write
var a;
a=10;
a="John";
print (a) //it displays John
it means that we can't assign the value of any other data type when a variable initializes at the time of declaration but we can assign the value of any other data type if the variable declares in one line and initializes at the second line. Why does dart work in this way?
The var keyword is used to let Dart automatically assign a type for the variable based on the value you are using to initialize the variable.
If you use var without providing any initial value, the type of your variable are automatically being assign to dynamic which allows any type of object to be assigned to the variable. But it also means your program are much less type safe since the analyzer can no longer help you with what type the variable are going to return and what types are allowed when setting the variable.
So in your first example, a is being assigned the type int since you provide 10 as the initial value. It is therefore a compile error when you are trying to set a String as the new value of your int variable.
In your second example, a is going to be dynamic since you are not providing any initial value. So it is not a problem to first give it 10 and later 'John' since dynamic allow us to use any type. But that also means that when we try to use a in our program, Dart cannot make any guarantees about what type of object you are going to get so errors will first be identified at runtime.
That's because var means dart will assign the type of variable itself.
In first case, the dart assigned variable a as int type because it was given a value during initialisation.
But in second case, the dart assigned variable a as dynamic and that's why you can assign it either a string or int later on.

Why does an unitialized typed variable in Dart not implement the type's interface?

I started learning Dart and was reading a critique of some of it's design choices here: https://medium.com/#krossovochkin/dart-language-bad-design-choices-6e35987dc693
The last point that is made is about the poor type system and the author cited this code snippet which prints null:
void main() {
String s = null;
if (s is String) {
print("string");
} else if (s is Null) {
print("null");
} else {
print ("none");
}
}
The is keyword was new to me but "The Dart Programming Language" by Gilad pointed out that is checks the interface implemented by an object's class and not the actual class of an object.
However this didn't help me much because I would think that the variable s is an instance of String and therefore implements String, but the evidence is to the contrary.
I get that the class is not required when defining objects/variables in Dart, and thus I started to wonder if putting the class in the definition just serves as sugar and has little functional purpose. But instead the class of an object/variable is completely determined by its value, and since the default value for all variables in Dart is null, then it would make sense that String is not implemented, but Null is. Is this the case? Am I way of base? Maybe someone could help me wrap my head around this.
The reason is that is checks the interface of the current object itself and not the reference to this object. So yes, s can point to a String object but also allowed to point to null which are a instance of Null: https://api.dart.dev/stable/2.7.2/dart-core/Null-class.html
Since Null does not implement the String interface, this will return false (null is String). This is also mentioned in the article.
The problem the article are trying to focus on are more the fact you are allowed to set the String variable to null value but Null does not implement String.
Well, in the future, this problem are going to be fixed with non-nullable types which are in development right now. When this is implemented you can actually define variables where you can be sure the value will never be null.
So I continued my Dart reading and I came to a better understanding, and that is that Dart is truly optionally typed and that means 2 things:
Type are syntactically optional.
Type has no impact on runtime semantics.
Therefore the actual type annotation of a variable in Dart only serves documentation purposes and it cannot be assumed that a type annotation is true. The actual type of a variable is wholly determined by the value stored at this variable, and in this case it is null.
In truth the variable that I defined in my example is not a String variable or an implementer of the String interface. It is just annotated that it may be/should be/most likely is a string.

swift: forced type modifier "!" - why is (was) it used in UIKit API (now anachronistic)

Edit: The intent of this question was to understand the use of the implicit optional operator "!" in the early UIKit API updates, specifically if a function was declared as returning a type expected to be non optional, why use optional at all, and if it was optional, why not use the optional "?" operator. The semantics of "!" were always clear though.
As time later showed, it was a matter of Apple auditing the API to make the optionality more precise, using ? for truly optional types, and using non optional types when they were in fact non optional. This was a hold-over of the original Objective-C signatures which were often ambiguous.
The swift documentation explains the purpose of the ! unboxing operator on optional types,
var optionalString : String? = "optional"
var regularString: String = optionalString!
but they have used it on type definitions themselves (String!), without an explicit explanation that I can find.
Example:
func takesBang(value:String!) -> String {
if !value {
return "nil value, without the safe syntax"
}
return "This works"
}
var unsafe:String!
takesBang(unsafe) // yields "nil value, without the safe syntax"
The String! type does not force an unboxing of the optional type, but only seems to remove the need for optional syntax (?.). Apple uses this in their own examples, but it seems to only negate the optional safety (pointer) mechanisms.
Can anybody explain the purpose / motivation? This seems generally unsafe as the caller won't have to check or at least think about their value.
The Language Reference states that both, ? as also !, when used on var declarations are only syntactic sugar (meaning they are replaced by the compiler during parsing). They map to Optional<T> (?) and ImplicitlyUnwrappedOptional<T> (!) respectively.
While you have to use the if let maybeNil = someVar? { ... } syntax for variables of type Optional<T>, you don't have to do so with the implicitly unwrapped optionals (as the name already implies). As the poster in https://stackoverflow.com/a/24071003/1599345 already mentioned, implicitly unwrapped optionals are meant to be used with legacy Objective-C APIs, since those don't provide enough information for Swift.
So as a short recap:
var foo : SomeType? // should be read as var foo : Optional<SomeType>
var bar : SomeType! // should be read as var bar : ImplicitlyUnwrappedOptional<SomeType>
The usage of ? and ! when working with actual values in variables is actually a mapping that can be read in this way, analogous to the declarations above:
foo?.somemethod() // if let maybeFoo = foo { maybeFoo.somemethod() }
foo!.somemethod() /* # Yeah I know for sure, that this is NOT nil ever ever… just call `somemethod` and kill me at runtime if it doesn't work out.
It is generally unsafe, but is used for imported Objective-C APIs, which are already unsafe in that way and don't expose enough information to decide whether they should be Optional or non-Optional.
In non-imported APIs, I wouldn't expect it to be used much.
It turns out that this was just an oversight on Apple's part, they have been auditing classes and updating the return types since Beta 5.
From the Beta 6 release notes:
"A large number of Foundation APIs have been audited for optional
conformance, removing a significant number of implicitly unwrapped
optionals from their interfaces. This clarifies the nullability of
their properties and arguments / return values of their methods. This
is an ongoing effort since beta 5."

In Dart, do I annotate a function return value with dynamic or Object if I don't know it's type?

If I have a function that returns a value of an unknown type, do I use dynamic, representing any object, or Object, which is the ancestor of all other types?
The style guide discusses this question for parameters, but not for return values.
How should I annotate the return value and why?
Dart engineer Bob Nystrom writes:
Return types are an interesting twist on this problem. With parameter types, the guidelines are pretty straightforward:
If you use Object as a parameter type, you're saying "my method will safely accept any object and only use it for stuff like toString() that all objects support".
If you use dynamic (or nothing) as a parameter type, you're saying "Dart's type system can't easily express the type that I accept here" or "I didn't bother to annotate".
It's tricky to flip (1) around. For a return type, I guess Object would say "You better not call anything except toString() or other stuff all objects support before doing a type test yourself", where dynamic would I think mean "we can't easily annotate this so you and I better just know what we're doing".
The user would have to "cast" it to a specific type that they expect to see to avoid compiler warning and get an error earlier in checked mode.
For what it's worth, in many cases you wouldn't have to cast even if you return Object. Dart allows implicit downcasting when you initialize a local variable with a type annotation. So you can do:
Object foo() => 123;
main() {
int x = foo(); // Implicit downcast. No type warning.
}
I think in this case, I would probably do dynamic, though. I think that conveys "I don't know what type this returns, but you should" better than Object.

Resources