uli
03/26/2019, 12:04 PMsvyatoslav.scherbina
03/26/2019, 12:18 PMkpgalligan
03/26/2019, 12:18 PMalex009
03/26/2019, 12:20 PMkpgalligan
03/26/2019, 12:20 PMkpgalligan
03/26/2019, 12:21 PMkpgalligan
03/26/2019, 12:21 PMalex009
03/26/2019, 12:21 PMkpgalligan
03/26/2019, 12:22 PMkpgalligan
03/26/2019, 12:23 PMkpgalligan
03/26/2019, 12:24 PMkpgalligan
03/26/2019, 12:24 PMalex009
03/26/2019, 12:25 PMkpgalligan
03/26/2019, 12:25 PMalex009
03/26/2019, 12:25 PMkpgalligan
03/26/2019, 12:35 PMsvyatoslav.scherbina
03/26/2019, 12:38 PM*
). So it doesnât seem to be possible to provide perfect interop support for generics.
@alex009 how do you use generics? Do you use generic interfaces, `in`/`out`/`*` in your public API to be consumed by Swift source?kpgalligan
03/26/2019, 12:42 PMkpgalligan
03/26/2019, 12:44 PMkpgalligan
03/26/2019, 12:45 PMkpgalligan
03/26/2019, 12:48 PMrusshwolf
03/26/2019, 12:54 PMSo it doesnât seem to be possible to provide perfect interop support for generics.Kotlin and Java treat generics differently as well, but they still interop fine and there's annotations you can use if you need fine-grained control. Something similar for Swift would be huge. Lack of generics support is a huge pain-point for convincing iOS developers to use Kotlin right now.
svyatoslav.scherbina
03/26/2019, 1:03 PMKotlin and Java treat generics differently as well, but they still interop fineThe difference is that in Java you can represent Kotlin concepts like generics variance by using wildcards. How do you suggest to import
Foo<out Bar>
to Swift?kpgalligan
03/26/2019, 1:05 PMFoo<Bar>
You lose the variance. The big question is, can you cast around that when you absolutely have to, and the answer seems to be yes. Alternatively, is it better to have no generic info in that case? Those I think are the two big questions here.kpgalligan
03/26/2019, 1:07 PMkpgalligan
03/26/2019, 1:10 PMabstract class Query<out RowType : Any>
from sqldelight. The variance exists to define more how this class is used, but in almost all cases, it doesnât need to be. The class is returning the type defined in the generic. However, from a readability standpoint in swift, this is pretty useful.kpgalligan
03/26/2019, 1:11 PMfun executeAsList(): List<RowType>
, fun executeAsOne(): RowType
, etc.kpgalligan
03/26/2019, 1:15 PMid
, or to Swift Any?
. However, having some info, and being aware of what does/doesnât interop well is useful. My opinion, though. Feedback would be good.russhwolf
03/26/2019, 1:26 PMkpgalligan
03/26/2019, 1:34 PMsvyatoslav.scherbina
03/26/2019, 1:46 PMIf, for example, you have a nullable generic, but return a list, the type defined in the list generic isUnfortunately, this is required since Objective-C collections canât contain, or to Swiftid
.Any?
null
, and Kotlin follows here the convention to use NSNull
instead. And id
is used as a common supertype.
if you decide this is something youâre going to work on, please let me know and Iâll stop đ For now Iâm going to see where it goes.I consider working on this somewhat later. I would really appreciate opinions from the community on how should we handle edge cases to cover common patterns and existing code.
kpgalligan
03/26/2019, 1:48 PMkpgalligan
03/26/2019, 1:50 PMsvyatoslav.scherbina
03/26/2019, 1:51 PMhow should we handle edge casesParticularly, as Iâve already mentioned above: ⢠How to represent
class Foo<in/out T>
? Should we erase its type parameter or make it invariant?
⢠How to represent type Foo<in/out T>
? Should we erase the type to Objective-C Foo *
?
⢠How to represent type Foo<*>
? Foo<upperBound>*
or Foo*
?svyatoslav.scherbina
03/26/2019, 1:52 PMkpgalligan
03/26/2019, 1:55 PMkpgalligan
03/26/2019, 1:58 PMsvyatoslav.scherbina
03/26/2019, 1:58 PMbasher
03/26/2019, 1:59 PMkpgalligan
03/26/2019, 1:59 PMbasher
03/26/2019, 1:59 PMkpgalligan
03/26/2019, 1:59 PMkpgalligan
03/26/2019, 2:00 PMsvyatoslav.scherbina
03/26/2019, 2:01 PMFoo<Bar>() as! Foo<Any>
. This may work ok while we use Objective-C classes but definitely wouldnât if interop with Swift was direct.kpgalligan
03/26/2019, 2:02 PMkpgalligan
03/26/2019, 2:04 PMkpgalligan
03/26/2019, 2:04 PMkpgalligan
03/26/2019, 2:05 PMsvyatoslav.scherbina
03/26/2019, 2:07 PMWhile I have attention of an audience, does Objc generics support multiple constraints, and what is the syntax?Does this make a trick?
@protocol Foo
@end;
@protocol Bar
@end;
@interface Baz : NSObject
@end;
@interface Test<T : Baz <Foo, Bar> * >
@end;
svyatoslav.scherbina
03/26/2019, 2:10 PMâFoo<Bar>() as! Foo<Any>â are you sure that wouldnât work?I mean that this doesnât work in pure Swift:
class Foo {}
class Test<T> {}
Test<Foo>() as! Test<Any>
So I suppose this will likely be a problem with direct Swift interop.kpgalligan
03/26/2019, 2:10 PMsvyatoslav.scherbina
03/26/2019, 2:13 PMTest<out Foo>
as Test<Foo>
đ
This would work for now, but Iâm not sure it is ok with direct Swift interop.
In fact, direct Swift interop appears to be somewhat less suitable for generics support ÂŻ\_(ă)_/ÂŻkpgalligan
03/26/2019, 2:14 PMkpgalligan
03/26/2019, 2:15 PMgildor
03/26/2019, 2:25 PMkpgalligan
03/26/2019, 2:25 PMEllen Shapiro
03/26/2019, 3:28 PMkpgalligan
03/26/2019, 3:31 PMivan.savytskyi
03/26/2019, 6:53 PMivan.savytskyi
03/26/2019, 9:30 PMSwift's generic is invariance
why we canât as temp solution just drop variance in/out
? When exporting objc headerskpgalligan
03/26/2019, 9:32 PMivan.savytskyi
03/26/2019, 9:44 PMsvyatoslav.scherbina
03/27/2019, 7:55 AMFoo<out Bar>
is (formally speaking) a union of all Foo<T>
where T : Bar
. Kotlin has exact type for it, Swift doesnât, so we have to use some approximation, e.g. common supertype. If class Foo<T> : Base
, then Base
is most common supertype for all these types.
Declaration-site variant generics (e.g. class Holder<out T>
) have to be erased completely (so Holder
wouldnât have generic parameters in Swift).
2)
Drop the variance now (so type Foo<out Bar>
becomes Foo<Bar>
, class Holder<out T>
becomes class Holder<T>
), but maybe apply 1) later, when implementing direct interop with Swift, thus breaking existing code and making it ugly,kpgalligan
03/27/2019, 11:21 AMkpgalligan
03/29/2019, 5:50 PMkpgalligan
03/29/2019, 5:54 PMalex009
03/31/2019, 4:10 PMkpgalligan
03/31/2019, 4:33 PMkpgalligan
03/31/2019, 4:34 PMkpgalligan
03/31/2019, 4:48 PMkpgalligan
03/31/2019, 4:48 PMkpgalligan
03/31/2019, 4:49 PMkpgalligan
03/31/2019, 4:51 PMkpgalligan
03/31/2019, 4:53 PMkpgalligan
03/31/2019, 4:53 PMkpgalligan
03/31/2019, 4:59 PMkpgalligan
03/31/2019, 4:59 PMalex009
04/01/2019, 1:18 AMkpgalligan
04/01/2019, 1:21 AMid
in Objc, but it looks like casting rules for Swift->Objc interop are pretty loose.kpgalligan
04/01/2019, 1:22 AMsvyatoslav.scherbina
04/03/2019, 8:03 AMout
-generics necessary for State.*
classes?alex009
04/03/2019, 9:25 AMState<User, Throwable>
svyatoslav.scherbina
04/03/2019, 9:33 AMon swift side will be good concrete type generic likeAnd this is still somewhat incorrect, as already discussed in this thread.State<User, Throwable>
alex009
04/03/2019, 9:37 AMsvyatoslav.scherbina
04/03/2019, 9:38 AMalex009
04/03/2019, 9:41 AMliveData: LiveData<State<User, String>>
and want to use it like liveData.observe { titleLable.text = $0.data?.firstName }
liveData.observe { errorLabel.text = $0.error }
kpgalligan
04/03/2019, 1:41 PMkpgalligan
04/03/2019, 1:44 PMkpgalligan
04/03/2019, 1:46 PMkpgalligan
04/03/2019, 1:48 PMkpgalligan
04/03/2019, 1:51 PMkpgalligan
04/03/2019, 1:52 PMpublic abstract class Enum<E : Enum<E>>
. Iâve simply disabled upper bounds for now, except as it relates to nullability.russhwolf
04/03/2019, 1:54 PMkpgalligan
04/03/2019, 2:27 PMkpgalligan
04/03/2019, 2:31 PMkpgalligan
04/03/2019, 2:36 PMyuya_horita
04/06/2019, 3:01 AMsvyatoslav.scherbina
04/08/2019, 8:17 AMkpgalligan
04/08/2019, 1:04 PMkpgalligan
04/08/2019, 2:56 PMsvyatoslav.scherbina
04/09/2019, 11:27 AM