[swift-users] Swift alternative for heterogeneous collection of objects with "generic" contents.

2017-06-29 Thread Mikhail Seriukov via swift-users
Hello everyone,
In objc there is quite common pattern when we use a base class with a type
property and concrete subclasses where type is uniquely identifying the
subclass.
We can then safely put subclasses objects into an array and then safely
downcast them when needed.
This kind of behaviour is commonly used in data sources implementations.

Like this:

typedef NS_ENUM(NSUInteger, CellDecriptorType) {
CellDecriptorTypeUnknown,
CellDecriptorType1,
CellDecriptorType2
};

@interface BaseCellDescriptor : NSObject

@property (nonatomic, readonly) CellDecriptorType type;
@property (nonatomic, strong) id value;

@end


@interface CellDescriptor1 : BaseCellDescriptor
@end

@implementation CellDescriptor1

- (CellDecriptorType)type {
return CellDecriptorType1;
}

- (NSString *)value {
return @"string value";
}

@end


@interface CellDescriptor2 : BaseCellDescriptor
@end

@implementation CellDescriptor2

- (CellDecriptorType)type {
return CellDecriptorType2;
}

- (NSNumber *)value {
return @42;
}

@end

And somewhere later we do:

- (void)doWorkWithCellDescriptors:(NSArray
*)descriptors {
for (BaseCellDescriptor *descriptor in descriptors) {
CellDecriptorType type = descriptor.type;
switch(type) {
case CellDecriptorType1: {
CellDescriptor1 *aDescriptor = (CellDescriptor1
*)descriptor;
NSString *value = aDescriptor.value;
// Do something with value
break;
}
case CellDecriptorType2: {
CellDescriptor2 *aDescriptor = (CellDescriptor2
*)descriptor;
NSNumber *value = aDescriptor.value;
// Do something with value
break;
}
case CellDecriptorTypeUnknown:
default: {
// Handle error
break;
}
}
}
}


I want to implement it swifty way. So the questions are:
0. Is it a bad practice to use this pattern and how we can avoid it?
1. Is it possible to avoid inheritance here and only use generic protocols
and how?
2. Is it possible to avoid downcasting if using this pattern in swift?


I've found the solution that seems to be a good example in this project
https://github.com/xmartlabs/Eureka.
They maintain both inheritance hierarchy and protocol hierarchy.

3. Is it a good practice to implement such tasks like in Eureka project,
what are the pros and cons of it?

Thanks for your time!
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Weird protocol behaviour.

2016-12-30 Thread Mikhail Seriukov via swift-users
So as the *foo(_ x:A) *function is generic, when we call *foo(x) *compiler
needs to determine what type is *A *to be able to create concrete function.
But x defined as *let x = X() as P *so we only know about it that it
conforms to *P *but not its real type to put instead of *A*. Right?
But where is the "Protocols do not conform to themselves" limitation is
coming out?

2016-12-30 18:25 GMT+07:00 Rien :

>
> > On 30 Dec 2016, at 12:14, Mikhail Seriukov via swift-users <
> swift-users@swift.org> wrote:
> >
> > Ok,
> > But I think I still do not get it.
> > What does really happen when we write this?
> >> let x = X() as P
> >>
>
> 'X()' creates a value.
> 'as P’ constrains the value such that the only things we know about it is
> that the value will conform to the protocol P
> ‘let x =‘ assigns the value to a constant, and the only thing we know
> about that constant is that we can call an operation of protocol P on it.
>
> Rien.
>
> > As I said, I expect x to be Any after that. If it is, then it should
> be ok IMO.
> > But if it is not then what is the actual type of x?
> >
> > So the real question is how the type checker works here?
> >
> >
> > 2016-12-25 22:13 GMT+07:00 Slava Pestov :
> >
> >> On Dec 22, 2016, at 4:43 PM, Howard Lovatt via swift-users <
> swift-users@swift.org> wrote:
> >>
> >> The following variation works:
> >>
> >> protocol P {}
> >>
> >> class P1:P {}
> >>
> >> class X:P1 {}
> >>
> >> func foo(_ x:A) {}
> >>
> >> func bar() {
> >> //let x = X() // this compiles
> >> let x = X() as P1 // this does not compile. Why?
> >> foo(x)
> >> }
> >>
> >> Which adds credence to the bug theory.
> >
> > It’s an intentional limitation. Protocols do not conform to themselves.
> Lifting the restriction would be difficult to do efficiently given our
> representation of generics and protocols at runtime.
> >
> > Slava
> >
> >>
> >> Note two changes: 1. two levels of inheritance and 2. change to
> classes. If you do two levels using protocols it doesn't work if you use
> either classes or structs.
> >>
> >>
> >>   -- Howard.
> >>
> >> On 23 December 2016 at 07:29, Kevin Nattinger 
> wrote:
> >> I recall seeing a request on the -evolution list for something like `T
> := X` to indicate it could be X itself or anything inheriting /
> implementing it, so it’s certainly known behavior, if not desired. IMO it’s
> a bug and `:` should be fixed to include the root type, whether or not that
> requires a discussion on -evolution.
> >>
> >>> On Dec 22, 2016, at 2:17 PM, Howard Lovatt via swift-users <
> swift-users@swift.org> wrote:
> >>>
> >>> I suspect a compiler bug since A is a P. The equivalent in Java works:
> >>>
> >>> interface P {}
> >>> class X implements P {}
> >>>
> >>>  void foo(A x) {}
> >>>
> >>> void bar() {
> >>> final P x = new X();
> >>> foo(x);
> >>> }
> >>>
> >>> -- Howard.
> >>>
> >>> On 23 Dec 2016, at 3:19 am, Rien via swift-users <
> swift-users@swift.org> wrote:
> >>>
> >>>> IMO the error message says it all:
> >>>>
> >>>> Playground execution failed: error: MyPlayground8.playground:9:5:
> error: cannot invoke 'foo' with an argument list of type '(P)'
> >>>>foo(x)
> >>>>^
> >>>>
> >>>> MyPlayground8.playground:9:5: note: expected an argument list of type
> '(A)'
> >>>>foo(x)
> >>>>^
> >>>>
> >>>> I.e. you are passing in a protocol while the function is specified
> for a type.
> >>>> Said other way: On which data do you expect the protocol to operate?
> >>>>
> >>>> Regards,
> >>>> Rien
> >>>>
> >>>> Site: http://balancingrock.nl
> >>>> Blog: http://swiftrien.blogspot.com
> >>>> Github: http://github.com/Swiftrien
> >>>> Project: http://swiftfire.nl
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>> On 22 Dec 2016, at 17:05, Mikhail Seriukov via swift-users <
> swift-users@swift.org> wrote:
> >>>>>
> >>>>> 

Re: [swift-users] Weird protocol behaviour.

2016-12-30 Thread Mikhail Seriukov via swift-users
Ok,
But I think I still do not get it.
What does really happen when we write this?

let x = X() as P

As I said, I expect x to be Any after that. If it is, then it should be
ok IMO.
But if it is not then what is the actual type of x?

So the real question is how the type checker works here?


2016-12-25 22:13 GMT+07:00 Slava Pestov :

>
> On Dec 22, 2016, at 4:43 PM, Howard Lovatt via swift-users <
> swift-users@swift.org> wrote:
>
> The following variation works:
>
> protocol P {}
>
> class P1:P {}
>
> class X:P1 {}
>
> func foo(_ x:A) {}
>
> func bar() {
> //let x = X() // this compiles
> let x = X() as P1 // this does not compile. Why?
> foo(x)
> }
>
> Which adds credence to the bug theory.
>
>
> It’s an intentional limitation. Protocols do not conform to themselves.
> Lifting the restriction would be difficult to do efficiently given our
> representation of generics and protocols at runtime.
>
> Slava
>
>
> Note two changes: 1. two levels of inheritance and 2. change to classes.
> If you do two levels using protocols it doesn't work if you use either
> classes or structs.
>
>
>   -- Howard.
>
> On 23 December 2016 at 07:29, Kevin Nattinger  wrote:
>
>> I recall seeing a request on the -evolution list for something like `T :=
>> X` to indicate it could be X itself or anything inheriting / implementing
>> it, so it’s certainly known behavior, if not desired. IMO it’s a bug and
>> `:` should be fixed to include the root type, whether or not that requires
>> a discussion on -evolution.
>>
>> On Dec 22, 2016, at 2:17 PM, Howard Lovatt via swift-users <
>> swift-users@swift.org> wrote:
>>
>> I suspect a compiler bug since A is a P. The equivalent in Java works:
>>
>> interface P {}
>> class X implements P {}
>>
>>  void foo(A x) {}
>>
>> void bar() {
>> final P x = new X();
>> foo(x);
>> }
>>
>> -- Howard.
>>
>> On 23 Dec 2016, at 3:19 am, Rien via swift-users 
>> wrote:
>>
>> IMO the error message says it all:
>>
>> Playground execution failed: error: MyPlayground8.playground:9:5: error:
>> cannot invoke 'foo' with an argument list of type '(P)'
>>foo(x)
>>^
>>
>> MyPlayground8.playground:9:5: note: expected an argument list of type
>> '(A)'
>>foo(x)
>>^
>>
>> I.e. you are passing in a protocol while the function is specified for a
>> type.
>> Said other way: On which data do you expect the protocol to operate?
>>
>> Regards,
>> Rien
>>
>> Site: http://balancingrock.nl
>> Blog: http://swiftrien.blogspot.com
>> Github: http://github.com/Swiftrien
>> Project: http://swiftfire.nl
>>
>>
>>
>>
>> On 22 Dec 2016, at 17:05, Mikhail Seriukov via swift-users <
>> swift-users@swift.org> wrote:
>>
>>
>> Hello community! I' wondering if somebody can explain this to me.
>>
>> Please take look at the snippet.
>>
>>
>> protocol P {}
>>
>> struct X:P {}
>>
>>
>> func foo(_ x:A) {}
>>
>>
>> func bar() {
>>
>>//let x = X() // this compiles
>>
>>let x = X() as P // this does not compile. Why?
>>
>>foo(x)
>>
>> }
>>
>>
>> I expect the both cases to work though. But only first works? And I do
>> not understand why.
>>
>> My coworkers said that it is a compiler bug, but I'm not shure it is.
>>
>> Thanks for the help.
>>
>> ___
>>
>> swift-users mailing list
>>
>> swift-users@swift.org
>>
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>> ___
>> swift-users mailing list
>> swift-users@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>> ___
>> swift-users mailing list
>> swift-users@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>>
> ___
> swift-users mailing list
> swift-users@swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
>
>
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


Re: [swift-users] Weird protocol behaviour.

2016-12-23 Thread Mikhail Seriukov via swift-users
>
> No it does not.
> You have made a type out of the parameter. It’s no longer a protocol.
> IMO the failure here is to understand the difference between a type and a
> protocol.
> A type (even if empty) is always a combination of storage with functions
> (that are assumed to work on the data in storage)
> A protocol is just a definition of functions without the accompanying data.
>

I see your point.
But actually when I write it as  `let x = X() as P` I really mean that I
want `x` to be `AnyObject` but conforming to P, not just protocol itself.
Is it even possible to downcast it this way?

2016-12-23 14:51 GMT+07:00 Marinus van der Lugt :

>
> On 22 Dec 2016, at 22:43, Howard Lovatt  wrote:
>
> The following variation works:
>
> protocol P {}
>
> class P1:P {}
>
> class X:P1 {}
>
> func foo(_ x:A) {}
>
> func bar() {
> //let x = X() // this compiles
> let x = X() as P1 // this does not compile. Why?
> foo(x)
> }
>
> Which adds credence to the bug theory.
>
>
>
> No it does not.
> You have made a type out of the parameter. It’s no longer a protocol.
> IMO the failure here is to understand the difference between a type and a
> protocol.
> A type (even if empty) is always a combination of storage with functions
> (that are assumed to work on the data in storage)
> A protocol is just a definition of functions without the accompanying data.
>
> Rien.
>
>
>
>
> Note two changes: 1. two levels of inheritance and 2. change to classes.
> If you do two levels using protocols it doesn't work if you use either
> classes or structs.
>
>
>   -- Howard.
>
> On 23 December 2016 at 07:29, Kevin Nattinger  wrote:
>
>> I recall seeing a request on the -evolution list for something like `T :=
>> X` to indicate it could be X itself or anything inheriting / implementing
>> it, so it’s certainly known behavior, if not desired. IMO it’s a bug and
>> `:` should be fixed to include the root type, whether or not that requires
>> a discussion on -evolution.
>>
>> On Dec 22, 2016, at 2:17 PM, Howard Lovatt via swift-users <
>> swift-users@swift.org> wrote:
>>
>> I suspect a compiler bug since A is a P. The equivalent in Java works:
>>
>> interface P {}
>> class X implements P {}
>>
>>  void foo(A x) {}
>>
>> void bar() {
>> final P x = new X();
>> foo(x);
>> }
>>
>> -- Howard.
>>
>> On 23 Dec 2016, at 3:19 am, Rien via swift-users 
>> wrote:
>>
>> IMO the error message says it all:
>>
>> Playground execution failed: error: MyPlayground8.playground:9:5: error:
>> cannot invoke 'foo' with an argument list of type '(P)'
>>foo(x)
>>^
>>
>> MyPlayground8.playground:9:5: note: expected an argument list of type
>> '(A)'
>>    foo(x)
>>^
>>
>> I.e. you are passing in a protocol while the function is specified for a
>> type.
>> Said other way: On which data do you expect the protocol to operate?
>>
>> Regards,
>> Rien
>>
>> Site: http://balancingrock.nl
>> Blog: http://swiftrien.blogspot.com
>> Github: http://github.com/Swiftrien
>> Project: http://swiftfire.nl
>>
>>
>>
>>
>> On 22 Dec 2016, at 17:05, Mikhail Seriukov via swift-users <
>> swift-users@swift.org> wrote:
>>
>>
>> Hello community! I' wondering if somebody can explain this to me.
>>
>> Please take look at the snippet.
>>
>>
>> protocol P {}
>>
>> struct X:P {}
>>
>>
>> func foo(_ x:A) {}
>>
>>
>> func bar() {
>>
>>//let x = X() // this compiles
>>
>>let x = X() as P // this does not compile. Why?
>>
>>foo(x)
>>
>> }
>>
>>
>> I expect the both cases to work though. But only first works? And I do
>> not understand why.
>>
>> My coworkers said that it is a compiler bug, but I'm not shure it is.
>>
>> Thanks for the help.
>>
>> ___
>>
>> swift-users mailing list
>>
>> swift-users@swift.org
>>
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>> ___
>> swift-users mailing list
>> swift-users@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>> ___
>> swift-users mailing list
>> swift-users@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>>
>
>
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users


[swift-users] Weird protocol behaviour.

2016-12-22 Thread Mikhail Seriukov via swift-users
Hello community! I' wondering if somebody can explain this to me.
Please take look at the snippet.

protocol P {}
struct X:P {}

func foo(_ x:A) {}

func bar() {
//let x = X() // this compiles
let x = X() as P // this does not compile. Why?
foo(x)
}

I expect the both cases to work though. But only first works? And I do not
understand why.
My coworkers said that it is a compiler bug, but I'm not shure it is.
Thanks for the help.
___
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users