Lazy load MirrorType - swift

Let's say I have something like this
struct A {
lazy var b: String = { return "Hello" }()
}
If I try to reflect struct A and access the value for b through its MirrorType like so:
var a = A()
var r = reflect(a)
for i in 0..r.count {
let (n, m) = r[i]
println("\(m.value)")
var c = a.b
println("\(m.value)")
}
I get nil in the console both times. Note that the underlying value type is Swift.Optional<Swift.String>, and the variable name is somewhat confusingly b.storage. Is there a way to access the underlying value of a lazy-loaded variable using reflection or initialize it from its MirrorType or am I stuck waiting for someone to write a first-class reflection api for Swift?

The MirorType is very limited in it's functionality. Besides that it's replaced by other functionality in Xcode 7 beta 4.
The point in your case is that the property has not been used yet. So it's actually still nil. The only way to make it not nil is by accessing the property by getting it's value. Unfortunately in Swift you can not do that by executing .valueForKey("propertyName")
If you are looking for a reflection library that is trying to get as much as possible out of Swift, then have a look at EVReflection

Related

Swift, when referencing a class property, is it making a copy of the data?

So I'm a little confused because of conflicting information, just looking for some clarity regarding memory allocation for Class properties.
So here are my assumptions, please let me know if any of them are wrong:
In Swift, except for Classes and Functions, everything is passed by Value.
Classes instances (objects) are allocated on the Heap
When you pass an object around, you are passing the pointer
When you reference a property on an object, the pointer is dereferenced, and the value of the property is retrieved
So here's my confusion, say my class has a String property, and an Int property. Both Swift data types, that get passed by value in any ordinary situation.
If I ask for let test = object.stringProperty, am I going to get a copy of my string value copied into my test variable?
Similarly, if I had a method inside of my class,
func getAllProperties() -> (String, Int) {
return (self.stringProperty, self.intProperty)
}
is object.getAllProperties() going to return a copy of the properties in a tuple?
I know it seems like a basic question, but after reading several sources I just ended up more uncertain than when I started
Yes and yes. It doesn't matter that the String and the Int were in a class. You asked for the String or the Int (or both), those are value types, you got copies.
It's easy to prove this to yourself, especially with the String. Just change something about it, and then look back at what the class instance is holding: it will be unchanged.
class C {
var stringProperty : String
init(string:String) {
self.stringProperty = string
}
}
let c = C(string:"hello")
var s = c.stringProperty
s.removeLast()
print(s) // hell
print(c.stringProperty) // hello
If you want to see the class-as-reference in action, make two of the same instance and do something to one of those:
class C {
var stringProperty : String
init(string:String) {
self.stringProperty = string
}
}
let c = C(string:"hello")
let d = c
c.stringProperty = "goodbye"
print(d.stringProperty) // goodbye

How does Optional covariance work in Swift

How does covariance work for Optionals in Swift?
Say I write the following code:
var nativeOptionalView: Optional<UIView>
let button = UIButton()
nativeOptionalView = .Some(button)
var nativeOptionalButton = Optional.Some(button)
nativeOptionalView = nativeOptionalButton
It compiles and works just fine. However if I define MyOptional as
enum MyOptional<T> {
case Some(T)
case None
}
And write the following:
var myOptionalView: MyOptional<UIView>
let button = UIButton()
myOptionalView = .Some(button)
var myOptionalButton = MyOptional.Some(button)
myOptionalView = myOptionalButton
I get the error:
error: cannot assign value of type 'MyOptional<UIButton>' to type 'MyOptional<UIView>'
I understand why this errors happens with MyOptional, what I don't understand is why it doesn't happen with Optional.
It doesn't. Swift does not support custom covariant generics for now.
The Swift type checker is per expression, not global (as in Haskell). This task is handled by the Semantic Analysis in lib/Sema. The constraint system then tries to match the types and special cases of covariance are then handled for collections, and optionals.
This was a language design decision. You should be able to do everything you need with the built-in collection types and optionals. If you aren't you should probably open a radar.
While I agree that there is probably some "compiler magic" going on, this can be accomplished in your custom implementation by casting the button to a UIView, e.g.
var myOptionalButton = MyOptional.Some(button as UIView)
or
var myOptionalButton: MyOptional<UIView> = .Some(button)

Cannot assign to property: function call returns immutable value

Consider the following example.
struct AStruct{
var i = 0
}
class AClass{
var i = 0
var a: A = A(i: 8)
func aStruct() -> AStruct{
return a
}
}
If I try to mutate the the variable of a instance of class AClass it compiles successfully.
var ca = AClass()
ca.a.i = 7
But If I try to mutate the return value of aStruct method, the compile screams
ca.aStruct().i = 8 //Compile error. Cannot assign to property: function call returns immutable value.
Can someone explain this.
This is compiler's way of telling you that the modification of the struct is useless.
Here is what happens: when you call aStruct(), a copy of A is passed back to you. This copy is temporary. You can examine its fields, or assign it to a variable (in which case you would be able to access your modifications back). If the compiler would let you make modifications to this temporary structure, you would have no way of accessing them back. That is why the compiler is certain that this is a programming error.
Try this.
var aValue = ca.aStruct()
aValue.i = 9
Explanation
aStruct() actually returns a copy of the original struct a. it will implicitly be treated as a constant unless you assign it a var.
Try using a class instead of a struct, as it's passed by reference and holds onto the object, while a struct is passed by value (a copy is created).

Syntactic Sugar Struct Reference in Swift?

In c++, one can introduce an alias reference as follows:
StructType & alias = lengthyExpresionThatEvaluatesToStuctType;
alias.anAttribute = value; // modify "anAttribute" on the original struct
Is there a similar syntactic sugar for manipulating a (value typed) struct in Swift?
Update 1: For example: Let say the struct is contained in a dictionary of kind [String:StructType], and that I like to modify several attributes in the the struct myDict["hello"]. I could make a temporary copy of that entry. Modify the copy, and then copy the temporary struct back to the dictionary, as follows:
var temp = myDict["hello"]!
temp.anAttribute = 1
temp.anotherAttribute = "hej"
myDict["hello"] = temp
However, if my function has several exit points I would have to write myDict["hello"] = temp before each exit point, and it would therefore be more convinient if I could just introduce and alias (reference) for myDict["hello"] , as follows:
var & alias = myDict["hello"]! // how to do this in swift ???
alias.anAttribute = 1
alias.anotherAttribute = "hej"
Update 2: Before down- or close- voting this question: Please look at Building Better Apps with Value Types in swift (from WWWDC15)!! Value type is an important feature of Swift! As you may know, Swift has borrowed several features from C++, and value types are maybe the most important feature of C++ (when C++ is compared to Java and such languages). When it comes to value types, C++ has some syntactic sugar, and my questions is: Does Swift have a similar sugar hidden in its language?. I am sure Swift will have, eventually... Please, do not close-vote this question if you do not understand it!
I have just read Deitel's book on Swift. While I'am not an expert (yet) I am not completely novel. I am trying to use Swift as efficient as possible!
Swift doesn't allow reference semantics to value types generally speaking, except when used as function parameters declared inout. You can pass a reference to the struct to a function that works on an inout version (I believe, citation needed, that this is implemented as a copy-write, not as a memory reference). You can also capture variables in nested functions for similar semantics. In both cases you can return early from the mutating function, while still guaranteeing appropriate assignment. Here is a sample playground that I ran in Xcode 6.3.2 and Xcode 7-beta1:
//: Playground - noun: a place where people can play
import Foundation
var str = "Hello, playground"
struct Foo {
var value: Int
}
var d = ["nine": Foo(value: 9), "ten": Foo(value: 10)]
func doStuff(key: String) {
let myNewValue = Int(arc4random())
func doMutation(inout temp: Foo) {
temp.value = myNewValue
}
if d[key] != nil {
doMutation(&d[key]!)
}
}
doStuff("nine")
d // d["nine"] has changed... unless you're really lucky
// alternate approach without using inout
func doStuff2(key: String) {
if var temp = d[key] {
func updateValues() {
temp.value = Int(arc4random())
}
updateValues()
d[key] = temp
}
}
doStuff2("ten")
d // d["ten"] has changed
You don't have to make the doMutation function nested in your outer function, I just did that to demonstrate the you can capture values like myNewValue from the surrounding function, which might make implementation easier. updateValues, however, must be nested because it captures temp.
Despite the fact that this works, based on your sample code, I think that using a class here (possibly a final class if you are concerned about performance) is really more idiomatic imperative-flavored Swift.
You can, if you really want to, get a raw pointer using the standard library function withUnsafeMutablePointer. You can probably also chuck the value into an inner class that only has a single member. There are also functional-flavored approaches that might mitigate the early-return issue.

Differentiating Between a Struct and a Class in Swift

I know why I would use a struct as opposed to a class, but how could I best tell which is being used by an API I'm using?
Obviously looking at the header file (or hopefully documentation) should make it immediately obvious. I am wondering if there is a way to know if the object I am using is a struct or class on face value though?
You can’t inherit from other structures or types. Classes have the ability to inherit functions, variables, and constants from parent classes.
In swift structs are value types while classes are reference types. Working with value types can make your code less error prone.
When you make a copy of a reference type variable, both variables are referring to the same object in memory. A change to one of the variables will change the other.
when you make a copy of a value type variable, the complete variable is copied to a new place in memory. A change to one of the copies will not change the other. If the copying of an object is cheap, it is far safer to make a copy than it is to share memory.
Auto completion in Xcode knows the type of type:
I'm not sure what you mean by "face-value". You can test to see if an object is an instance of a class by getting it's MirrorType using reflect and checking for the MirrorType's objectIdentifier property, like this:
struct TestStruct { }
class TestClass { }
let testStruct = TestStruct()
let testClass = TestClass()
if let x = reflect(testStruct).objectIdentifier {
println("I am a class...")
} else {
println("I am not a class...") // prints "I am not a class..."
}
if let x = reflect(testClass).objectIdentifier {
println("I am a class...") // prints "I am a class..."
} else {
println("I am not a class...")
}
This answer may be outdated with the upcoming release of Swift 1.2 (I do not have the new xCode beta so I can't say for sure), which I understand has better object introspection, but this does do the trick.