> On Jun 2, 2016, at 6:48 PM, Matthew Johnson <matt...@anandabits.com> wrote:
> On Jun 2, 2016, at 6:51 PM, John McCall via swift-evolution 
> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
> 
>>> On Jun 2, 2016, at 4:33 PM, Xiaodi Wu <xiaodi...@gmail.com 
>>> <mailto:xiaodi...@gmail.com>> 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.

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.

John.

> 
>> 
>> John.
>> 
>>> 
>>> On Thu, Jun 2, 2016 at 18:22 Brent Royal-Gordon via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> 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
>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <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