> On Jun 3, 2016, at 1:36 PM, John McCall <[email protected]> wrote: > >> On Jun 2, 2016, at 6:48 PM, Matthew Johnson <[email protected] >> <mailto:[email protected]>> wrote: >> On Jun 2, 2016, at 6:51 PM, John McCall via swift-evolution >> <[email protected] <mailto:[email protected]>> wrote: >> >>>> On Jun 2, 2016, at 4:33 PM, Xiaodi Wu <[email protected] >>>> <mailto:[email protected]>> wrote: >>>> The IntegerLiteral type idea might be worth exploring. It does seem to >>>> provide some additional consistency. For example, wasn't it clarified on >>>> this list just recently that literals don't have a type and adopt one >>>> based on context? It'd be nice to point out that 42 is an IntegerLiteral >>>> when explaining that it's not an Int. >>> >>> I think that's a very promising way of thinking about literals. Writing a >>> literal creates a notional value whose type is the informal, >>> infinite-precise type of all integer/FP/collection/etc. literals, which (1) >>> can be implicitly converted to any type that implements the appropriate >>> protocol and (2) in fact *must* be converted to some such type (possibly >>> the default type for that literal) in order for the code to be executable. >>> You can then think about this proposal as saying that an explicit >>> conversion from that informal type to a literal-convertible type follows >>> the same path as an implicit conversion would have. >> >> It sounds like the reason you don't want to remove the label is because it >> distinguishes the literal initializer and you don't want it called with a >> variable accidentally right? >> >> What if we do something like this: >> >> init(_ value: IntegerLiteralType, literal: IntegerLiteral = #literal) >> >> The idea here is that the IntegerLiteral type and friends are special types >> that have no members and cannot be used except by the literal convertible >> protocols and their conformances. There is nothing you can do with the >> value at all. >> >> The trick is that by defaulting it to #literal we are indicating the >> compiler synthesizes the logical value, as with #file, #line, etc. The >> compiler would refuse to synthesize this value when a literal is not used. >> This means it is never selected when the user provides a variable to a >> converting initializer. If an independent initializer accepting a value of >> the same type also exists that would be selected. However, when a literal >> *is* used and the type conforms to the relevant literal convertible protocol >> the compiler always synthesized the value making it always the most specific >> overload. >> >> Of course no runtime value would actually exist. This is just a logical >> value marking the fact that a literal was used to call the initializer. >> >> This approach solves the same problem while retaining semantic consistency >> with the language (no label elision or short circuit of overload >> resolution). The magic is arguably a lot more restrained - types for which >> values can only be supplied by the compiler. We could artificially restrict >> usage of these types if we wanted to, but we wouldn't have to. Nothing >> could be accomplished by using the types anywhere else so nobody do so and >> it wouldn't be actively harmful to allow them to be used anywhere other >> types can be used. Only the ability to create values of the type needs to >> be restricted and we can already write types like that by marking the >> initializers private. >> >> Any thoughts on this approach? > > This is still a special-case type-checking rule, which means that it's still > basically my proposal except, instead of just rewriting the call to use a > labeled literal initializer, it rewrites the call to use a magic initializer > which cannot be used by users because it requires arguments that users cannot > create. I just don't understand the motivation here. It's not a simpler > language model to use, explain, or implement; it purports to be conceptually > simpler and less magical while actually inventing two magic new language > concepts (IntegerLiteral and #literal) on top of the same special cases.
I understand that this is still a special case and also that the implementation is pretty much identical. But I think the way it is presented to users is important. The motivation is to come up with a design that lets us implement your proposal without magically eliding a parameter label. There is no other case in Swift where you can directly call any function (initializer or otherwise) without including labels for all parameters that have external labels. Creating a special case to allow that here is inconsistent. Why wouldn’t look for a way to do this that treats the signature consistently with the rest of the language and is more in line with how we handle other compiler magic (i.e. #file, #line, etc)? I am not the only one who feels that way. Quoting Brent: "But if you're going to call `init(integerLiteral:)` like it's `init(_:)`, I don't think that's a good idea. Parameter labels are supposed to be significant; we don't want to lose that.” I agree with this. That is the motivation for my suggestion. I think it’s at least worth discussing as an alternative to magically allowing an external parameter label to be omitted. Brent, what do you think of my suggestion? > > Literals are always going to involve some magic behind the scenes. The > non-trivial literals, for example, all actually traffic through some sort of > builtin protocol (e.g. BuiltinIntegerLiteralConvertible) which cannot be > implemented by users and whose construction necessarily involves a private > API contract between the standard library and compiler that we reserve the > right to change at will without bringing in swift-evolution. All of the > supposedly simple explanations eventually reach, "okay, but if Int isn't a > special type, how does the literal turn into an Int in the first place", and > that is just unanswerable, because it turns out that standard library types > *are* actually special in the sense that they get to conform to > BuiltinIntegerLiteralConvertible and nobody else does. Understood. But Swift does a good job of making the magic feel consistent with the rest of the language. That’s a good thing. Allowing omission of a parameter label is a break from that IMO. I believe this is an important problem to solve but I also think we should try to find a way to solve it that doesn’t violate rules that apply everywhere else in the language (specifically regarding parameter labels). -Matthew > > John. > >> >>> >>> John. >>> >>>> >>>> On Thu, Jun 2, 2016 at 18:22 Brent Royal-Gordon via swift-evolution >>>> <[email protected] <mailto:[email protected]>> wrote: >>>> > So, you think that this syntax is enticing to new developers who >>>> > naturally think that the feature works the way that I'm proposing it >>>> > should work, and you think that the right solution is to make the syntax >>>> > illegal so that you can more conveniently tell them it doesn't work that >>>> > way? :) >>>> >>>> I think the difference between a cast (which merely reinterprets a value >>>> as a compatible type) and a fullwidth conversion (which creates a similar >>>> instance of an incompatible type) is very important to understanding how >>>> to write Swift, and we shouldn't muddy the waters by creating a magic >>>> syntax. >>>> >>>> > You can still tell them that it's a struct and you're calling an >>>> > initializer on it; it's just that the initializer chosen is the special >>>> > literal initializer because the argument is a literal. >>>> >>>> If you're planning to change `IntegerLiteralConvertible` and friends to >>>> require a fullwidth conversion initializer like `init(_ value: >>>> IntegerLiteralType)`, then this is simply an overload resolution rule. In >>>> that case, I think your proposal is fine. >>>> >>>> But if you're going to call `init(integerLiteral:)` like it's `init(_:)`, >>>> I don't think that's a good idea. Parameter labels are supposed to be >>>> significant; we don't want to lose that. >>>> >>>> -- >>>> Brent Royal-Gordon >>>> Architechies >>>> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] <mailto:[email protected]> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] <mailto:[email protected]> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
