[Idea] Custom keywords for operators.

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?

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

Unicode has a lot of operator characters. If the one you want isn't already easy to type, you can use a utility like Ukelele (http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=ukelele\) to map them to some unused key combination (on macOS, anyway... dunno what the Linux/Windows equivalent is).

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.

I wouldn't be opposed to just requiring whitespace around infix operators in general (but I suspect I'm in the minority on that).

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?

The topic of using identifiers as operators has come up before, and rejected on the grounds that it'd make parsing things much slower. I don't recall if your ideas regarding restrictions on the spellings have been discussed, though.

I'm +1 if the technical issues can be sorted out.

- Dave Sweeris

···

Sent from my iPad

On Jul 31, 2017, at 2:09 PM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

As I said in some other thread, I'm not convinced we should be making design decisions based on potential aesthetic bugs in text editors. Not because syntax highlighting isn't important for non Xcode users, but because they're just that: bugs... Presumably they'll get fixed in the next release of whatever does your syntax highlighting.

Does anyone know if the new technologies that Xcode ties into are specific to swiftc/clang, or is LLVM in general now able to integrate with text editors for syntax highlighting, etc? This might be a hard sell if only works with Swift, but if it's a new service that LLVM provides for any language (or even just Swift & the Cs, given the laters' popularity), all your text editor's vendor has do is support that and it'll automatically get correct syntax highlighting info straight from the compiler itself.

- Dave Sweeris

···

On Jul 31, 2017, at 3:59 PM, Taylor Swift via swift-evolution <swift-evolution@swift.org> wrote:

I’m gonna come out and say I’m not a fan of this at all. I’m already pretty suspicious of operator overloading, and I think supporting this would make Swift code much more difficult to read. Also, while for some reason everyone ignores this, this kind of syntax is almost impossible for text editors to highlight, which I think is an important consideration for any changes to language syntax.

I think I read on some thread here that the sets of token sequences for identifiers and operators are deliberately distinct, so basic parsing agents can be made. This can’t be done in C++ because some tokens are too context-sensitive for anything less than a full parser; the Swift authors didn’t want this to happen here. The keyword operators you gave aren’t a general rule, but custom syntax. They work because the exception list is limited, and probably won’t be generally open.

···

On Jul 31, 2017, at 5:09 PM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

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.


Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com

See the 3rd entry of:

-Chris

···

On Jul 31, 2017, at 2:09 PM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org> wrote:

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’m gonna come out and say I’m not a fan of this at all. I’m already pretty
suspicious of operator overloading, and I think supporting this would make
Swift code much more difficult to read. Also, while for some reason
everyone ignores this, this kind of syntax is almost impossible for text
editors to highlight, which I think is an important consideration for any
changes to language syntax.

···

On Mon, Jul 31, 2017 at 5:09 PM, Gor Gyolchanyan via swift-evolution < swift-evolution@swift.org> wrote:

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
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

>
> I’m gonna come out and say I’m not a fan of this at all. I’m already
pretty suspicious of operator overloading, and I think supporting this
would make Swift code much more difficult to read. Also, while for some
reason everyone ignores this, this kind of syntax is almost impossible for
text editors to highlight, which I think is an important consideration for
any changes to language syntax.

As I said in some other thread, I'm not convinced we should be making
design decisions based on potential aesthetic bugs in text editors. Not
because syntax highlighting isn't important for non Xcode users, but
because they're just that: bugs... Presumably they'll get fixed in the next
release of whatever does your syntax highlighting.

It’s not that I’m against new syntax, language packages can always be
updated. But when it comes to introducing syntax that you cannot update a
language package to support, I think that’s something to avoid. Most text
editors parse source code using regular expressions. That’s not just a
technical limitation, it’s also good sense. You don’t want to have to
search for a keyword declaration that potentially lives in another file, or
even another module, if it exists, just to know whether a word is an
identifier or an operator.

Does anyone know if the new technologies that Xcode ties into are specific
to swiftc/clang, or is LLVM in general now able to integrate with text
editors for syntax highlighting, etc? This might be a hard sell if only
works with Swift, but if it's a new service that LLVM provides for any
language (or even just Swift & the Cs, given the laters' popularity), all
your text editor's vendor has do is support that and it'll automatically
get correct syntax highlighting info straight from the compiler itself.

- Dave Sweeris

This idea came up in the past <Issues · atom/atom · GitHub;
with Swift support in the Atom editor and it never went anywhere. Just
because one single proprietary source editor supports the proposed syntax
is not evidence that it would be widely supported. Considering Atom is one
of the more progressive editors out there, if they weren’t going to support
SourceKit integration I doubt the many other editors out there would. Mind
you gedit literally *just* got basic regex Swift highlighting support about
a month ago.

···

On Mon, Jul 31, 2017 at 7:20 PM, David Sweeris <davesweeris@mac.com> wrote:

> On Jul 31, 2017, at 3:59 PM, Taylor Swift via swift-evolution < > swift-evolution@swift.org> wrote:

PS, for what it’s worth, i am the maintainer of the language-swift-89
<Sunsetting Atom - The GitHub Blog; atom package.

···

On Mon, Jul 31, 2017 at 8:29 PM, Taylor Swift <kelvin13ma@gmail.com> wrote:

On Mon, Jul 31, 2017 at 7:20 PM, David Sweeris <davesweeris@mac.com> > wrote:

> On Jul 31, 2017, at 3:59 PM, Taylor Swift via swift-evolution < >> swift-evolution@swift.org> wrote:
>
> I’m gonna come out and say I’m not a fan of this at all. I’m already
pretty suspicious of operator overloading, and I think supporting this
would make Swift code much more difficult to read. Also, while for some
reason everyone ignores this, this kind of syntax is almost impossible for
text editors to highlight, which I think is an important consideration for
any changes to language syntax.

As I said in some other thread, I'm not convinced we should be making
design decisions based on potential aesthetic bugs in text editors. Not
because syntax highlighting isn't important for non Xcode users, but
because they're just that: bugs... Presumably they'll get fixed in the next
release of whatever does your syntax highlighting.

It’s not that I’m against new syntax, language packages can always be
updated. But when it comes to introducing syntax that you cannot update a
language package to support, I think that’s something to avoid. Most text
editors parse source code using regular expressions. That’s not just a
technical limitation, it’s also good sense. You don’t want to have to
search for a keyword declaration that potentially lives in another file, or
even another module, if it exists, just to know whether a word is an
identifier or an operator.

Does anyone know if the new technologies that Xcode ties into are
specific to swiftc/clang, or is LLVM in general now able to integrate with
text editors for syntax highlighting, etc? This might be a hard sell if
only works with Swift, but if it's a new service that LLVM provides for any
language (or even just Swift & the Cs, given the laters' popularity), all
your text editor's vendor has do is support that and it'll automatically
get correct syntax highlighting info straight from the compiler itself.

- Dave Sweeris

This idea came up in the past <Issues · atom/atom · GitHub;
with Swift support in the Atom editor and it never went anywhere. Just
because one single proprietary source editor supports the proposed syntax
is not evidence that it would be widely supported. Considering Atom is one
of the more progressive editors out there, if they weren’t going to support
SourceKit integration I doubt the many other editors out there would. Mind
you gedit literally *just* got basic regex Swift highlighting support
about a month ago.

I thought limiting the keywords to the ones explicitly defined for this purpose would solve the problem of overcomplicating the parser.
Just to be clear: I do *not* propose replacing punctuation-based operators with identifier-based ones, the ideas was purely additive.
But I do see the problem now. I can't think of a good way at the moment of resolving the recursive problem with the parser if it needs to resolve the imports first.
Perhaps If I come up with a deterministic and easy parsing mechanism that would not depend on pre-arsing the entire file at once, this would not be such a bit show-stopper.
And again, I wouldn't even bring this up if swift didn't already rely on keyword operators, which means that there can not be any semantical reason to disallow this.

···

On Aug 1, 2017, at 4:29 AM, Chris Lattner <clattner@nondot.org> wrote:

On Jul 31, 2017, at 2:09 PM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

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.

See the 3rd entry of:
https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

-Chris

I understand the technical problem here, and killed my hope for "nominal" operators long time ago with fire.

But if someone here uses Kotlin, they know very well how great it is to be able to infix functions of 2 parameters like they were operators: it makes code extremely clean and readable, and it's extremely useful when writing DSLs.

Elviro

···

Il giorno 01 ago 2017, alle ore 03:29, Chris Lattner via swift-evolution <swift-evolution@swift.org> ha scritto:

On Jul 31, 2017, at 2:09 PM, Gor Gyolchanyan via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

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.

See the 3rd entry of:
https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md

-Chris

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution