Swift: Difference between var a: Int { calculateValue() } and var b = { calculateValue() }() - swift

I am trying to understand the difference between
var a: Int { calculateValue() }
and
var b = { calculateValue() }()
I'm a little confused, but I think I get the basics, so I just wanted to make sure I have it right: Is it that the first one is a computed property that will run calculateValue() every single time I use a somewhere and use that value, whereas the second one just assigns the value of the closure to b at the time of initialisation?
Thank you

A
var a: Int { calculateValue() } is a computed property, equivalent to:
var a: Int {
get { calculateValue() }
}
The computed body is called everytime a is accessed, which means calculateValue is called on every access (which can be good good, if its value changes, but wasteful if it doesn't)
B
{ calculateValue() } is a closure of type () -> Int, whose body calls calculateValue. The trailing () calls that closure, which makes it an immediately evaluated closure.
The result (as assigned to the stored property var b) is just an Int (not at () -> Int, because the closure was already called)

Related

Swift protocol with lazy property - Cannot use mutating getter on immutable value: '$0' is immutable

Goal: Create a protocol that allows lazy computation of a property for structs that conform to the protocol and then add the properties for an array of those structs. The computation is intensive and should only be executed once, hence the lazy requirement.
So, after lots of reading (eg this: Swift Struct with Lazy, private property conforming to Protocol) and trial and error (please don't flag this as a duplicate, unless it actually addresses this exact case), I came up with something that works:
import Foundation
protocol Foo {
var footype: Double { mutating get }
func calculateFoo() -> Double
}
struct Bar: Foo {
private lazy var _footype: Double = {
let value = calculateFoo()
return value
}()
var footype: Double {
mutating get {
return _footype
}
}
func calculateFoo() -> Double {
print("calc")
return 3.453
}
}
Testing this in a Playground:
var bar = Bar()
print(bar.footype)
print(bar.footype)
And the output is:
calc
3.453
3.453
So far, so good.
Now, I want to make an array of Bar and add the footype properties:
var bar1 = Bar()
var bar2 = Bar()
var bar3 = Bar()
var bars = [bar1, bar2, bar3]
print(bars.map { $0.footype }.reduce(0.0, +))
Which gives me the following error:
Cannot use mutating getter on immutable value: '$0' is immutable
Found a lot of info on this error, but am stuck how to solve it. One way would be to use class instead of struct, but that doesn't work well with other parts of the code.
Is it possible what I am trying to achieve?
As you can tell from the error message, $0 is immutable, so you can't use a mutating member on it.
Therefore, you can't iterate over the bars directly. What you can do is iterating through its indices, because we know that bars[$0] is mutable:
print(bars.indices.map { bars[$0].footype }.reduce(0.0, +))

what is the difference protocol's `: AnyObject` between `none`?

1.
protocol A: AnyObject { }
2.
protocol A { }
I know case 1 can limit class-type
But, why should I limit class-type?
AnyObject requires that conforming types be classes, rather than structs or enums. See Class-Only Protocols for details.
Classes provide reference semantics, rather than value semantics, which you may require for your protocol. For example, if you want to observe an object, that only makes sense for a reference type (you can't observe changes to a value type, since value types are copied when modified). For more details on that see Structures and Classes, and particularly the sections explaining value and reference types.
There is no value type equivalent of AnyObject. You can't require value semantics for a protocol. This can lead to some headaches. As an example of the difference, consider the following:
protocol Incrementing {
var value: Int { get set }
}
extension Incrementing {
func incremented() -> Self {
var new = self // Value types copy, reference types reference
new.value += 1
return new
}
}
struct S: Incrementing { var value: Int = 0 }
class C: Incrementing { var value: Int = 0 }
var s = S()
s.incremented().value // 1
s.value // 0
var c = C()
c.incremented().value // 1
c.value // 1 (!!!)
This code makes sense for a struct, but is buggy for a class. There's no real fix for that in Swift today.

How to store a reference to an integer in Swift

I know swift has both reference types and value types. And I know Int is a value type. But how can I store a reference to an integer?
var x:Int = 1
var y:Int = x // I want y to reference x (not copy)
++y
println(x) // prints 1, but I want 2
I tried using boxed types, and I tried using array of Int, but neither works for holding a reference to integer.
I guess I can write my own
class IntRef {
var a:Int = 0
init(value:Int) { a = value }
}
var x:IntRef = IntRef(value: 3)
var y = x
++y.a
println(x.a)
seems a bit awkward.
Unfortunately there is no reference type Integer or something like that in Swift so you have to make a Box-Type yourself.
For example a generic one:
class Reference<T> {
var value: T
init(_ value: T) { self.value = value }
}
You can also use closures. I think these better because they are more powerful and also more specific. They not only store a reference, but they also indicate how the reference will be used. For example,
var x:Int = 1
var setx = { (a:Int) in x = a }
var getx = { x }
setx(getx() + 1)
println(x) // This will print 2
I don't recommend actually defining getx/setx. Define a closure that does a specific task for your application.

Swift- variable not initialized before use (but it's not used)

Currently I've got some swift code like this:
class C {
let type: Type;
var num = 0;
init() {
self.type = Type({ (num: Int) -> Void in
self.num = num;
});
}
}
The Swift compiler refuses to permit it, saying that I've referenced self.type before it's initialized, even though that's clearly completely untrue. Furthermore, I can't employ the workaround found in other questions/answers, because the type is not optional, and it's immutable, so it can't be initialized with nil pointlessly first.
How can I make the Swift compiler accept this perfectly valid code?
This has nothing to do with returning from the initializer early. The callback is executed asynchronously- it is stored and then used later.
I also have a few further lets that are initialized after this one. I would have to turn them all into mutable optionals, even though they're not optional and can't be mutated.
This works:
class C {
var type: Type?;
var num = 0;
init() {
self.type = Type({ (num: Int) -> Void in
self.num = num;
});
}
}
I assume you knew that. But you want to know why your version isn't working.
Now for the tricky part: for the line
self.num = num;
to work, the compiler has to pass self to inside the closure. The closure could be and probably is executed inside of the constructor of Type.
This is as if you had written
self.type = Type({ (self: C, num: Int) -> Void in
self.num = num
});
which is syntactically wrong but explains what the compiler has to do to compile your code.
To pass this necessary instance of self to the constructor of Type, self has to be initialized. But self isn't initialized, because you are still in the constructor.
The compiler tells you which part of self is not initialized, when you try to pass self to the constructor of Type.
P.S.
obviously Type knows num in your code.
If you want to use let in C instead of var you could do...
class Type {
let num: Int
init () {
num = 3
}
}
class C {
let type: Type;
var num = 0;
init() {
self.type = Type();
num = type.num
}
}
or even
class C {
let type: Type;
var num: Int {
return type.num
}
init() {
self.type = Type();
}
}
depending on whether you want num to change or not. Both examples compile without error.
First, it's important to explain why this is not perfectly valid code, and that it isn't clear at all that self.type is not used before it is initialized. Consider the following extension of your code:
struct A {
init(_ f: (Int) -> Void) { f(1) }
}
class C {
let type: A
var num = 0 {
didSet { print(type) }
}
init() {
self.type = A({ (num: Int) -> Void in
self.num = num
})
}
}
If you walk through the logic, you'll note that self.type is accessed via print before it has been initialized. Swift can't currently prove that this won't happen, and so doesn't allow it. (A theoretical Swift compiler might prove that it wouldn't happen for some particular cases, but for most non-trivial code it would likely bump into the halting problem. In any case, the current Swift compiler isn't powerful enough to make this proof, and it's a non-trivial proof to make.)
One solution, though somewhat unsatisfying, is to use implicitly unwrapped optionals:
private(set) var type: A! = nil
Except for the declaration, every other part of the code is the same. You don't have to treat it as optional. In practice, this just turns off the "used before initialization" checks for this variable. It also unfortunately makes it settable inside of the current file, but does make it immutable to everyone else.
This is the technique I've most often used, though often I try to rework the system so that it doesn't require this kind of closure (not always possible, but I often rack my brain to try). It's not beautiful, but it is consistent and bounds the ugly.
Another technique that can work in some cases is laziness:
class C {
lazy var type: A = {
A({ (num: Int) -> Void in self.num = num })}()
var num = 0
init() {}
}
Sometimes that works, sometimes it doesn't. In your case it might. When it does work, it's pretty nice because it makes the property truly immutable, rather than just publicly immutable, and of course because it doesn't require !.
Interesting.
It looks like the error goes away if you avoid referencing self inside the closure.
If the callback is synchronous you can change your code as follow:
class C {
let type: Type
var num = 0
init() {
var numTemp = 0 // create a temporary local var
let initialType = Type({ (num: Int) -> () in
numTemp = num // avoid self in the closure
});
self.type = initialType
self.num = numTemp
}
}
Important: this will NOT work if the closure is async.
Tested with Xcode (Playground) 6.4 + Swift 1.2
Hope this helps.
As appzYourLife said, a temporary variable for num will suffice:
class Type{
var y: (Int)->Void
init(y2:((Int)->Void)){
self.y = y2
}
}
class C {
let type: Type
var num: Int = 0
init() {
var num2 = 0
self.type = Type(y2: { (num3: Int) -> () in
num2 = num3
});
self.num = num2
}
}
However, you do not need a temporary variable for type, this error message is misleading.

Generalized type constraints with Swift

As an exercise, I'm trying to extend Array in Swift to add a sum() member function. This should be type safe in a way that I want a call to sum() to compile only if the array holds elements that can be added up.
I tried a few variants of something like this:
extension Array {
func sum<U : _IntegerArithmeticType where U == T>() -> Int {
var acc = 0
for elem in self {
acc += elem as Int
}
return acc
}
}
The idea was to say, “OK, this is a generic function, the generic type must be something like an Int, and must also be the same as T, the type of the elements of the array”. But the compiler complains: “Same-type requirement make generic parameters U and T equivalent”. That's right, and they should be, with the additional contraint T : _IntegerArithmeticType.
Why isn't the compiler letting me do this? How can I do it?
(I know that I should later fix how things are added up and what the return type exactly is, but I'm stuck at the type constraint for now.)
As per Martin R's comment, this is not currently possible. The thing I'm tempted to use in this particular situation would be an explicit passing of a T -> Int conversion function:
extension Array {
func sum(toInt: T -> Int?) -> Int {
var acc = 0
for elem in self {
if let i = toInt(elem) {
acc += i
}
}
return acc
}
}
Then I can write stuff like this:
func itself<T>(t: T) -> T {
return t
}
let ss = ["1", "2", "3", "4", "five"].sum { $0.toInt() }
let si = [1, 2, 3, 4].sum(itself)
An explicit function has to be passed, though. The (itself) part can of course be replaced by { $0 }. (Others have called the itself function identity.)
Note that an A -> B function can be passed when A -> B? is needed.