[Re-Review] SE-0104: Protocol-oriented integers


(Karl) #1

Are there Number types which can’t be Comparable?

Complex numbers. I believe `Number` is designed to allow a complex number type to conform.

Magnitude could be comparable then. For vectors, matrices and complex numbers, “magnitude” typically refers to a scalar. I don’t think we need something broader than that.

- Karl


(David Sweeris) #2

Using magnitude for comparison leads to some decidedly odd places:
let x: Complex = 1
let y: Complex = -2
x < y // returns true

- Dave Sweeris

···

On Feb 22, 2017, at 23:52, Karl Wagner via swift-evolution <swift-evolution@swift.org> wrote:

Are there Number types which can’t be Comparable?

Complex numbers. I believe `Number` is designed to allow a complex number type to conform.

Magnitude could be comparable then. For vectors, matrices and complex numbers, “magnitude” typically refers to a scalar. I don’t think we need something broader than that.


(Karl) #3

Are there Number types which can’t be Comparable?

Complex numbers. I believe `Number` is designed to allow a complex number type to conform.

Magnitude could be comparable then. For vectors, matrices and complex numbers, “magnitude” typically refers to a scalar. I don’t think we need something broader than that.

Using magnitude for comparison leads to some decidedly odd places:
let x: Complex = 1
let y: Complex = -2
x < y // returns true

- Dave Sweeris

Fixed:

let x: Complex = 1
let y: Complex = -2
x.magnitude < y.magnitude // returns true

I don’t mean we should compare all numbers by magnitude, only that the Magnitude associated type be required to be comparable. That way you could, for example, sort things by magnitude (if that’s useful to you).

Given that magnitudes appear to always be scalars (I couldn’t find an exact definition beyond a “norm”, which is a scalar), it seems fair to require them to be comparable.

- Karl

···

On 23 Feb 2017, at 18:40, David Sweeris <davesweeris@mac.com> wrote:
On Feb 22, 2017, at 23:52, Karl Wagner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:


(David Sweeris) #4

Ah, ok, I misunderstood you. Yes, that seems reasonable to me.

- Dave Sweeris

···

On Feb 23, 2017, at 9:54 AM, Karl Wagner <razielim@gmail.com> wrote:

On 23 Feb 2017, at 18:40, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Feb 22, 2017, at 23:52, Karl Wagner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Are there Number types which can’t be Comparable?

Complex numbers. I believe `Number` is designed to allow a complex number type to conform.

Magnitude could be comparable then. For vectors, matrices and complex numbers, “magnitude” typically refers to a scalar. I don’t think we need something broader than that.

Using magnitude for comparison leads to some decidedly odd places:
let x: Complex = 1
let y: Complex = -2
x < y // returns true

- Dave Sweeris

Fixed:

let x: Complex = 1
let y: Complex = -2
x.magnitude < y.magnitude // returns true

I don’t mean we should compare all numbers by magnitude, only that the Magnitude associated type be required to be comparable. That way you could, for example, sort things by magnitude (if that’s useful to you).

Given that magnitudes appear to always be scalars (I couldn’t find an exact definition beyond a “norm”, which is a scalar), it seems fair to require them to be comparable.


(Max Moiseev) #5

Conformance to Comparable is not required by anything in the standard library. Besides, it is always possible to further constrain your own code as in:

func f<T : Number>(_ x: T) where T.Magnitude : Comparable {}

I would argue that adding constraints without solid proof of them being useful and necessary is not the right thing to do.
Also, sorting things by magnitude will require using a predicate-based sorted() anyway, and that does not require Comparable.

Max

···

On Feb 23, 2017, at 9:59 AM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:

On Feb 23, 2017, at 9:54 AM, Karl Wagner <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

On 23 Feb 2017, at 18:40, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Feb 22, 2017, at 23:52, Karl Wagner via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Are there Number types which can’t be Comparable?

Complex numbers. I believe `Number` is designed to allow a complex number type to conform.

Magnitude could be comparable then. For vectors, matrices and complex numbers, “magnitude” typically refers to a scalar. I don’t think we need something broader than that.

Using magnitude for comparison leads to some decidedly odd places:
let x: Complex = 1
let y: Complex = -2
x < y // returns true

- Dave Sweeris

Fixed:

let x: Complex = 1
let y: Complex = -2
x.magnitude < y.magnitude // returns true

I don’t mean we should compare all numbers by magnitude, only that the Magnitude associated type be required to be comparable. That way you could, for example, sort things by magnitude (if that’s useful to you).

Given that magnitudes appear to always be scalars (I couldn’t find an exact definition beyond a “norm”, which is a scalar), it seems fair to require them to be comparable.

Ah, ok, I misunderstood you. Yes, that seems reasonable to me.

- Dave Sweeris

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


(David Sweeris) #6

Conformance to Comparable is not required by anything in the standard library.

That surprises me. Isn't there a sort function or something, or did we change it so they all need a predicate now?

I would argue that adding constraints without solid proof of them being useful and necessary is not the right thing to do.
Also, sorting things by magnitude will require using a predicate-based sorted() anyway, and that does not require Comparable.

Yeah, if it's not needed... Well, it's easier to add it later if it turns out to be useful than to remove it if it gets in the way.

- Dave Sweeris

···

Sent from my iPhone

On Feb 23, 2017, at 10:40, Max Moiseev <moiseev@apple.com> wrote:


(Max Moiseev) #7

Sent from my iPhone

Conformance to Comparable is not required by anything in the standard library.

That surprises me. Isn't there a sort function or something, or did we change it so they all need a predicate now?

I meant it’s not required from Number.Magnitude. Not in general.

···

On Feb 23, 2017, at 12:43 PM, David Sweeris <davesweeris@mac.com> wrote:

On Feb 23, 2017, at 10:40, Max Moiseev <moiseev@apple.com> wrote:

I would argue that adding constraints without solid proof of them being useful and necessary is not the right thing to do.
Also, sorting things by magnitude will require using a predicate-based sorted() anyway, and that does not require Comparable.

Yeah, if it's not needed... Well, it's easier to add it later if it turns out to be useful than to remove it if it gets in the way.

- Dave Sweeris


(Karl) #8

Conformance to Comparable is not required by anything in the standard library. Besides, it is always possible to further constrain your own code as in:

Besides FloatingPoint, you mean? Or Collection indexes? Quite a lot of stuff, actually.

func f<T : Number>(_ x: T) where T.Magnitude : Comparable {}

I would argue that adding constraints without solid proof of them being useful and necessary is not the right thing to do.
Also, sorting things by magnitude will require using a predicate-based sorted() anyway, and that does not require Comparable.

Max

Yes, but the constraints in the standard library should also convey some meaning and be useful. What do we mean by a “magnitude” anyway? Won’t it be strange in practice that I can create a “magnitude” out of nothing but an arbitrary integer literal but can’t compare two values? Ultimately it looks like a deficiency in the design to me - either it’s a simple scalar, ExpressibleByIntegerLiteral and Comparable, or it’s something more complex and can’t be either.

This is exactly the kind of flaw I’ve been working around with the current Strideable.Stride (i.e. current SignedNumber). If a type is ExpressibleByIntegerLiteral, you should be able to basically do all the things to it that you can do with an integer.

- Karl

···

On 23 Feb 2017, at 19:40, Max Moiseev <moiseev@apple.com> wrote:


(David Sweeris) #9

(replying to bolded part)

Not necessarily... Complex numbers can conform to `ExpressibleByIntegerLiteral` but not `Comparable`. At least not in a generally-accepted way.

- Dave Sweeris

···

On Feb 23, 2017, at 2:33 PM, Karl Wagner <razielim@gmail.com> wrote:

On 23 Feb 2017, at 19:40, Max Moiseev <moiseev@apple.com> wrote:

Conformance to Comparable is not required by anything in the standard library. Besides, it is always possible to further constrain your own code as in:

Besides FloatingPoint, you mean? Or Collection indexes? Quite a lot of stuff, actually.

func f<T : Number>(_ x: T) where T.Magnitude : Comparable {}

I would argue that adding constraints without solid proof of them being useful and necessary is not the right thing to do.
Also, sorting things by magnitude will require using a predicate-based sorted() anyway, and that does not require Comparable.

Max

Yes, but the constraints in the standard library should also convey some meaning and be useful. What do we mean by a “magnitude” anyway? Won’t it be strange in practice that I can create a “magnitude” out of nothing but an arbitrary integer literal but can’t compare two values? Ultimately it looks like a deficiency in the design to me - either it’s a simple scalar, ExpressibleByIntegerLiteral and Comparable, or it’s something more complex and can’t be either.

This is exactly the kind of flaw I’ve been working around with the current Strideable.Stride (i.e. current SignedNumber). If a type is ExpressibleByIntegerLiteral, you should be able to basically do all the things to it that you can do with an integer.


(David Sweeris) #10

Perhaps a better example would be the `%` operator, since it involves stdlib types. Floating point types are ExpressibleByIntegerLiteral, but don't have the % operator that integers have.

- Dave Sweeris

···

On Feb 23, 2017, at 14:44, David Sweeris <davesweeris@mac.com> wrote:

On Feb 23, 2017, at 2:33 PM, Karl Wagner <razielim@gmail.com> wrote:

On 23 Feb 2017, at 19:40, Max Moiseev <moiseev@apple.com> wrote:

Conformance to Comparable is not required by anything in the standard library. Besides, it is always possible to further constrain your own code as in:

Besides FloatingPoint, you mean? Or Collection indexes? Quite a lot of stuff, actually.

func f<T : Number>(_ x: T) where T.Magnitude : Comparable {}

I would argue that adding constraints without solid proof of them being useful and necessary is not the right thing to do.
Also, sorting things by magnitude will require using a predicate-based sorted() anyway, and that does not require Comparable.

Max

Yes, but the constraints in the standard library should also convey some meaning and be useful. What do we mean by a “magnitude” anyway? Won’t it be strange in practice that I can create a “magnitude” out of nothing but an arbitrary integer literal but can’t compare two values? Ultimately it looks like a deficiency in the design to me - either it’s a simple scalar, ExpressibleByIntegerLiteral and Comparable, or it’s something more complex and can’t be either.

This is exactly the kind of flaw I’ve been working around with the current Strideable.Stride (i.e. current SignedNumber). If a type is ExpressibleByIntegerLiteral, you should be able to basically do all the things to it that you can do with an integer.

(replying to bolded part)

Not necessarily... Complex numbers can conform to `ExpressibleByIntegerLiteral` but not `Comparable`. At least not in a generally-accepted way.


(Xiaodi Wu) #11

That was a deliberate design choice discussed during review of floating
point protocols. Floating point remainder and integer modulo are very
different. Spelling them the same way enables use in generic protocols,
which would be incorrect uses. This was borne out by observation of
erroneous uses of floating point % in Swift 2.

···

On Fri, Feb 24, 2017 at 18:13 David Sweeris via swift-evolution < swift-evolution@swift.org> wrote:

On Feb 23, 2017, at 14:44, David Sweeris <davesweeris@mac.com> wrote:

On Feb 23, 2017, at 2:33 PM, Karl Wagner <razielim@gmail.com> wrote:

On 23 Feb 2017, at 19:40, Max Moiseev <moiseev@apple.com> wrote:

Conformance to Comparable is not required by anything in the standard
library. Besides, it is always possible to further constrain your own code
as in:

Besides FloatingPoint, you mean? Or Collection indexes? Quite a lot of
stuff, actually.

func f<T : Number>(_ x: T) where T.Magnitude : Comparable {}

I would argue that adding constraints without solid proof of them being
useful and necessary is not the right thing to do.
Also, sorting things by magnitude will require using a predicate-based
sorted() anyway, and that does not require Comparable.

Max

Yes, but the constraints in the standard library should also convey some
meaning and be useful. What do we mean by a “magnitude” anyway? Won’t it be
strange in practice that I can create a “magnitude” out of nothing but an
arbitrary integer literal but can’t compare two values? Ultimately it looks
like a deficiency in the design to me - either it’s a simple scalar,
ExpressibleByIntegerLiteral and Comparable, or it’s something more complex
and can’t be either.

This is exactly the kind of flaw I’ve been working around with the current
Strideable.Stride (i.e. current SignedNumber). *If a type is
ExpressibleByIntegerLiteral, you should be able to basically do all the
things to it that you can do with an integer.*

(replying to bolded part)

Not necessarily... Complex numbers can conform to
`ExpressibleByIntegerLiteral` but not `Comparable`. At least not in a
generally-accepted way.

Perhaps a better example would be the `%` operator, since it involves
stdlib types. Floating point types are ExpressibleByIntegerLiteral, but
don't have the % operator that integers have.

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


(David Sweeris) #12

Oh, I know. I was just pointing out another instance where a type conforms to `ExpressibleByIntegerLiteral` and can’t do something Int can do.

- Dave Sweeris

···

On Feb 24, 2017, at 4:45 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

That was a deliberate design choice discussed during review of floating point protocols. Floating point remainder and integer modulo are very different. Spelling them the same way enables use in generic protocols, which would be incorrect uses. This was borne out by observation of erroneous uses of floating point % in Swift 2.
On Fri, Feb 24, 2017 at 18:13 David Sweeris via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Feb 23, 2017, at 14:44, David Sweeris <davesweeris@mac.com <mailto:davesweeris@mac.com>> wrote:

On Feb 23, 2017, at 2:33 PM, Karl Wagner <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:

On 23 Feb 2017, at 19:40, Max Moiseev <moiseev@apple.com <mailto:moiseev@apple.com>> wrote:

Conformance to Comparable is not required by anything in the standard library. Besides, it is always possible to further constrain your own code as in:

Besides FloatingPoint, you mean? Or Collection indexes? Quite a lot of stuff, actually.

func f<T : Number>(_ x: T) where T.Magnitude : Comparable {}

I would argue that adding constraints without solid proof of them being useful and necessary is not the right thing to do.
Also, sorting things by magnitude will require using a predicate-based sorted() anyway, and that does not require Comparable.

Max

Yes, but the constraints in the standard library should also convey some meaning and be useful. What do we mean by a “magnitude” anyway? Won’t it be strange in practice that I can create a “magnitude” out of nothing but an arbitrary integer literal but can’t compare two values? Ultimately it looks like a deficiency in the design to me - either it’s a simple scalar, ExpressibleByIntegerLiteral and Comparable, or it’s something more complex and can’t be either.

This is exactly the kind of flaw I’ve been working around with the current Strideable.Stride (i.e. current SignedNumber). If a type is ExpressibleByIntegerLiteral, you should be able to basically do all the things to it that you can do with an integer.

(replying to bolded part)

Not necessarily... Complex numbers can conform to `ExpressibleByIntegerLiteral` but not `Comparable`. At least not in a generally-accepted way.

Perhaps a better example would be the `%` operator, since it involves stdlib types. Floating point types are ExpressibleByIntegerLiteral, but don't have the % operator that integers have.