swift closure cannot override Any - ios

Maybe it's a stupid question, but I couldn't find any solutions yet. So, my problem is, that is have an event emitter protocol with a function like this:
mutating func on(eventName:String, action:((Any?)->())) {
//..
}
And I want to use it to inform the listeners whenever an event is triggered with some information. Access token for the "login" event for example.
appSessionHadler.on("login") { (weak data: String?) in
//...
}
And than I get an error, that I cannot invoke "on" with that argument list of type. Of course it works with Any:
appSessionHadler.on("login") { (weak data: Any?) in
//...
}
Everything conforms to Any, so I'm a but confused. Can someone explain this, please!
I could solve this with a Generic protocol, but it still frustrates me that it does not works like this.

You're making a promise the compiler can't keep. The on function is free to call action with any kind of data at all. But the function you passed only accepts String. What is the system supposed to do if on includes the following code (directly or indirectly):
action(1)
1 is not a String, so type safety would be broken. The compiler can't let you do that.
Another way to think about this is that on takes a function of type F, and you are passing a supertype of F rather than a subtype of F. String is a subtype of Any. But function parameters work in the reverse order. (String)->Void is a supertype of (Any)->Void. So this is the same as passing a variable of type Any to a function that requires String. Formally we say that functions are contravariant in their parameters and covariant in their return values. You can read more on that in Type Variance in Swift.
As you suspect, generics are the right answer here. Any is almost always the wrong tool. And Any? is one of the hardest types to work with in Swift, so I'd definitely avoid that one at all costs. (Optional is itself a subtype of Any, and Swift has automatic promotion to Optional, so it is very common when you have Any? to start getting double Optionals and worse.)

Related

Dart generics not reified as per the docs

I'm trying to pass a type in order to make use of the type information, but that types doesn't appear to be pass through.
I went back to the docs to double check that Dart generics are in fact reified and according to the docs, they are:
I call hydrate on a response which morphs the content of response object:
response.hydrate<BoqVO>();
I'm expecting T to be of type BoqVO:
class Response {
...
void hydrate<T>() {
print(T.runtimeType); // always prints _Type
if (T is BoqVO) {
print("IF");
} else {
print("ELSE"); // always goes into ELSE block
}
}
...
}
... but it's not.
Replacing response.hydrate<BoqVO>(); with response.hydrate(new BoqVO()); and changing the method signature to
void hydrate(T t) {
works if i now use lowercase t, but one shouldn't have to instantiate the object in order for reified generics to be available.
Any ideas why Dart is doing this or what i'm missing for reified generics to work correctly?
PS: I'm not on Dart 2 yet, currently on Dart 1.24.3
As Günther Zöchbauer has said, the type parameter doesn't work in Dart 1.24.
The following explains what would happen if you tried the same code in Dart 2.0, where it would also not work, because it uses the type parameter incorrectly.
The code T.runtimeType treats T as an expression. When a type, including a type parameter, is used as an expression, it evaluates to an instance of the class Type. What you print is the runtime type of that Type object (where _Type is an internal platform implementation of Type).
To print the real type, just print(T) (that still converts T to a Type object, but one representing the type BoqVO and with a toString that includes the BoqVO name).
Likewise for T is BoqVO, you evaluate T to a Type object, and since Type doesn't implement BoqVO, that test is always false. There is no simple way to test if the type of a type parameter implements a specific other type, but you can hack around it as <T>[] is List<BoqVO>.
Generic collections were supported from the beginning and they got some type support, but generic methods were only experimental in Dart 1 and reified type parameters were only added in Dart 2 pre releases.

Function that accepts sequence of type

I want a function that accepts a sequence of Int. Here is what I want to write:
func process(items: Sequence<Int>) {
items.forEach { ... }
}
Error: "Cannot specialize non-generic type 'Sequence'".
Corrected (I think):
func process<S: Sequence>(items: S) where S.Iterator.Element == Int {
items.forEach { ... }
}
Quite a bit more verbose.
I know that the Sequence protocol has an associated type of Iterator which has Element. But I'm not quite sure why I have to resolve the Int requirement in such a weird way.
What are the underlying concepts that make the first version not work but the second? What does the error mean?
Your question is to do with the difference between generic types and associated types. See here (sections titled "Generic Types", "Associated Types") for a basic explanation of their purposes in Swift. Protocols, like Sequence, use associated types, rather than generic types. Your first code sample would make sense if Sequence was a concrete class with a generic type - this difference should explain the error message.
As for why protocols use associated types, rather than generic types, see the top answer to this question. Essentially, though they seem to serve the same purpose, associated types are meant to be more flexible and descriptive, where generic types are about implementation. This makes your code sample more verbose, but overall, makes many code samples simpler.
In fact, from the Sequence source code, Sequence has an associated type Iterator, which conforms to the IteratorProtocol protocol, which in turn has its own associated type Element (which can be any type).
Why are you not using an array of Int?
func process(items: [Int]) {
items.forEach { ... }
}
You can use Variadic Parameters:
func process(items: Int...) {
items.forEach { (item) in
//do stuff with your 'item'
}
}

In Dart, do I annotate a function return value with dynamic or Object if I don't know it's type?

If I have a function that returns a value of an unknown type, do I use dynamic, representing any object, or Object, which is the ancestor of all other types?
The style guide discusses this question for parameters, but not for return values.
How should I annotate the return value and why?
Dart engineer Bob Nystrom writes:
Return types are an interesting twist on this problem. With parameter types, the guidelines are pretty straightforward:
If you use Object as a parameter type, you're saying "my method will safely accept any object and only use it for stuff like toString() that all objects support".
If you use dynamic (or nothing) as a parameter type, you're saying "Dart's type system can't easily express the type that I accept here" or "I didn't bother to annotate".
It's tricky to flip (1) around. For a return type, I guess Object would say "You better not call anything except toString() or other stuff all objects support before doing a type test yourself", where dynamic would I think mean "we can't easily annotate this so you and I better just know what we're doing".
The user would have to "cast" it to a specific type that they expect to see to avoid compiler warning and get an error earlier in checked mode.
For what it's worth, in many cases you wouldn't have to cast even if you return Object. Dart allows implicit downcasting when you initialize a local variable with a type annotation. So you can do:
Object foo() => 123;
main() {
int x = foo(); // Implicit downcast. No type warning.
}
I think in this case, I would probably do dynamic, though. I think that conveys "I don't know what type this returns, but you should" better than Object.

How do I typedef a function that returns another function of the same type?

I'm implementing a state machine in dart, and I'd like to have my state functions return other state functions, but
typedef State State(foo);
Gives me an error:
typedef 'State' illegally refers to itself
Is there any way to do this typedef? Obviously I could wrap it in a class or have it return Function, but I was hoping to do this with typedef.
Sorry, this is not allowed by the spec right now. You could open a feature request at http://dartbug.com/new
Using an object or returning Function, as you mention, would be the best ways to go right now.

Retrieve TProc from Generic Container

Just discovered something rather funny:
var
Queue : TQueue <TProc>;
MyProc : TProc;
...
MyProc := Queue.Dequeue;
I think you see what is intendend here. However, the compiler thinks I want to store the Queue.Dequeue method (type "procedure of object") in MyProc and reports an error
E2010 Incompatible Types: 'TProc' und 'Procedure of object'
The workaround I came up with goes like this
MyProc := TProc (Pointer (Queue.Dequeue));
Is there a more elegant solution?
There's a bit of syntactical ambiguity there about whether the name "Dequeue" refers to the function itself, or the function's return value. And since you're dealing with an anonymous method pointer which you can assign a normal function to, it's trying to interpret that as a function assignment, not a function result assignment. Casting it to a pointer is the wrong solution, as that would force the function assignment to go through, which would then cause all sorts of fun errors when you attempt to invoke MyProc.
The correct way to fix it is by removing the syntactical ambiguity. Put an empty parenthesis after Dequeue, so that the compiler is sure that you're calling the function and not simply referencing it by name, and then it'll work.
MyProc := Queue.Dequeue();
As Mason said, there's an ambiguity in the Delphi syntax. Where TFoo.Bar is a method, it's not clear that FooValue.Bar means to refer to the result of calling TFoo.Bar, or a method pointer (or reference) TFoo.Bar itself (with implied Self argument of FooValue).
In the comments of Mason's answer, Rob Kennedy seems to suggest that the compiler simply figure this out based on the types of everything involved. This isn't simple; the compiler already does a lot of work to figure out whether you mean to refer to a method pointer value or a method call. It actually parses expressions in a different way when the expected receiver is a method pointer (or reference, or function pointer) type. The effort is especially involved when overloads are brought into the picture: the compiler scans through every overload candidate and checks for method pointer types in every parameter position, and then parses arguments differently depending on whether or not that parameter position contains a function pointer in one of the overloads. Then, if an overload that expects a function pointer isn't matched, the compiler changes the parse tree from function pointer to method call. The overloading mechanism itself needs to figure out which to use when its doing value to parameter comparisons. It's pretty messy, and it would be great if we didn't make it messier.
A prefix-style operator like # or Addr() isn't much help in resolving this ambiguity, not least because functions may return function pointers, and so on; how many # do you need to inhibit implicit (no () necessary) calling to grab the right value out? So when anonymous methods were introduced, a change in the expression parsing was made: I introduced the possibility of using () to force an invocation.
You can read more about it here:
http://blog.barrkel.com/2008/03/odd-corner-of-delphi-procedural.html
and here:
http://blog.barrkel.com/2008/03/procedurally-typed-expressions-redux.html

Resources