So I was thinking the other day (and by "the other day" I mean "It just 
occurred to me") that Swift's custom operator declaration mechanism is pretty 
sweet (it's become even sweeter ever since numeric precedence values were 
replaced with purely relativistic precedence trees). There are currently only 
two problems with them that grind my operator-declaring endeavors to a painful 
halt:
        1. The fact that most punctuation characters on the keyboard (think - 
ASCII) are reserved, so any custom operator either has to be a long sequence of 
two or three non-reserved ASCII characters or have to include difficult-to-type 
unicode punctuation characters.
        2. The fact that anything that passes as an identifier character (which 
includes a surprisingly wide array of punctuation characters) is off the table 
as well.

I have no good idea how to deal with the first problem, but the second problem 
seems to have a bafflingly simple solution that I can't believe I haven't 
noticed until now.
And the reason to even try to solve that problem is because Swift already has a 
lot of operators with identifiers in them:
        * infix is
        * infix as
        * infix as?
        * infix as!
        * prefix try
        * prefix try?
        * prefix try!
        * prefix throw
So this is hardly a new concept to Schwifty developers.

The way I think could this could be solved is by introducing custom keywords 
that can be defined just like custom operators can be.
The custom keyword has to be a valid identifier and is defined much like a 
non-infix custom operator (by writing `keyword`, followed by an identifier).

Custom operator definitios would now be permitted to have any number of 
non-adjacent keywords among usual punctuation characters.
Any identifier that matches a custom keyword has to be escaped with backticks 
just like it's the case for regular keywords.
Prefix operators may not end with a keyword.
Postfix operators may not begin with a keyword.
Infix operators that either begin or end with a keyword may not be used without 
whitespaces.

Here's an example:

precedencegroup AggregateFormingPrecedence {
        higherThan: TernaryPrecedence
        lowerThan: LogicalDisjunctionPrecedence
}

precedencegroup DimensionFormingPrecedence {
        higherThan: AggregateFormingPrecedence
        lowerThan: LogicalDisjunctionPrecedence
}

keyword of
keyword by
infix operator of: AggregateFormingPrecedence
infix operator by: DimensionFormingPrecedence

public struct Matrix<Element> where Element: FloatingPoint {

        public struct Dimensions {
                let rows: Int
                let columns: Int
        }

        public init(dimensions: Dimensions, value: Element) {
                self.elements = .init(repeating: value, count: dimensions.rows 
* dimensions.columns)
        }

        private var elements: [Element]
        
}

public static func by(_ rows: Int, _ columns: Int) -> Matrix.Dimensions {
        return .init(rows: rows, columns: columns)
}

public static func of<Element>(_ dimensions: Matrix.Dimensions, _ value: 
Element) -> Matrix<Element> where Element: FloatingPoint {
        return .init(dimensions: dimensions, value: value)
}

let m = 3 by 4 of 1.0 // m is of type Matrix<Double>

I feel like these kind of changes would be best considered in the early stages 
of a major release (namely, Swift 5) so that they have time to be refined and 
tested.
What do you guys think?

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to