In the subsection Capturing Values of the section Closures, Apple's book The Swift Programming Language says
The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.
It should be written as "refer to constants and refer to and modify variables" Try the following in a playground:
let x = 1
println(x)
{ x = x + 1 }()
println(x)
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
As everyone knows, JavaScript "Hoists" the variables to the top of the file or scope. But from my understanding, using let is the same as var only let is confined to the scope it is defined in.
Being a compiled language instead of an interpreted, can we assume Swift does NOT do this?
For example:
x = 10
var y = x + 10
var x
can we assume Swift does NOT do this?
You can assume whatever you want, but no matter the programming language, your absolute best bet it to just try it and find out. If you would have pasted your sample code into a Playground or in any Swift-capable IDE, or just tried running it through the command line, you'd quickly find out that this simply does not work.
Your question is somewhat confusing, but I think I can address all or at least most of your questions.
x = 10
var y = x + 10
var x
Assuming there is no other code to go with your original sample, it simply does not compile. All three lines have a problem.
The first two lines complain about the use of an unresolved identified 'x'. In English, this means Swift can't figure out what variable you're talking about. Variables in Swift must be declared before they are used, so the declaration on line three doesn't help the next two lines.
The third line complains that it can't figure out what type x should be. "Type annotation missing in pattern". In some cases, Swift can figure out what type our variable should be. For example, with var x = 10, Swift can figure out that x's type should be Int. If we want something else, we must specify. But if we aren't assigning a value in the declaration, Swift has no idea and must be told: var x: Int?
What about the case where x exists at a different scope?
Well, Swift allows variable shadowing. That is to say, a variable declared at one scope hides a variable declared at another scope.
So, for example:
class Foo {
let x = 10
func foo(value: Int) -> Int {
let a = value * self.x
let x = 10
return a * x
}
}
Now we can use some x before we've declared a locally scoped x, but these are different variables. Also, perhaps most importantly, notice the self. prepended to x here. It's required. Without it, Swift will refuse to compile this code and will complain: "Use of local variable 'x' before its declaration."
However, within functions of classes is not the only place we can shadow variables. We can also do it within if blocks (among other places) which is where things can get a little more confusing. Consider this:
class Foo {
let x = 10
func foo(value: Int) -> Int {
print(x)
if x > 3 {
let x = 2
print(x)
}
return x
}
}
Here, we've used x twice before declaring it. And we didn't have to make use of the self. and it doesn't complain and compiles perfectly fine. But it's important to note that outside the if block (including the x > 3 conditional) the x we're referencing is the instance variable, but inside the if block, we've created a new variable called x which shadows the instance variable. We can also create the same sort of shadowing by using if let and if var constructs (but not guard let).
The result of calling this function will be that the value 10 is printed, we enter the if block, the value of 2 is printed, then we exit the if block and the value of 10 is returned.
Now let's through var into the mix here. First, if you aren't already aware, you should start by reading this which explains the difference between let and var (one is a constant, the other is not).
Let's combine let vs var with scoping and variable shadowing to see how it effects things.
class Foo {
let x = 10
func foo(value: Int) -> Int {
print(x)
if x > 3 {
var x = 2
while x < 10 {
print(x)
x += 3
}
return x
}
return x
}
}
Okay, so this is the same as before but with a slightly more complicated bit within the if block.
Here, our locally-scoped variable is declared as a var while our instance variable remains a constant let. We cannot modify the instance variable, but we can modify the local variable. And we do so, on each iteration of the while loop.
But importantly, this variable is an entirely different variable from the instance variable. It might as well have a completely different name (and in practice, it basically always should have a different name). So modifying our local variable x doesn't change anything about our more broadly scoped instance variable x. They're different variables that reside in different memory locations. And once a variable is declared as a let or a var, that variable cannot be changed to the other.
'let' and 'var' do not have a difference in scope.
Global variables are variables that are defined outside of any
function, method, closure, or type context. Local variables are
variables that are defined within a function, method, or closure
context.
Why does for loop require var while for..in does not allow use of var?
for loop
for var index = 0; index < 10; i++ {
}
for..in loop
for index in "test" {
}
instead of:
for var index in "test" {
}
The Swift documentation sums it up pretty nicely:
index is a constant whose value is automatically set at the start of each iteration of the loop. As such, it does not have to be declared before it is used. It is implicitly declared simply by its inclusion in the loop declaration, without the need for a let declaration keyword.
In other words, the variable used in a for/in loop can only be a constant; thus, there's really no need to require that let be used.
The variable(s) used in a "traditional" for loop, however, can be variables or constants, so var or let is required. (Generally, they will be variables, but it is possible to use a constant in a for loop.) They can also be declared outside of the for loop (i.e., before it) and still used in the for loop. Because of this flexibility, you are required to declare it as a constant or variable.
The compiler expands for x in 0..<5 to the following:
var g = (0..<5).generate() {
while let x = g.next() {
// Use x in loop body
}
Every time around the loop, x is a freshly declared variable, the value of unwrapping the next result from calling next on the generator.
Now, that while can be rewritten in this fashion:
while var x = g.next() {
// use x here
}
I guess for this reason, for...in doesn't support the var syntax for declaring the loop counter so that it doesn't give you the wrong impression that x is mutable.
If you run this code, the variable f seems to shadow the function f. Is there anyway to reach the function f?
func f (a:Int)->Int{
return a + 43
}
var f = {(a:Int) in a + 42}
var z = f(1)
println(z)
No.
In Swift, function declarations are simply shortcuts for what you did with that closure + variable thing. That is, function names are essentially constants and should always be viewed as such (you can even pass around the function name, without brackets, as a reference).
What you're doing is you're redeclaring the name f to the variable closure. It seems Swift has a compiler issue not complaining about this. However, this problem would never occur in good code, so it's not a real problem.
It can be a bit confusing, though.
Found the following snippet on the Closure page on wikipedia
//# Return a list of all books with at least 'threshold' copies sold.
def bestSellingBooks(threshold: Int) = bookList.filter(book => book.sales >= threshold)
//# or
def bestSellingBooks(threshold: Int) = bookList.filter(_.sales >= threshold)
Correct me if I'm wrong, but this isn't a closure? It is a function literal, an anynomous function, a lambda function, but not a closure?
Well... if you want to be technical, this is a function literal which is translated at runtime into a closure, closing the open terms (binding them to a val/var in the scope of the function literal). Also, in the context of this function literal (_.sales >= threshold), threshold is a free variable, as the function literal itself doesn't give it any meaning. By itself, _.sales >= threshold is an open term At runtime, it is bound to the local variable of the function, each time the function is called.
Take this function for example, generating closures:
def makeIncrementer(inc: Int): (Int => Int) = (x: Int) => x + inc
At runtime, the following code produces 3 closures. It's also interesting to note that b and c are not the same closure (b == c gives false).
val a = makeIncrementer(10)
val b = makeIncrementer(20)
val c = makeIncrementer(20)
I still think the example given on wikipedia is a good one, albeit not quite covering the whole story. It's quite hard giving an example of actual closures by the strictest definition without actually a memory dump of a program running. It's the same with the class-object relation. You usually give an example of an object by defining a class Foo { ... and then instantiating it with val f = new Foo, saying that f is the object.
-- Flaviu Cipcigan
Notes:
Reference: Programming in Scala, Martin Odersky, Lex Spoon, Bill Venners
Code compiled with Scala version 2.7.5.final running on Java 1.6.0_14.
I'm not entirely sure, but I think you're right. Doesn't a closure require state (I guess free variables...)?
Or maybe the bookList is the free variable?
As far as I understand, this is a closure that contains a formal parameter, threshold and context variable, bookList, from the enclosing scope. So the return value(List[Any]) of the function may change while applying the filter predicate function. It is varying based on the elements of List(bookList) variable from the context.
I am wraping some SQL Stored Procs with in/out parameters. This of course means I have to do ugly stuff like declare my parameters as by reference and use mutables.
How would I do this in F#?
F# does indeed have a byref parameter. Here's an example from the MSDN page:
type Incrementor(z) =
member this.Increment(i : int byref) =
i <- i + z
Mutable variables also exist (though there's an important difference between using ref and mutable variables, either of which can be used for many of the same purposes). The MSDN page on this subject is very informative - including a discussion of when to use which keyword/construct.
Example of reference variables:
// Declare a reference.
let refVar = ref 6
// Change the value referred to by the reference.
refVar := 50
Example of mutable variables:
// Declare a reference.
let mutable refVar = 6
// Change the value referred to by the reference.
refVar <- 50
As you can see, the syntax for assignment (as well as retrieval) differs between the two constructs, too.