Skip to content

Instantly share code, notes, and snippets.

@beccadax
Last active March 26, 2017 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beccadax/c3f9dc7c03a34c979e5e363826c2e19d to your computer and use it in GitHub Desktop.
Save beccadax/c3f9dc7c03a34c979e5e363826c2e19d to your computer and use it in GitHub Desktop.
An example formatter design.
protocol Formatter {
associatedtype Input
associatedtype Output
func format(_ input: Input) -> Output
}
protocol CombiningFormatter: Formatter where
InnerFormatter.Output == CombinedFormatter.Input
{
associatedtype InnerFormatter: Formatter
associatedtype CombinedFormatter: Formatter
func combined(with inner: InnerFormatter) -> CombinedFormatter
}
struct Formatted<FormatterType: Formatter> {
var input: FormatterType.Input
var formatter: FormatterType
}
func %% <FormatterType: CombiningFormatter>(lhs: FormatterType.InnerFormatter, rhs: FormatterType) -> FormatterType.CombinedFormatter {
return rhs.combined(with: lhs)
}
func %% <FormatterType: Formatter>(lhs: FormatterType.Input, rhs: FormatterType) -> Formatted<FormatterType.Input> {
return Formatted<FormatterType>(input: lhs, formatter: rhs)
}
struct int<Integer: BinaryInteger>: Formatter {
enum Sign { case always, never, auto }
var sign: Sign
var thousandsSeparator: Bool
var radix: Int
init(sign: Sign = .auto, thousands: Bool = true, radix: Int = 10) {...}
func format(_ input: Integer) -> String { ... }
}
struct PassthroughFormatter<Input>: Formatter {
func format(_ input: Input) -> Input {
return input
}
}
extension CombiningFormatter where Self: Formatter, InnerFormatter == PassthroughFormatter<Input> {
func format(_ input: Input) -> Output {
return combined(with: PassthroughFormatter()).format(input)
}
}
// Here's the part this proposal touches on. This initializer would be
// used when interpolating a `Formatted` value.
extension String {
init<FormatterType: Formatter>(_ formatted: Formatted<FormatterType>)
where FormatterType.Output == String
{
self = formatted.formatter.format(formatted.input)
}
}
struct width<InnerFormatter: Formatter>: CombiningFormatter, Formatter
where InnerFormatter.Output == String {
enum Side { case leading, trailing }
var countRange: Range<Int>
var padOn: Side?
var padWith: Character
var truncateOn: Side?
init(padding: Side, with: Character = " ", orTruncating: Side, to: Range<Int>) {...}
init(padding: Side, with: Character = " ", to: Int) {...}
init(truncating: Side, to: Int) {...}
func combined(with inner: InnerFormatter) {
return CombinedFormatter(inner: inner, combining: self)
}
struct CombinedFormatter: Formatter {
let inner: InnerFormatter
let combining: width
func format(_ input: String) -> String {...}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment