Error "Inout argument could be set to a value with a type other than ..." when passing in a protocol type - swift

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.

Related

How am I able to change this constant? [duplicate]

I'm really new to Swift and I just read that classes are passed by reference and arrays/strings etc. are copied.
Is the pass by reference the same way as in Objective-C or Java wherein you actually pass "a" reference or is it proper pass by reference?
Types of Things in Swift
The rule is:
Class instances are reference types (i.e. your reference to a class instance is effectively a pointer)
Functions are reference types
Everything else is a value type; "everything else" simply means instances of structs and instances of enums, because that's all there is in Swift. Arrays and strings are struct instances, for example. You can pass a reference to one of those things (as a function argument) by using inout and taking the address, as newacct has pointed out. But the type is itself a value type.
What Reference Types Mean For You
A reference type object is special in practice because:
Mere assignment or passing to function can yield multiple references to the same object
The object itself is mutable even if the reference to it is a constant (let, either explicit or implied).
A mutation to the object affects that object as seen by all references to it.
Those can be dangers, so keep an eye out. On the other hand, passing a reference type is clearly efficient because only a pointer is copied and passed, which is trivial.
What Value Types Mean For You
Clearly, passing a value type is "safer", and let means what it says: you can't mutate a struct instance or enum instance through a let reference. On the other hand, that safety is achieved by making a separate copy of the value, isn't it? Doesn't that make passing a value type potentially expensive?
Well, yes and no. It isn't as bad as you might think. As Nate Cook has said, passing a value type does not necessarily imply copying, because let (explicit or implied) guarantees immutability so there's no need to copy anything. And even passing into a var reference doesn't mean that things will be copied, only that they can be if necessary (because there's a mutation). The docs specifically advise you not to get your knickers in a twist.
Everything in Swift is passed by "copy" by default, so when you pass a value-type you get a copy of the value, and when you pass a reference type you get a copy of the reference, with all that that implies. (That is, the copy of the reference still points to the same instance as the original reference.)
I use scare quotes around the "copy" above because Swift does a lot of optimization; wherever possible, it doesn't copy until there's a mutation or the possibility of mutation. Since parameters are immutable by default, this means that most of the time no copy actually happens.
It is always pass-by-value when the parameter is not inout.
It is always pass-by-reference if the parameter is inout. However, this is somewhat complicated by the fact you need to explicitly use the & operator on the argument when passing to an inout parameter, so it may not fit the traditional definition of pass-by-reference, where you pass the variable directly.
Here is a small code sample for passing by reference.
Avoid doing this, unless you have a strong reason to.
func ComputeSomeValues(_ value1: inout String, _ value2: inout Int){
value1 = "my great computation 1";
value2 = 123456;
}
Call it like this
var val1: String = "";
var val2: Int = -1;
ComputeSomeValues(&val1, &val2);
The Apple Swift Developer blog has a post called Value and Reference Types that provides a clear and detailed discussion on this very topic.
To quote:
Types in Swift fall into one of two categories: first, “value types”,
where each instance keeps a unique copy of its data, usually defined
as a struct, enum, or tuple. The second, “reference types”, where
instances share a single copy of the data, and the type is usually
defined as a class.
The Swift blog post continues to explain the differences with examples and suggests when you would use one over the other.
When you use inout with an infix operator such as += then the &address symbol can be ignored. I guess the compiler assumes pass by reference?
extension Dictionary {
static func += (left: inout Dictionary, right: Dictionary) {
for (key, value) in right {
left[key] = value
}
}
}
origDictionary += newDictionaryToAdd
And nicely this dictionary 'add' only does one write to the original reference too, so great for locking!
Classes and structures
One of the most important differences between structures and classes is that structures are always copied when they are passed around in your code, but classes are passed by reference.
Closures
If you assign a closure to a property of a class instance, and the closure captures that instance by referring to the instance or its members, you will create a strong reference cycle between the closure and the instance. Swift uses capture lists to break these strong reference cycles
ARC(Automatic Reference Counting)
Reference counting applies only to instances of classes. Structures and enumerations are value types, not reference types, and are not stored and passed by reference.
Classes are passed by references and others are passed by value in default.
You can pass by reference by using the inout keyword.
Swift assign, pass and return a value by reference for reference type and by copy for Value Type
[Value vs Reference type]
If compare with Java you can find matches:
Java Reference type(all objects)
Java primitive type(int, bool...) - Swift extends it using struct
struct is a value type so it's always passed as a value. let create struct
//STEP 1 CREATE PROPERTIES
struct Person{
var raw : String
var name: String
var age: Int
var profession: String
// STEP 2 CREATE FUNCTION
func personInformation(){
print("\(raw)")
print("name : \(name)")
print("age : \(age)")
print("profession : \(profession)")
}
}
//allow equal values
B = A then call the function
A.personInformation()
B.personInformation()
print(B.name)
it have the same result when we change the value of 'B' Only Changes Occured in B Because A Value of A is Copied, like
B.name = "Zainab"
a change occurs in B's name. it is Pass By Value
Pass By Reference
Classes Always Use Pass by reference in which only address of occupied memory is copied, when we change similarly as in struct change the value of B , Both A & B is changed because of reference is copied,.

Differences generic protocol type parameter vs direct protocol type

This is my playground code:
protocol A {
init(someInt: Int)
}
func direct(a: A) {
// Doesn't work
let _ = A.init(someInt: 1)
}
func indirect<T: A>(a: T) {
// Works
let _ = T.init(someInt: 1)
}
struct B: A {
init(someInt: Int) {
}
}
let a: A = B(someInt: 0)
// Works
direct(a: a)
// Doesn't work
indirect(a: a)
It gives a compile time error when calling method indirect with argument a. So I understand <T: A> means some type that conforms to A. The type of my variable a is A and protocols do not conform to themselfs so ok, I understand the compile time error.
The same applies for the compile time error inside method direct. I understand it, a concrete conforming type needs to inserted.
A compile time also arrises when trying to access a static property in direct.
I am wondering. Are there more differences in the 2 methods that are defined? I understand that I can call initializers and static properties from indirect and I can insert type A directly in direct and respectively, I can not do what the other can do. But is there something I missed?
The key confusion is that Swift has two concepts that are spelled the same, and so are often ambiguous. One of the is struct T: A {}, which means "T conforms to the protocol A," and the other is var a: A, which means "the type of variable a is the existential of A."
Conforming to a protocol does not change a type. T is still T. It just happens to conform to some rules.
An "existential" is a compiler-generated box the wraps up a protocol. It's necessary because types that conform to a protocol could be different sizes and different memory layouts. The existential is a box that gives anything that conforms to protocol a consistent layout in memory. Existentials and protocols are related, but not the same thing.
Because an existential is a run-time box that might hold any type, there is some indirection involved, and that can introduce a performance impact and prevents certain optimizations.
Another common confusion is understanding what a type parameter means. In a function definition:
func f<T>(param: T) { ... }
This defines a family of functions f<T>() which are created at compile time based on what you pass as the type parameter. For example, when you call this function this way:
f(param: 1)
a new function is created at compile time called f<Int>(). That is a completely different function than f<String>(), or f<[Double]>(). Each one is its own function, and in principle is a complete copy of all the code in f(). (In practice, the optimizer is pretty smart and may eliminate some of that copying. And there are some other subtleties related to things that cross module boundaries. But this is a pretty decent way to think about what is going on.)
Since specialized versions of generic functions are created for each type that is passed, they can in theory be more optimized, since each version of the function will handle exactly one type. The trade-off is that they can add code-bloat. Do not assume "generics are faster than protocols." There are reasons that generics may be faster than protocols, but you have to actually look at the code generation and profile to know in any particular case.
So, walking through your examples:
func direct(a: A) {
// Doesn't work
let _ = A.init(someInt: 1)
}
A protocol (A) is just a set of rules that types must conform to. You can't construct "some unknown thing that conforms to those rules." How many bytes of memory would be allocated? What implementations would it provide to the rules?
func indirect<T: A>(a: T) {
// Works
let _ = T.init(someInt: 1)
}
In order to call this function, you must pass a type parameter, T, and that type must conform to A. When you call it with a specific type, the compiler will create a new copy of indirect that is specifically designed to work with the T you pass. Since we know that T has a proper init, we know the compiler will be able to write this code when it comes time to do so. But indirect is just a pattern for writing functions. It's not a function itself; not until you give it a T to work with.
let a: A = B(someInt: 0)
// Works
direct(a: a)
a is an existential wrapper around B. direct() expects an existential wrapper, so you can pass it.
// Doesn't work
indirect(a: a)
a is an existential wrapper around B. Existential wrappers do not conform to protocols. They require things that conform to protocols in order to create them (that's why they're called "existentials;" the fact that you created one proves that such a value actually exists). But they don't, themselves, conform to protocols. If they did, then you could do things like what you've tried to do in direct() and say "make a new instance of an existential wrapper without knowing exactly what's inside it." And there's no way to do that. Existential wrappers don't have their own method implementations.
There are cases where an existential could conform to its own protocol. As long as there are no init or static requirements, there actually isn't a problem in principle. But Swift can't currently handle that. Because it can't work for init/static, Swift currently forbids it in all cases.

Argument labels for initialization parameters in Swift 3.1

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.

How to constrain function parameter's protocol's associated types

For fun, I am attempting to extend the Dictionary class to replicate Python's Counter class. I am trying to implement init, taking a CollectionType as the sole argument. However, Swift does not allow this because of CollectionType's associated types. So, I am trying to write code like this:
import Foundation
// Must constrain extension with a protocol, not a class or struct
protocol SingletonIntProtocol { }
extension Int: SingletonIntProtocol { }
extension Dictionary where Value: SingletonIntProtocol { // i.e. Value == Int
init(from sequence: SequenceType where sequence.Generator.Element == Key) {
// Initialize
}
}
However, Swift does not allow this syntax in the parameter list. Is there a way to write init so that it can take any type conforming to CollectionType whose values are of type Key (the name of the type used in the generic Dictionary<Key: Hashable, Value>)? Preferably I would not be forced to write init(from sequence: [Key]), so that I could take any CollectionType (such as a CharacterView, say).
You just have a syntax problem. Your basic idea seems fine. The correct syntax is:
init<Seq: SequenceType where Seq.Generator.Element == Key>(from sequence: Seq) {
The rest of this answer just explains why the syntax is this way. You don't really need to read the rest if the first part satisfies you.
The subtle difference is that you were trying to treat SequenceType where sequence.Generator.Element == Key as a type. It's not a type; it's a type constraint. What the correct syntax means is:
There is a type Seq such that Seq.Generator.Element == Key, and sequence must be of that type.
While that may seem to be the same thing, the difference is that Seq is one specific type at any given time. It isn't "any type that follows this rule." It's actually one specific type. Every time you call init with some type (say [Key]), Swift will create an entirely new init method in which Seq is replaced with [Key]. (In reality, Swift can sometimes optimize that extra method away, but in principle it exists.) That's the key point in understanding generic syntax.
Or you can just memorize where the angle-brackets go, let the compiler remind you when you mess it up, and call it day. Most people do fine without learning the type theory that underpins it.

Is Swift Pass By Value or Pass By Reference

I'm really new to Swift and I just read that classes are passed by reference and arrays/strings etc. are copied.
Is the pass by reference the same way as in Objective-C or Java wherein you actually pass "a" reference or is it proper pass by reference?
Types of Things in Swift
The rule is:
Class instances are reference types (i.e. your reference to a class instance is effectively a pointer)
Functions are reference types
Everything else is a value type; "everything else" simply means instances of structs and instances of enums, because that's all there is in Swift. Arrays and strings are struct instances, for example. You can pass a reference to one of those things (as a function argument) by using inout and taking the address, as newacct has pointed out. But the type is itself a value type.
What Reference Types Mean For You
A reference type object is special in practice because:
Mere assignment or passing to function can yield multiple references to the same object
The object itself is mutable even if the reference to it is a constant (let, either explicit or implied).
A mutation to the object affects that object as seen by all references to it.
Those can be dangers, so keep an eye out. On the other hand, passing a reference type is clearly efficient because only a pointer is copied and passed, which is trivial.
What Value Types Mean For You
Clearly, passing a value type is "safer", and let means what it says: you can't mutate a struct instance or enum instance through a let reference. On the other hand, that safety is achieved by making a separate copy of the value, isn't it? Doesn't that make passing a value type potentially expensive?
Well, yes and no. It isn't as bad as you might think. As Nate Cook has said, passing a value type does not necessarily imply copying, because let (explicit or implied) guarantees immutability so there's no need to copy anything. And even passing into a var reference doesn't mean that things will be copied, only that they can be if necessary (because there's a mutation). The docs specifically advise you not to get your knickers in a twist.
Everything in Swift is passed by "copy" by default, so when you pass a value-type you get a copy of the value, and when you pass a reference type you get a copy of the reference, with all that that implies. (That is, the copy of the reference still points to the same instance as the original reference.)
I use scare quotes around the "copy" above because Swift does a lot of optimization; wherever possible, it doesn't copy until there's a mutation or the possibility of mutation. Since parameters are immutable by default, this means that most of the time no copy actually happens.
It is always pass-by-value when the parameter is not inout.
It is always pass-by-reference if the parameter is inout. However, this is somewhat complicated by the fact you need to explicitly use the & operator on the argument when passing to an inout parameter, so it may not fit the traditional definition of pass-by-reference, where you pass the variable directly.
Here is a small code sample for passing by reference.
Avoid doing this, unless you have a strong reason to.
func ComputeSomeValues(_ value1: inout String, _ value2: inout Int){
value1 = "my great computation 1";
value2 = 123456;
}
Call it like this
var val1: String = "";
var val2: Int = -1;
ComputeSomeValues(&val1, &val2);
The Apple Swift Developer blog has a post called Value and Reference Types that provides a clear and detailed discussion on this very topic.
To quote:
Types in Swift fall into one of two categories: first, “value types”,
where each instance keeps a unique copy of its data, usually defined
as a struct, enum, or tuple. The second, “reference types”, where
instances share a single copy of the data, and the type is usually
defined as a class.
The Swift blog post continues to explain the differences with examples and suggests when you would use one over the other.
When you use inout with an infix operator such as += then the &address symbol can be ignored. I guess the compiler assumes pass by reference?
extension Dictionary {
static func += (left: inout Dictionary, right: Dictionary) {
for (key, value) in right {
left[key] = value
}
}
}
origDictionary += newDictionaryToAdd
And nicely this dictionary 'add' only does one write to the original reference too, so great for locking!
Classes and structures
One of the most important differences between structures and classes is that structures are always copied when they are passed around in your code, but classes are passed by reference.
Closures
If you assign a closure to a property of a class instance, and the closure captures that instance by referring to the instance or its members, you will create a strong reference cycle between the closure and the instance. Swift uses capture lists to break these strong reference cycles
ARC(Automatic Reference Counting)
Reference counting applies only to instances of classes. Structures and enumerations are value types, not reference types, and are not stored and passed by reference.
Classes are passed by references and others are passed by value in default.
You can pass by reference by using the inout keyword.
Swift assign, pass and return a value by reference for reference type and by copy for Value Type
[Value vs Reference type]
If compare with Java you can find matches:
Java Reference type(all objects)
Java primitive type(int, bool...) - Swift extends it using struct
struct is a value type so it's always passed as a value. let create struct
//STEP 1 CREATE PROPERTIES
struct Person{
var raw : String
var name: String
var age: Int
var profession: String
// STEP 2 CREATE FUNCTION
func personInformation(){
print("\(raw)")
print("name : \(name)")
print("age : \(age)")
print("profession : \(profession)")
}
}
//allow equal values
B = A then call the function
A.personInformation()
B.personInformation()
print(B.name)
it have the same result when we change the value of 'B' Only Changes Occured in B Because A Value of A is Copied, like
B.name = "Zainab"
a change occurs in B's name. it is Pass By Value
Pass By Reference
Classes Always Use Pass by reference in which only address of occupied memory is copied, when we change similarly as in struct change the value of B , Both A & B is changed because of reference is copied,.