Why do we need the keywords "let" and "var" at all ?

First, forgive me if my questions are completely off base. I've only recently started using Swift. I searched for similar questions without finding anything, but me search skills in Apple's forums have let me down many times in the past. If this topic has been discussed before, I'm happy just to have a link in reply.



The Swift compiler can always tell when a variable is being defined because there is either an immediate assignment from which type can be inferred, or there is an explicit type provided after a ":". The presence of an assignment or a colon following a name not previously seen unambiguously indicates creation of a variable or possibly a constant.


Why do we need the keyword "var" at all. I must be missing something obvious, but under what situation does the keyword "var" add any information the compiler did not already have or could infer?


For local variables, I'm fairly confident that "var" and "let" add no information the compiler doesn't already have. Xcode tells me when a variable is not mutated within scope and suggests I change the declaration to "let". If I could omit the "var" keyword, the compiler would be free to identify unmutated values and treat them as constants all on its own. IN other words, if Xcode can tell me I'm doing it wrong, then Xcode could have done it for me.


For class properties and globals, I can see that "let" differentiates between constants and variables. Why not just assume each global and each property is "var" unless I specify "let". (And I'm not sure why "let" is a better keyword than "const" in this context)


In summary, why can't we omit "var" in every case and use "let" exclusively for constants that have a scope indeterminate to the compiler? As far as I can tell, right now, only globals (which should be discouraged) and immutable properties require "let" to give the compiler information it didn't already have.


Again, I apologize if I'm way off. I can't help thinking I'm missing something obvious. I have used LLVM extensively to build "compilers", and I've looked at the Swift grammar, and I just don't see why we "need" "var".

Accepted Reply

Interesting question. The short answer is "human factors" and "hard cases".


You're right: compilers have a precise knowledge about what the codebase it can see is doing and (at least in a language like Swift, though not so much in a language like C) what is its expressed semantics. For a local variable, the compiler can know with precision whether or not a value is mutated, so let vs var is not important to the compiler.


The longer answer is that "humans are important", and let vs var is an expression of intention. The compiler can reason about whether something is mutated or not by looking at whether it is assigned to or not. Humans prefer to know up front whether or not something is mutable without examining all uses of that value. The let and var keywords do a great job of expressing this intention up front for humans, and Swift optimizes for readability over writability in a number of cases.


In more complex cases (e.g. public global variables, public instance variables, etc) let vs var is an important part of the API contract that indicates whether external users are allowed to mutate something. This hinges on access control and a number of other things that the compiler cannot infer, and here let vs var really shine: human intention is all we have, because the compiler cannot decide beyond that what was meant.


-Chris

Replies

Put simply, one is mutable, the other is immutable. How would the compiler know

which you mean otherwise?

Interesting question. The short answer is "human factors" and "hard cases".


You're right: compilers have a precise knowledge about what the codebase it can see is doing and (at least in a language like Swift, though not so much in a language like C) what is its expressed semantics. For a local variable, the compiler can know with precision whether or not a value is mutated, so let vs var is not important to the compiler.


The longer answer is that "humans are important", and let vs var is an expression of intention. The compiler can reason about whether something is mutated or not by looking at whether it is assigned to or not. Humans prefer to know up front whether or not something is mutable without examining all uses of that value. The let and var keywords do a great job of expressing this intention up front for humans, and Swift optimizes for readability over writability in a number of cases.


In more complex cases (e.g. public global variables, public instance variables, etc) let vs var is an important part of the API contract that indicates whether external users are allowed to mutate something. This hinges on access control and a number of other things that the compiler cannot infer, and here let vs var really shine: human intention is all we have, because the compiler cannot decide beyond that what was meant.


-Chris

As far as the necessity to declare local variables, there's one important reason to do so: typos. "The presence of an assignment or a colon following a name not previously seen" may be a typo or an error.


Scripting languages which follow the "an assignment to a previously unused variable name is an implicit and automatic declaration of that variable" have a tendency to create frustration and debugging sessions when developers (through typos and other accidents) manage to get their variable names wrong. And since someone could reasonably go through and create an entire sequence of assign-only variables for a section of code, the compiler really doesn't have any grounds to complain about the accidentally misspecified variable names.


line1 = 1

line2 = 2

line3 = line1 + line2

line4 = line3

linel = line4 + 4

line5 = line3 - line4

line6 = line1 + line4

What value does the programmer expect to see in line6 and how many variables/constants did they intend to create?


If the language doesn't require explicit declarations of variables, linel is a perfectly valid new variable. If the language does require explicit declarations of variables, it's an error. Replace "linel" (an L at the end) and "line1" (a 1 at the end) with any number of misspelled word pairs, transposed letter pairs, or whatever else you'd like, that all look the same to a compiler.

Explicit statement of var can make the code more readable,代码可读性很重要的啊!