Wow, you’re right. Look like this is a bug? The issue shows up in class 
definitions, not protocol definitions.  

This works:

protocol Selfie {
    static func retOne() -> Self
    static func retMany() -> Array<Self>
    static func retTuple() -> (Self, Int)
}

This doesn’t work:

class Selfie {
    required init() {}
    // Compiles
    static func retOne() -> Self {return self.init()}
    // Doesn't Compile
    static func retMany() -> Array<Self> { return [] }
    // Doesn't Compile
    static func retTuple() -> (Self, Int) { return (self.init(), 0) }
    
}

So Self in non-nominal types with class methods end up with the compiler error:

Error: 'Self' is only available in a protocol or as the result of a method in a 
class; did you mean ’Selfie’?

Can we get confirmation from anyone?



> On Jun 2, 2017, at 2:39 AM, Gwendal Roué <gwendal.r...@gmail.com> wrote:
> 
> Hello Zaid,
> 
> I don't know what prevents you from implementing your DAOs.
> 
> For an example of a library that uses them extensively, see 
> http://github.com/groue/GRDB.swift: <http://github.com/groue/GRDB.swift:>
> 
>     struct PointOfInterest {
>         var id: Int64?
>         var title: String?
>         var favorite: Bool
>         var coordinate: CLLocationCoordinate2D
>     }
> 
>     // (snip) adopt protocols that turn PointOfInterest in a "record"
> 
>     // Fetch from SQL
>     let pois = try PointOfInterest.fetchAll(db, "SELECT * FROM 
> pointOfInterests") // [PointOfInterest]
>     
>     // Fetch without SQL
>     let title = Column("title")
>     let favorite = Column("favorite")
>     let poi1 = try PointOfInterest.fetchOne(db, key: 1)                   // 
> PointOfInterest?
>     let pois = try PointOfInterest.fetchOne(db, keys: [1, 2, 3])          // 
> [PointOfInterest]
>     let paris = try PointOfInterest.filter(title == "Paris").fetchOne(db) // 
> PointOfInterest?
>     let favoritePois = try PointOfInterest                                // 
> [PointOfInterest]
>         .filter(favorite)
>         .order(title)
>         .fetchAll(db)
>     
>     // Insert, update, delete
>     var berlin = PointOfInterest(
>         id: nil,
>         title: "Berlin",
>         favorite: false,
>         coordinate: CLLocationCoordinate2DMake(52.52437, 13.41053))
>     try berlin.insert(db)
>     berlin.id // some value
>     berlin.favorite = true
>     try berlin.update(db)
>     try berlin.delete(db)
> 
> GRDB "records" work pretty well with structs, but also class hierarchies, 
> without any caveat.
> 
> Can you explain a little more your issue ?
> 
> Gwendal Roué
> 
> 
>> Le 2 juin 2017 à 11:18, Zaid Daghestani via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :
>> 
>> Greetings Swift Community,
>> 
>> Today I’m throwing out a pitch on freeing the shackles on Self. Self is a 
>> potentially significant tool that I am itching to implement in my patterns 
>> to make my code more concise, clear and intuitive.
>> 
>> Self, by far, is cherished by Data Models and ORM's, and particularly DAO 
>> <https://en.wikipedia.org/wiki/DAO> s (Ref. 1 for examples). There are a 
>> significant amount of patterns in which a base class’s methods are Self 
>> relevant and not generic relevant. Self being non-referrable in non-nominal 
>> types denies significant feature and pattern delivery such as DAO. And to 
>> deny implementation of a pattern as significant as DAO’s seems like a shot 
>> in the foot. Adding Self to non-nominal types brings Collections and Async 
>> to our class/protocol methods. A single query method returning a sync or 
>> likely async collection on my DataModel class will be used in about 80% of 
>> my app screens and 80% of my eerver API’s, almost all of the time. Hell this 
>> even applies to struct patterns as well.
>> 
>> Now, DAO’s can actually already currently be achieved via generics, see Ref. 
>> 2. This actually still a pretty good implementation, but Self is a 
>> significantly more true implementation of these patterns. Issues with the 
>> current generic pattern of Self relevancy in Swift is:
>> 1- Generic methods in the base class are a workaround to the lack of Self. 
>> The base class is not a class that implements generic patterns. It a base 
>> class that implements Self patterns. Self is more concise and intuitive in 
>> implementing a DAO or any other Self relevant base class.
>> 2- Self relevant patterns are distinct and not the same as Generic patterns. 
>> 3- In usage of a DAO, the generic pattern requires that the Left Hand Side 
>> be typed to collapse the generic. In the case of Self relevance, the 
>> particular class name is enough. Swift, being an inference language, would 
>> be truer with the Self system, and not the repetitive type declaration style 
>> of ObjC/Java that generics provide.
>> let friends = User.where("id IN %@", friendIds) // truer to Swift type 
>> inference
>> // vs.
>> let friends:[User] = User.where("id IN %@", friendIds) // Java/Objective-C 
>> style repetitive type declarations
>> 
>> Let’s break the chains on Self! It is extremely intuitive, and we are all 
>> going to use it
>> 
>> Peace!
>> 
>> Z
>> 
>> 
>> 
>> 
>> Ref 1: DAO patterns::
>> 
>> class DataModelObject  {
>>     
>>     /* One of the most significant use cases
>>      * Retrieving a queried on collection asynchronusly
>>      */
>>     class func `where`(_ predicate:String, _ args:CVarArg...) -> 
>> Promise<[Self]> {
>>         // querie
>>         return Promise(value: [[])
>>     }
>>     
>>     // some more examples
>> 
>>     // optional async get
>>     class func get(id:String) -> Promise<Self?> {
>>         return Promise(value:self.init(id:id))
>>     }
>>     
>>     // sync all collection
>>     class func all() -> [Self] {
>>         return []
>>     }
>>     // asynnchronous fetch
>>     class func allAsync() -> Promise<[Self]> {
>>         return Promise(value: [])
>>     }
>>     
>>     // in the case of RealmDB we have returns of Results<Self>, a lazy 
>> collection
>>     class func `where`(_ predication:NSPredicate) -> Results<Self> {
>>         return Results<self>()
>>     }
>> }
>> 
>> class User : DataMadelObject {
>>     dynamic var id:String = ""
>>     dynamic var name:String = ""
>> }
>> 
>> let friendIds = [1, 2, 3]
>> let friends = User.where("id IN %@", friendIds)
>> 
>> Ref 2: Currently implementable DAO
>> 
>> class DataModelObject  {
>>     
>>     /* One of the most significant use cases
>>      * Retrieving a queried on collection asynchronusly
>>      */
>>     class func `where`<T: DataModelObject>(_ predicate:String, _ 
>> args:CVarArg...) -> Promise<[T]> {
>>         // querie
>>         return Promise(value: [])
>>     }
>>     
>>     // some more examples
>>     // optional async get
>>     class func <T: DataModelObject>get(id:String) -> Promise<T?> {
>>         return Promise(value:self.init(id:id))
>>     }
>>     
>>     
>>     // sync all collection
>>     class func all<T: DataModelObject>() -> [T] {
>>         return []
>>     }
>>     // asynnchronous fetch
>>     class func allAsync<T: DataModelObject>() -> Promise<[T]> {
>>         return Promise(value: [])
>>     }
>>     
>>     // in the case of RealmDB we have returns of Results<Self>, a lazy 
>> collection
>>     class func `where`<T: DataModelObject>(_ predication:NSPredicate) -> 
>> Results<T> {
>>         return Results<T>()
>>     }
>> }
>> 
>> class User : DataMadelObject {
>>     dynamic var id:String = ""
>>     dynamic var name:String = ""
>> }
>> 
>> let friendIds = [1, 2, 3]
>> let friends:[User] = User.where("id IN %@", friendIds)
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to