Formally, perhaps the proposal should include the following: 1. Missing type parameters are assumed to be implicit and trailing (as in the particular case of all type parameters missing).
2. _ is allowed as a placeholder when specifying explicit parameters in a function call. The corresponding parameter is assumed to be implicit. In addition to this, and following the discussion on the unsafeBitCast example, it might be a good idea to incorporate to the proposal adding an (optional) explicit keyword for type parameters in generic function definitions: func unsafeBitCast<explicit U, T>(_ x: T) -> U foo(unsafeBitCast(something)) // error: explicit type parameter required foo(unsafeBitCast<U>(something)) // ok Regards, Ramiro On Thu, 1 Dec 2016 at 01:36 Ramiro Feria Purón <[email protected]> wrote: > Or perhaps in a more "swifty" way, use _ for implicit type parameters, > i.e.: > > f<_,T>() > > On Thu, 1 Dec 2016 at 01:13 Ramiro Feria Purón < > [email protected]> wrote: > > Douglas, > > Regarding the question on the restriction for type parameters to appear on > the signature, the answer is remain. The proposal does not intend this > restriction to be lifted. > > One might expect to find a few legitimate cases where having it lifted > would be handy or desirable. They seem to emerge often, for example, > while developing components using Core Data. From a real case scenario: > > protocol Activable { var dateLastActive: Date { get } } > > > class A: NSManagedObject {} > > class B: NSManagedObject {} > > //.. > > class Z: NSManagedObject {} > > > extension A: Activable { var dateLastActive: Date { return Date() } } > > extension B: Activable { var dateLastActive: Date { return Date() } } > > //.. > > extension Z: Activable { var dateLastActive: Date { return Date() } } > > > > > func deleteInactiveObjects<T: NSManagedObject>(since date: Date, > inContext context: NSManagedObjectContext) where T: Activable { > > //.. > > } > > > // for the sake of the example > > let context = NSManagedObjectContext(concurrencyType: . > privateQueueConcurrencyType) > > let yesterday = Date() > > let oneWeekAgo = Date() > > > > deleteInactiveObjects<A>(since: yesterday, inContext: context) > > deleteInactiveObjects<B>(since: oneWeekAgo, inContext: context) > > //.. > > (here again, as you mention, the parameter affects how the function > operates, yet it is not part of the signature) > > If the restriction was lifted, however, it would also be in detriment of > the educational value of the proposal (apart from your arguments above). When > defining a generic function, it feels natural to expect all of the type > parameters to be present in the generic function signature. Relaxing this > rule could be perceived by the novice as an invitation to an obscure > design. In the best case, it would generate doubts about its actual intent. > > From a pedagogical perspective, the proposal aims to save Swift from > disappointment when this topic is brought to discussion, say whether at the > end of a Programming or a Compilers undergraduate course -- albeit fully > understanding (or implementing) the current alternatives could be an > excellent exercise for the class. > > From the (primary) language and development perspective, I don't think it > could be expressed in a better way than in your lines, which are truly > appreciated: > > "*That’s how I see this proposal: not as a replacement for the metatype > parameter idiom that unsafeBitCast uses, but as a way to be more explicit > at particular call sites when type inference either fails (e.g., due to > lack of contextual type information), produces a result different than what > is desired, or is sufficiently complicated that the call site requires more > documentation.*" > > Finally, we should also consider the possibility of being explicit about > some but not all type parameters. If allowed, something like "only trailing > type parameters could be missing" would be necessary to avoid ambiguity. > > All the best, > Ramiro > > > On Tue, 29 Nov 2016 at 17:11 Douglas Gregor <[email protected]> wrote: > > > On Nov 21, 2016, at 3:05 PM, Ramiro Feria Purón via swift-evolution < > [email protected]> wrote: > > *Problem:* > > Currently, it is not possible to be explicit about the generic parameters > (type parameters) in a generic function call. Type parameters are inferred > from actual parameters: > > func f<T>(_ t: T) { > > > //.. > } > > f(5) // T inferred to be Int > f("xzcvzxcvx") // T inferred to be string > > If no type parameter is involved in the formal parameters, the type > parameter needs to be used somehow as part of the return type. For example: > > func g<T>(_ x: Int) -> [T] { > > > var result: [T] = [] > > > //.. > > > return result > } > > In such cases, the type parameters must be inferrable from the context: > > g(7) // Error: T cannot be inferred > let array = g(7) // Error: T cannot be inferred > > let array: [String] = g(7) // Ok: T inferred to be String > let array = g<String>(7) // Error: Cannot explicitly specialise > generic function > > > > *Proposed Solution:* > > Allow explicit type parameters in generic function call: > > let _ = g<String>(7) // Ok > > > > *Motivation:* > > Consider the following contrived example: > > class Vehicle { > var currentSpeed = 0 > //.. > } > > class Bicycle: Vehicle { > //.. > } > > class Car: Vehicle { > //.. > } > > @discardableResult > func processAll<T: Vehicle>(in vehicles: [Vehicle], condition: (Vehicle) > -> Bool) -> [T] { > > > var processed: [T] = [] > > > for vehicle in vehicles { > guard let t = vehicle as? T, condition(vehicle) else { continue } > //.. > processed.append(t) > } > > > return processed > > } > > func aboveSpeedLimit(vehicle: Vehicle) -> Bool { > return vehicle.currentSpeed >= 100 > > } > > > let processedVehicles = processAll(in: vehicles, condition: > aboveSpeedLimit) // Uh, T inferred to be Vehicle! > > let processedCars: [Car] = processAll(in: vehicles, condition: > aboveSpeedLimit) // T inferred to be Car > > processAll<Bicycle>(in: vehicles, condition: aboveSpeedLimit) > // This should be allowed under this proposal > > > *Notes:* > > If necessary, the (real life) Swift code that lead to the proposal could > be shared. > > > This seems completely reasonable to me. I had always expected us to > implement this feature, but we never got around to it, and it wasn’t a high > priority because one can always use type inference. Additionally, there > were a few places where we originally thought we wanted this feature, but > prefer the more-explicit form where the user is required to explicitly pass > along a metatype. unsafeBitCast is one such case: > > func unsafeBitCast<T, U>(_ x: T, to: U.Type) -> U > > Even if we had the ability to provide explicit type arguments, we would > *not* want to change this signature to > > func unsafeBitCast<U, T>(_ x: T) -> U // bad idea > > because while it makes the correct usage slightly cleaner: > > unsafeBitCast<Int>(something) // slightly prettier, but... > > it would enable type inference to go wild with unsafe casts: > > foo(unsafeBitCast(something)) // just cast it to.. whatever > > which is… not great. > > I’d like one bit of clarification in the proposal. Right now, one is not > permitted to have a type parameter in a generic function that isn’t used > somewhere in its signature, e.g., > > func f<T>() -> Void { … } // error: T is not part of the signature of f() > > This restriction is obvious in today’s Swift, because there is absolutely > no way one could ever use this function. With your proposed extension, it > would be possible to use this function. Does the restriction remain or is > it lifted? > > Personally, I’d like the restriction to stay, because it feels like such > functions fall into the same camp as unsafeBitCast: if the type parameter > affects how the function operates but is *not* part of its signature, then > it should be expressed like a normal parameter (of a metatype). It also > helps provide better diagnostics when changing a generic function to no > longer require one of its type parameters. > > And, as Dave notes, it’s effectively syntactic sugar, so it belongs in > Swift 4 stage 2. > > - Doug > > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
