I read the Zephir's documentation (https://docs.zephir-lang.com/0.12/en/types) and I'm not sure I understand the difference between var and let in Zephir. My first thought was that maybe var only declares a variable and if you want to assign it to something, you have to use let. But then I saw the following lines in the documentation:
var a = false, b = true;
var number = 5.0, b = 0.014;
and I'm quite confused now.
Per the docs:
Variables are, by default, immutable. This means that Zephir expects
that most variables will stay unchanged. Variables that maintain their
initial value can be optimized down by the compiler to static
constants. When the variable value needs to be changed, the keyword
let must be used.
In other words, your assumption seems right. The reason the sample you posted uses var is because those are initial assignments as opposed to reassignments. Immutable, in that context, means that Zephir expects variables to maintain their original values.
Related
I am trying to figure out difference between Objective-C and Swift constant. I just read a tutorial document
//Objective-C
const int number = 0;
//Swift
let number = 0
"A const is a variable initialized at compile time with a value or an expression that must be resolved at compilation time.
An immutable created with let is a constant determined at runtime. You can initialize it with a static or a dynamic expression. This allows a declaration such as:
let higherNumber = number + 5
Note that you can only assign its value once."
Can someone explain these phrases and deep little dive into to explain why let constant determined at runtime ? I was thinking let is constant and never change.
Let means once assigned the value can’t be changed. The compiler will enforce that. An expression like “let now=Date()” can’t be determined at compile time but at compile time you can disallow reassigning to “now”.. “let pi = 3.141” can be determined at compile time, enabling optimisations and that is like C’s const
Note for reference types (classes) let means the assigned object will continue to be the same object, it doesn’t mean the object itself can’t or doesn’t change.
The description comes from the swift office document
Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables.
I don't fully understand the store references part. Does it means It creates some sort of "Pointer" to a variable? If the value changed the "de-referenced pointer" also changed to the new value. I think Swift has no pointer concept. I borrowed it to express my understandings.
Would be very nice that someone can provide a simple code lines to explain how the closure stores reference to the constants/variables.
Does it means It creates some sort of "Pointer" to a variable? If the
value changed the "de-referenced pointer" also changed to the new
value.
Yes.
I think Swift has no pointer concept.
It most certainly does, in the (implicit) form of reference types (classes), and the (explicit) form of UnsafePointer
Here's an example of a variable being captured in a closure. This all happens to be single threaded, but you could have this closure be dispatched by grand central dispatch. x is captured so that it exists for the entire life of the closure, even if the closure exists after x's declaring scope (f()) exits.
func f() {
var x = 0 //captured variable
_ = {
x = 5 //captures x from parent scope, and modifies it
}()
print(x) //prints 5, as x was modified by the closure
}
f()
I wrote another answer that explains the relationships between functions, closures, and other terms. It's worth reading, IMO.
I'm new to Swift and iOS coding and have been working on writing my first app. While my programming background is pretty significant, I come from a Python and C# background where pretty much anything can be None or null and it's up to the user to check at runtime for a null. I'm finding this whole concept of "nullable vs. non-nullable types" or "optional types" in Swift to be confusing.
I understand that the core concept is that a variable declared as a type like myObject cannot be set to nil. However, if I define it as type myObject? then the value can be set to nil.
The problem is that, when I look at my code designs, it feels like everything will have to be "nullable" in my code. It feels like this either means I'm not thinking correctly with how my code should run, or that I'm missing some crucial piece of understanding.
Let's take the simplest example of something I am confused about. Suppose I have two classes - one that stores and manages some sort of data, and another that provides access to that data. (An example of this might be something like a database connection, or a file handle, or something similar.) Let's call the class containing data myData and the class that works with that data myObject.
myObject will need a class-level reference to myData because many of its methods depend on a local reference to the class. So, the first thing the constructor does is to generate a data connection and then store it in the local variable dataConnection. The variable needs to be defined at the class level so other methods can access it, but it will be assigned to in the constructor. Failure to obtain the connection will result in some sort of exception that will interfere with the very creation of the class.
I know that Swift has two ways to define a variable: var and let, with let being analogous to some languages' const directive. Since the data connection will persist throughout the entire life of the class, let seems an obvious choice. However, I do not know how to define a class-level variable via let which will be assigned at runtime. Therefore, I use something like
var dataConnection: myData?
in the class outside any functions.
But now I have to deal with the nullable data type, and do explicit unwrapping every time I use it anywhere. It is frustrating to say the least and quite confusing.
func dealWithData() {
self.dataConnection.someFunctionToGetData() <- results in an unwrapping error.
self.dataConnection!.someFunctionToGetData() <- works.
let someOtherObjectUsingData: otherObject = self.getOtherObject() <- may result in error unless type includes ?
someOtherObjectUsingData.someMethod(self.dataConnection) <- unwrap error if type included ?
var myData = self.dataConnection!
someOtherObjectUsingData.someMethod(myData) <- works
}
func somethingNeedingDataObject(dataObject: myData?) {
// now have to explicitly unwrap
let myDataUnwrapped = myData!
...
}
This just seems to be an extremely verbose way to deal with the issue. If an object is nil, won't the explicit unwrap in and of itself cause a runtime error (which could be caught and handled)? This tends to be a nightmare when stringing things together. I've had to do something like:
self.dataConnection!.somethingReturningAnObject!.thatObjectsVariable!.someMethod()
var myData? = self.dataConnection
var anotherObject? = myData!.somethingReturningAnObject
...
The way I'm used to doing this is that you simply define a variable, and if it is set to null and you try to do something with it, an exception (that you can catch and handle) is thrown. Is this simply not the way things work anymore in Swift? This has confused me sufficiently that just about every time I try to compile an app, I get tons of errors about this (and I just let Xcode fix them). But this can't be the best way to deal with it.
Do I have to consistently deal with wrapping and unwrapping variables - even those which are expected to never be null in the first place but simply can't be assigned at compile time?
However, I do not know how to define a class-level variable via let which will be assigned at runtime.
This part is easy. Just use let instead of var. With Swift 1.2 and later, you can delay the actual assignment of a let. The compiler is smart enough to do flow analysis and make sure it's assigned once, and only once, in all paths. So in the case of a class-wide let, the assignment can also happen in the constructor.
But now I have to deal with the nullable data type, and do explicit unwrapping every time I use it anywhere.
But this is what implicitly unwrapped Optionals are for. For example, StoryBoard defines all #IBOutlets as implicitly unwrapped, because the semantics are very clear: upon entrance to viewDidLoad() and everywhere after, unwrapping is safe. If you can prove clear semantics to yourself, you can do the same.
So you have roughly 4 choices:
A) declare at class level as implicitly unwrapped:
let dataConnection: MyData!
And be forced to initialize it in the constructor:
init() {
let whateverObj = someInitialCalculation()
dataConnection = whateverObj.someWayOfGettingTheConnection()
}
And from then on you don't need the '!'; it should be clear that implicit unwrap is always safe.
B) Initialize it right in its declaration if its initialization is reliable and sensible at that point, allowing you to forgo the entire concept of Optionals:
let dataConnection = SomeClass.someStaticMethod()
C) Declare at class level as a var, as implicit optional:
var dataConnection: MyData!
You won't have to init it in the constructor; let it be nil until its value can/should be computed. You still need some flow analysis to prove after a certain point, as in the case of #IBOutlets, accessing it will always be valid
D) The most 'unpredictable' case. Declare it as an explicit optional, because throughout the lifecycle of the class, the data connection will come and go:
var dataConnection: MyData?
func someMethodThatHandlesData() {
if let dC = dataConnection {
dc.handleSomeData()
}
else {
alert("Sorry, no data connection at the moment. Try again later.")
}
}
I think you're imagining that Swift always forces you down path D).
As far as your spaghetti-string code, you want to look into Optional Chaining, and only need to check the end result for nil.
Hi I'm new to swift language, first of all I don't know if this is a permitable topic I'm creating but I need to understand this and couldn't find any information on the web for this
in swift I realized there's a couple of ways for declaring a variable and it's type. but I don't know the differences and don't know where to use which..
correct me If I am wrong..
to begin with: when
var anything = "When I do it like this my anything variable becomes type of string"
but if I type
var anything = 12 //it's type Int
and so on.. apart from this I could also declare these variables as
var anything:Int
or
var anything:String
so far I'm good with this but what is the difference of declaring a global variable as
var anything:String
or
var anything:String = String()
how do I decide to use which and where? thank you
I'll start backwards. What is the difference between
var anything:String and var anything:String = String()
The first one declares a variable called anything of type String and the second initializes it by calling String's constructor. In the first case you will have to tell Swift's compiler what to expect from this variable - will it have a value or it will be nil. So the best thing to do if you don't know this is to declare it as optional:
var anything:String?
About the types that you initialize like this var anything = 12, Swift determines the type by the context, in this case it is an Int.
Swift types can be inferred (determined from the context). In
var anything: Int = 12
Int is redundant as it can be inferred form context (Int is default for integer literals). However sometimes you need more specific like Int8. You can then explicitly declare the type or use initialiser to infer the type type:
var anything: Int8 = 12
or
var anything = Int8(12)
Personally I used type inferring whenever I can and haven't run into any problems yet.
Your question is very basic, but I understand the trouble of learning a new language and that you need help. It is the standard learning curve.
Swift uses a technique called type inference. It can determine the type of a variable from the initial value.
var v = 8
automatically make v an Int.
var v:Int = 8
does the same
You can always use inferred types. Try to make your code readable and if type-inference improves the readability, then use it.
If you need more context to be able to understand your code 2 weeks after writing it, use explicitly declared types.
When you declare variables without an initial value you always have to declare the type explicitly. In this case, the compiler does not have any chance to guess the type.
Silly beginner Swift question:
I am expecting the following 3 lines of code to work in the playground:
let items = ["Apple", "Orange", "Pear"]
items[1] = "Banana" // error here
items
Now the error
error: '#lvalue $T5' is not identical to 'String'
items[1] = "Banana"
My understanding that updating content of immutable array is possible in Swift.
I use XCODE 6.1.1
Any idea what is going on here?
Thanks
Based on this thread this was possible in previous releases:
Why in immutable array in swift value can be changed?
When you write let, you define an immutable variable. Use var instead; this lets you define a variable that is mutable.
as stated before me- use a var array if you wish to change your array.
a bit below the question you posted a link and an answer was given inside:
Array in Swift has been completely redesigned to have full value
semantics like Dictionary and String have always had in Swift. This
resolves various mutability problems – now a 'let' array is completely
immutable, and a 'var' array is completely mutable – composes properly
with Dictionary and String, and solves other deeper problems. Value
semantics may be surprising if you are used to NSArray or C arrays: a
copy of the array now produces a full and independent copy of all of
the elements using an efficient lazy copy implementation. This is a
major change for Array, and there are still some performance issues to
be addressed. Please see the Swift Programming Language for more
information. (17192555)
The use of the let keyword declares a Constant.
By definition, a constant cannot be modified.
You want to use the var keyword to declare a Variable,
hence things that will/may vary.
From the apple Swift documentation:
Constants and Variables
Constants and variables associate a name (such as
maximumNumberOfLoginAttempts or welcomeMessage) with a value of a
particular type (such as the number 10 or the string "Hello"). The
value of a constant cannot be changed once it is set, whereas a
variable can be set to a different value in the future.
Declaring Constants and Variables
Constants and variables must be declared before they are used. You
declare constants with the let keyword and variables with the var
keyword. Here’s an example of how constants and variables can be used
to track the number of login attempts a user has made:
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0