Apple's book "The Swift Programming Language (Swift 3.1)" states the following:
As with function and method parameters, initialization parameters can have both a parameter name for use within the initializer’s body and an argument label for use when calling the initializer.
However, initializers do not have an identifying function name before their parentheses in the way that functions and methods do. Therefore, the names and types of an initializer’s parameters play a particularly important role in identifying which initializer should be called. Because of this, Swift provides an automatic argument label for every parameter in an initializer if you don’t provide one.
I don't understand the last sentence, as I didn't notice any difference between functions/methods and initializers when it comes to parameters names/labels. How is the argument label automatically provided for an initializer?
The feature being described is this: Given a struct:
struct Point {
let x: Double
let y: Double
}
Swift will automatically generate Point.init(x: Double, y: Double). If you add an init method of your own in the main struct definition, then Swift won't create that automatic init. (If you add an init in an extension, then you will get an automatic init. This is why people often add convenience init in an extension for structs.)
The point the last paragraph is trying to make is that Point(x:y:) is preferable to Point(_:_:). The labels in an initializer are even more valuable than labels in method names, because all initializers have the same "base" name ("init"). They're just explaining why they didn't choose a more implicit default that some people might expect coming from other languages.
In short, sometimes unlabeled parameters make sense in methods depending on what the name of the method is and how unambiguous that makes the first parameter. But in init, unlabeled parameters should be eyed with strong suspicion.
Related
I'm trying to understand how to find protocol method's implementation.
I know that Swift uses an Existential Container for fixed-size storage in Stack memory which manages how to describe an instance of a struct in memory. and it has a Value Witness Table (VWT) and Protocol Witness Table (PWT)
VWTs know how to manage real value in instance of struct (their lifecycle) and PWTs know the implementation of protocol's method.
But I want know the relation between the instance of a struct and the "existential container".
Does an instance of struct have a pointer which refers to an existential container?
How does an instance of a struct know its existential container?
Preface: I don't know how much background knowledge you have, so I might over-explain to make sure my answer is clear.
Also, I'm doing this to the best of my ability, off by memory. I might mix up some details, but hopefully this answer could at least point you towards further reading.
See also:
https://stackoverflow.com/a/41490551/3141234
https://github.com/apple/swift/blob/main/docs/SIL.rst#id201
In Swift, protocols can be used "as a type", or as a generic constraint. The latter case looks like so:
protocol SomeProtocol {}
struct SomeConformerSmall: SomeProtocol {
// No ivars
}
struct SomeConformerBig: SomeProtocol {
let a, b, c, d, e, f, g: Int // Lots of ivars
}
func fooUsingGenerics<T: SomeProtocol>(_: T) {}
let smallObject = SomeConformerSmall()
let bigObject = SomeConformerBig()
fooUsingGenerics(smallObject)
fooUsingGenerics(bigObject)
The protocol is used as a constraint for type-checking at compile time, but nothing particularly special happens at runtime (for the most part). Most of the time, the compiler will produced monomorphized variants of the foo function, as if you had defined fooUsingGenerics(_: SomeConformerSmall) or fooUsingGenerics(_: SomeConformerBig) to begin with.
When a protocol is "used like a type", it would look like this:
func fooUsingProtcolExistential(_: SomeProtocol) {}
fooUsingGenerics(smallObject)
fooUsingGenerics(bigObject)
As you see, this function can be called using both smallObject and bigObject. The problem is that these two objects have different sizes. This is a problem: how will the compiler know how much stack space is necessary to allocate for the arguments of this function, if the arguments can be different sizes? It must do something to help fooUsingProtcolExistential accommodate that.
Existential containers are the solution. When you pass a value where a protocol type is expected, the Swift compiler will generate code that automagically boxes that value into an "existential container" for you. As currently defined, an existential container is 4 words in size:
The first word is a pointer to the Protocol Witness Table (more on this later)
The next three words are inline storage for the value.
When the value being stored is less than 3 words in size (e.g. SomeConformerSmall), the value is packed directly inline into that 3 word buffer. If the value is more than 3 words in size (e.g. SomeConformerSmall), a ARC-managed box is allocated on the heap, and the value is copied into there. A pointer to this box is then copied into the first word of the existential container (the last 2 words are unused, IIRC).
This introduces a new issue: suppose that fooUsingProtcolExistential wanted to forward along its parameter to another function. How should it pass the EC? fooUsingProtcolExistential doesn't know whether the EC contains a value-inline (in which case, passing the EC just entails copying its 4 words of memory), or heap-allocated (in which case, passing the EC also requires an ARC retain on that heap-allocated buffer).
To remedy this, the Protocol Witness Table contains a pointer to a Value Witness Table (VWT). Each VWT defines the a standard set of function pointers, that define how the EC can be allocated, copied, deleted, etc. Whenever a protocol existential needs to be manipulated in someway, the VWT defines exactly how to do so.
So now we have a constant-size container (which solves our heterogeneously-sized parameter passing problem), and a way to move the container around. What can we actually do with it?
Well at a minimum, values of this protocol type must at least define the required members (initializers, properties (stored or computed), functions and subscripts) that the protocol defines.
But each conforming type might implement these members in a different way. E.g. some struct might satisfy a method requirement by defining the method directly, but another class might satisfy it by inheriting the method from a superclass. Some might implement a property as a stored property, others as a computed property, etc.
Handling these incompatibilities is the primary purpose of the Protocol Witness Table. There's one of these tables per protocol conformance (e.g. one for SomeConformerSmall and one for SomeConformerBig). They contain a set of function pointers with point to the implementations of the protocols' requirements. While the pointed-to functions might be in different places, the PWT's layout is consistent for the protocol is conforms to. As a result, fooUsingProtcolExistential is able to look at the PWT of an EC, and use it to find the implementation of a protocol method, and call it.
So in short:
An EC contains a PWT and a value (inline or indirect)
A PWT points to a VWT
My understanding:
Struct doesn't know where existential container/value witness table/protocol witness table is, the compiler knows. If needed somewhere, compiler pass them to there.
I am coming from C++ to Swift. I have this situation with respect to protocols and structs (I am working with random numbers):
(1) A protocol RandomPr that specifies there are methods such as randFloat() that returns a Float between 0 and 1.
(2) A struct RandomS that implements RandomPr using a "real" random number generator.
(3) A struct FakeRandomS that implements RandomPr, but has additional methods such as loadFloat() to load an array of Floats that are then regurgitated when I call randFloat() on a FakeRandomS instance. (For testing purposes.)
Now I have a function DoSomething(rng: inout RandomPr), which I want to use with both RandomS and FakeRandomS. The parameter has to be in-out as I need to update the RNG (whether it is real or fake). No problem calling DoSomething with an instance of RandomS.
But if I do
var fakeRng = FakeRandomS()
fakeRng.loadFloat([0.1, 0.2, 0.3])
DoSomething(rng: &fakeRng)
I get an error "Inout argument could be set to a value with a type other than 'FakeRandomS'. The suggested fix is to define fakeRng as
var fakeRng: RandomPr = FakeRandomS()
But now trying to call loadFloat on fakeRng fails because RandomPr doesn't have a method loadFloat, and the compiler doesn't see that fakeRng does have one.
I tried making another protocol FakeRandomPr that contains the extra methods that FakeRandomS has, and defining
var fakeRng: RandomPr & FakeRandomPr = FakeRandomS()
but, frustratingly, I now get the "Inout argument could be set to a value with a type other than ..." error back again.
I could do the equivalent of this in C++ without problems (a pure abstract base class and two child classes, passed in by reference), and it didn't matter that one of the things I wanted to pass in has extra methods. I want to translate this into protocols and structs. What is the Swift solution?
What is the Swift solution?
You may need to use generics:
func doSomething<RP: RandomPr>(rng: inout RP) {
//...
}
Swift is not just another syntax of C++, better think in Swifty way.
Swift appears to share with python one characteristic of requiring the class instance reference to access the members - even inside the class itself. The default in both languages is self. In particular
self.someClassMethod()
This is identical between python and swift. I also dislike this requirement finding it to be intrusive: it attracts my attention to self and away from which method is actually being invoked. In python I reduce (though do not remove) the annoyance by using s instead:
def someInstanceMethod(s, param1, param2)
instead of the standard
def someInstanceMethod(self, param1, param2)
Then inside the method I can access other instance methods :
s.someOtherInstanceMethod()
I'm not going to fight any battles on this: PEP folks will jump up and down about it -but it is more readable to me and others in my team. Is there any such way to do a shortcut in swift? I noticed typealias and tried to use it:
fileprivate let tp = U.tprint // Any non-critical logging statements will happen with this
But then it is necessary to do this:
self.tp("Loaded synthesizer settings")
Without the reference to self the following error occurs:
(162, 25) reference to property 'tp' in closure requires explicit 'self.' to make capture semantics explicit
I would prefer just
tp("Loaded synthesizer settings")
but that is not apparently possible. Can we get closer to that - along the lines of s.<method> instead of self.<method> ?
It's a little unclear what the question is, or what you think is the purpose of passing self around, so here's a quick summary of the key facts:
There are instance members and type members (type members are marked static or class).
If a method is an instance method, it does not need to say self to access instance members.
If a method is a type method, it does not need to say self to access type members.
If a method is an instance method, it can say Self to access type members.
If a method is a type method, there is no instance so instance members cannot be accessed.
I'm trying to make a generic testing interface that takes an function, fills out the function signature parameters via introspection, and then runs the arbitrary function.
Test(function: <Any>)
{
let signature = Mirror(reflecting:function)
...
}
In Swift 3 I can get the function signature from reflection. With the Zewo library I have KVO & KVC built on top of the swift 3 Metadata. So far so good.
But the last two steps I'm tripping over: Building up a arbitrary parameter list and dynamically calling Function.
Is there a generic way to do this? (pointers are allowed!) Now that tuple splat is gone (and it was never dynamic in the first place), are there any exposed methods for dynamic arguments, or popping arguments onto the stack dynamically or another language provision?
I'm reading through the Swift documentation about type methods and type properties, and I cannot for the life of me figure out why it says this particular thing (in bold):
Within the body of a type method, the implicit self property refers to
the type itself, rather than an instance of that type. For
structures and enumerations, this means that you can use self to
disambiguate between type properties and type method parameters, just
as you do for instance properties and instance method parameters.
More generally, any unqualified method and property names that you use
within the body of a type method will refer to other type-level
methods and properties. A type method can call another type method
with the other method’s name, without needing to prefix it with the
type name. Similarly, type methods on structures and enumerations
can access type properties by using the type property’s name without a
type name prefix.
So, why is this pointing out structures and enumerations being able to do these things when, as far as I know, you can do these things with any kind of type methods/parameters (i.e. classes as well)? It makes me think I'm missing something.
The page in the documentation I'm looking at is here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
Apparently I wasn't the only one with this question. I'm not sure how I didn't see this post before: https://softwareengineering.stackexchange.com/questions/276962/static-properties-and-implicit-self-property-in-structures-and-enumerations-vs