Here's another example use case: Auto Layout visual format strings. https://gist.github.com/jtbandes/9c1c25ee4996d2554375#file-constraintcollection-swift-L85-L87
Since only views and numeric types are supported, the generic init<T> has to be a run-time error. Ideally it could be a compile-time error. On Tue, Aug 2, 2016 at 6:10 PM, Brent Royal-Gordon <[email protected]> wrote: > > On Jul 30, 2016, at 10:35 PM, Jacob Bandes-Storch via swift-evolution < > [email protected]> wrote: > > > > In the past, there has been some interest in refining the behavior of > ExpressibleByStringInterpolation (née StringInterpolationConvertible), for > example: > > > > - Ability to restrict the types that can be used as interpolation > segments > > - Ability to distinguish the string-literal segments from interpolation > segments whose type is String > > > > Some prior discussions: > > - "StringInterpolationConvertible and StringLiteralConvertible > inheritance" > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160516/017654.html > > - Sub-discussion in "Allow multiple conformances to the same protocol" > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160606/020746.html > > - "StringInterpolationConvertible: can't distinguish between literal > components and String arguments" https://bugs.swift.org/browse/SR-1260 / > rdar://problem/19800456&18681780 > > - "Proposal: Deprecate optionals in string interpolation" > https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160516/018000.html > > > > > > About Swift 4, Chris wrote: > > - String re-evaluation: String is one of the most important fundamental > types in the language. The standard library leads have numerous ideas of > how to improve the programming model for it, without jeopardizing the goals > of providing a unicode-correct-by-default model. Our goal is to be better > at string processing than Perl! > > > > I'd be interested in any more detail the team can provide on this. I'd > like to talk about string interpolation improvements, but it wouldn't be > wise to do so without keeping an eye towards possible regex/pattern-binding > syntax, and the String refinements that the stdlib team has in mind, if > there's a chance they would affect interpolation. > > > > Discuss! > > I'm not one of the core team, so all I can really provide is a use case. > > Given a LocalizedString type like: > > /// Conforming types can be included in a LocalizedString. > protocol LocalizedStringConvertible { > /// The format to use for this instance. This format string will > be included in the key when > /// this type is interpolated into a LocalizedString. > var localizedStringFormat: String { get } > > /// The arguments to use when formatting to represent this > instance. > var localizedStringArguments: [CVarArg] { get } > } > > extension NSString: LocalizedStringConvertible {…} > extension String: LocalizedStringConvertible {…} > extension LocalizedString: LocalizedStringConvertible {…} > > extension Int: LocalizedStringConvertible {…} > // etc. > > struct LocalizedString { > /// Initializes a LocalizedString by applying the `arguments` to > the format string with the > /// indicated `key` using `String.init(format:arguments:)`. > /// > /// If the `key` does not exist in the localized string file, the > `key` itself will be used as > /// the format string. > init(key: String, formattedWith arguments: [CVarArg]) {…} > } > > extension String { > init(_ localizedString: LocalizedString) { > self.init(describing: localizedString) > } > } > > extension LocalizedString { > /// Initializes a LocalizedString with no arguments which uses the > indicated `key`. `%` > /// characters in the `key` will be converted to `%%`. > /// > /// If the `key` does not exist in the localized string file, the > `key` itself will be used as > /// the string. > init(key: String) {…} > > /// Initializes a LocalizedString to represent the indicated > `value`. > init(_ value: LocalizedStringConvertible) {…} > > /// Initializes a LocalizedString to represent the empty string. > init() {…} > } > > extension LocalizedString: CustomStringConvertible {…} > > extension LocalizedString: ExpressibleByStringLiteral { > init(stringLiteral value: String) { > self.init(key: value) > } > … > } > > The current ExpressibleByStringInterpolation protocol has a number of > defects. > > 1. We want to only permit LocalizedStringConvertible types, or at > least *use* the LocalizedStringConvertible conformance; neither of these > appears to be possible. (`is` and `as?` casts always fail, overloads don't > seem to be called, etc.) > > 2. The literal parts of the string are interpreted using > `String`'s `ExpressibleByStringLiteral` conformance; we really want them to > use `LocalizedString`'s instead. > > 3. We don't want the literal parts of the string to pass through > `init(stringInterpolationSegment:)`, because we want to treat interpolation > and literal segments differnetly. > Yep, this is what I filed https://bugs.swift.org/browse/SR-1260 for. > > In other words, we want to be able to write something like this: > > extension LocalizedString: ExpressibleByStringInterpolation { > typealias StringInterpolatableType = > LocalizedStringConvertible > > init(stringInterpolation segments: LocalizedString) { > self.init() > for segment in segments { > formatKey += segment.formatKey > arguments += segment.arguments > } > } > > init(stringInterpolationSegment expr: > LocalizedStringConvertible) { > self.init(expr) > } > } > > And change the code generated by the compiler from (given the statement > `"foo \(bar) baz" as LocalizedString`) this: > > LocalizedString(stringInterpolation: > LocalizedString(stringInterpolationSegment: > String(stringLiteral: "foo ")), > LocalizedString(stringInterpolationSegment: bar), > LocalizedString(stringInterpolationSegment: > String(stringLiteral: " baz")) > ) > > To this: > > LocalizedString(stringInterpolation: > LocalizedString(stringLiteral: "foo "), > LocalizedString(stringInterpolationSegment: bar), > LocalizedString(stringLiteral: " baz") > ) > > This would obviously require a few changes to the > ExpressibleAsStringInterpolation protocol: > > // You cannot accept interpolations unless you can also be a plain > literal. > // Necessary for literal segments. > protocol ExpressibleByStringInterpolation: > ExpressibleByStringLiteral { > // An associated type for the type of a permitted > interpolation > associatedtype StringInterpolatableType = Any > > // No changes here > init(stringInterpolation segments: Self...) > > // No longer generic; instead uses > StringInterpolatableType existentials. > // Also a semantic change: this is only called for the > actual interpolations. > // init(stringLiteral:) is called for literal segments. > init(stringInterpolationSegment expr: > StringInterpolatableType) > > // Given the change in roles, we might want to consider > renaming the initializers: > // > // init(stringInterpolation:) => > init(combinedStringLiteral:) or init(stringInterpolationSegments:) > // init(stringInterpolationSegment:) => > init(stringInterpolation:) > } > > Or perhaps we would hoist the combining initializer up into > ExpressibleAsStringLiteral, and generate an `init(combinedStringLiteral:)` > call every time string literals are used. > > protocol ExpressibleByStringLiteral { > associatedtype StringLiteralType: > _ExpressibleByBuiltinStringLiteral = String > > init(stringLiteralSegments segments: Self...) > init(stringLiteral value: StringLiteralType) > } > > protocol ExpressibleByStringInterpolation: > ExpressibleByStringLiteral { > associatedtype StringInterpolatableType = Any > > init(stringInterpolation expr: StringInterpolatableType) > } > > // "foo" as LocalizedString > LocalizedString(stringLiteralSegments: > LocalizedString(stringLiteral: "foo") > ) > > // "foo \(bar) baz" as LocalizedString > LocalizedString(stringInterpolation: > LocalizedString(stringLiteral: "foo "), > LocalizedString(stringInterpolation: bar), > LocalizedString(stringLiteral: " baz") > ) > > Now, it's quite possible--perhaps even likely--that there are really good > reasons for the current design. But I've been thinking about this for two > years and I don't know what they are yet; nor can I find much relevant > design documentation. I, too, would love to find out why the current design > was selected. > > -- > Brent Royal-Gordon > Architechies > >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
