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

2016-06-27 Thread Nicola Salmoria via swift-evolution
On Mon, Jun 27, 2016 at 12:38 AM, Károly Lőrentey <kar...@lorentey.hu>
wrote:

>
> > On 2016-06-25, at 14:23, Nicola Salmoria via swift-evolution <
> swift-evolution@swift.org> wrote:
> > The first comment I have to make is that, as has already been noted by
> plx,
> > the Arithmetic protocol looks like a "bag of syntax" with loose semantics
> > attached. It will be used by signed integers, unsigned integers
> (naturals),
> > floating point numbers; and is an obvious conformance for a Rational
> type as
> > well.
> > In the proposal, there is no indication of the expected semantics of the
> > four basic operations.
> > - Are addition and multiplication commutative?
> > - Is multiplication distributive over addition?
> > - Is 'rhs != 0' a precondition for division?
> > - Presumably associativity must match the associativity of the operators.
> > - What is (a / b) * b?
> > - Is T(exactly: n) * x guaranteed to be == (x + ... + x) n times?
>
> I’m not sure if this has been mentioned yet, but the semantics of Integer
> operations also needs to be tied down. In particular, the expected behavior
> of the remainder operation (in all forms) when given a negative numerator
> and/or denumerator should be explicitly spelled out.
>
> > Now about the AbsoluteValue associatedtype, which several other people
> have
> > already shown doubts about.
> > I found it useful, precisely for the reason stated in the proposal
> > (generating the description of a Rational). However, it seems to be
> mostly
> > an implementation detail, used to:
> > 1) work around the fact that -Int.min isn't representable in two's
> complement;
> > 2) provide a way to get the unsigned version of an integer type, to be
> used
> > by the doubleWidthMultiply() return type.
> >
> > These uses suggest that the Integer protocol might not be the best place
> for
> > this associatedtype: both of the use cases above would not apply to a
> > BigInt. It seems more appropriate for it to be part of FixedWidthInteger.
> > It might even make sense to rename it UnsignedSelf, to make it clear that
> > it's intended to be the unsigned equivalent of Self.
>
> I think absoluteValue would be a better fit in SignedInteger or
> SignedArithmetic. But if implementation experience suggests it should be in
> Integer, I don’t mind including AbsoluteValue as an alias to Self (or
> BigUInt) in the BigInt case.
>

AbsoluteValue is currently part of the signature of doubleWidthMultiply()
in FixedWidthInteger. I suppose that moving it to SignedInteger would
require having FixedWithSignedInteger and FixedWidthUnsignedInteger, with
different signatures for the function.


>
> I’m also a bit suspicious of Integer's static isSigned property. What is
> its intended usecase? Why do we need it, given that we also have
> SignedInteger/UnsignedInteger protocols? (Does it ever make sense to
> implement Integer without also implementing SignedInteger or
> UnsignedInteger?)
>
> > I also join Karoly's request for double-width division operations. In
> > particular I would suggest:
> >
> > static func doubleWidthDivideWithOverflow(_ lhs: (high: Self, low:
> > AbsoluteValue), by rhs: Self) -> (partialValue: Self, overflow:
> > ArithmeticOverflow)
> >
> > static func doubleWidthRemainder(_ lhs: (high: Self, low:
> AbsoluteValue), by
> > rhs: Self) -> Self
> >
> > Note that I needed to use static members here, because the first
> argument of
> > the division is not Self. Alternatively, the result of
> doubleWidthMultiply()
> > could be a struct, so that double-width division operations could be
> members
> > of that struct.
>
> I suggest to combine generation of the quotient and remainder into a
> single division operation. (The implementations I know of provide both, so
> it makes sense to combine them.)
>
> static func doubleWidthDivide(_ numerator: (high: Self, low:
> AbsoluteValue), by denumerator: Self) -> (partialQuotient: Self, remainder:
> Self, overflow: ArithmeticOverflow)
>
> A more spoon-feeding name would be
> “doubleWidthQuotientAndRemainderWithOverflow(dividing:, by:)”, but yuck.
>

If it's guaranteed to be free, no objections. I separated them because in
one case I need the quotient and not the remainder, and in another case the
opposite.


> (I’d personally also be fine with simplifying this by requiring that the
> division not overflow, i.e., that lhs.high < rhs (assuming rhs > 0), and
> treating overflow as a precondition failure. I know Rational's addition
> needs to handle overflow, but perhaps it would be OK to move this check
> outside

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

2016-06-25 Thread Nicola Salmoria via swift-evolution
> * What is your evaluation of the proposal?

This is a great proposal which was sorely needed, so I strongly support it
in general. I have a few comments and suggestions to make.


First of all, a bit of background to explain where I'm coming from: in the
past weeks I have been working for educational purposes on a Rational type. This is one of those things that seem trivial at first
sight, but are surprisingly difficult to do right. Thoroughly testing and
avoiding traps or incorrect results in edge cases was a lot of work.
I have now updated my code to use the new interfaces described in the
proposal, and I was able to remove a lot of custom protocols and
boilerplate. So it was a net improvement.


The first comment I have to make is that, as has already been noted by plx,
the Arithmetic protocol looks like a "bag of syntax" with loose semantics
attached. It will be used by signed integers, unsigned integers (naturals),
floating point numbers; and is an obvious conformance for a Rational type as
well.
In the proposal, there is no indication of the expected semantics of the
four basic operations.
- Are addition and multiplication commutative?
- Is multiplication distributive over addition?
- Is 'rhs != 0' a precondition for division?
- Presumably associativity must match the associativity of the operators.
- What is (a / b) * b?
- Is T(exactly: n) * x guaranteed to be == (x + ... + x) n times?

While this protocol is useful to simplify the implementation of operators,
it might be largely superseded by other improvements related to SE-0091.
Taken alone, I'm not sure it pulls its own weight.

For example say I wanted to write some generic code using values that
represent probabilities. I would need arithmetic to work on such values, but
since probabilities are strictly in the interval [0.0, 1.0], integers would
be useless. I could make the code generic over FloatingPoint, but a Rational
type would fit the bill as well, and guarantee accuracy. So to write
meaningful generic code I'd need a different protocol, one that made more
promises about the semantics of division.


Now about the AbsoluteValue associatedtype, which several other people have
already shown doubts about.
I found it useful, precisely for the reason stated in the proposal
(generating the description of a Rational). However, it seems to be mostly
an implementation detail, used to:
1) work around the fact that -Int.min isn't representable in two's complement;
2) provide a way to get the unsigned version of an integer type, to be used
by the doubleWidthMultiply() return type.

These uses suggest that the Integer protocol might not be the best place for
this associatedtype: both of the use cases above would not apply to a
BigInt. It seems more appropriate for it to be part of FixedWidthInteger.
It might even make sense to rename it UnsignedSelf, to make it clear that
it's intended to be the unsigned equivalent of Self.


I also join Karoly's request for double-width division operations. In
particular I would suggest:

static func doubleWidthDivideWithOverflow(_ lhs: (high: Self, low:
AbsoluteValue), by rhs: Self) -> (partialValue: Self, overflow:
ArithmeticOverflow)

static func doubleWidthRemainder(_ lhs: (high: Self, low: AbsoluteValue), by
rhs: Self) -> Self

Note that I needed to use static members here, because the first argument of
the division is not Self. Alternatively, the result of doubleWidthMultiply()
could be a struct, so that double-width division operations could be members
of that struct.

These operations are difficult to implement, and are very useful.

In my specific use case of Rational, addition is the trickiest operation to
implement because it can have transient overflows, which get simplified in
the final result. To handle them, I need to do two double-width multiplies,
followed by a double-width addition (which is easily implemented without
explicit support from the standard library). Then I need a double-width
remainder to compute the GCD, and finally an overflowing double-width
division to attempt fitting the result in a single-width numerator.

Without support for double-width division, the proposal falls short of being
really useful for this kind of operations.


Finally, I don't understand this example, which is also repeated twice in
the proposal. Is it perhaps a copy error?

public struct Int8 {
  public func addingWithOverflow(_ rhs: DoubleWidth)
-> (partialValue: DoubleWidth, overflow: ArithmeticOverflow) {
// efficient implementation
  }
}


> * Is the problem being addressed significant enough to warrant a change to
Swift?

Absolutely. Working with integer types in generic code is currently one of
the most frustrating experiences in Swift. The proposal should address most
of the common issues.

> * Does this proposal fit well with the feel and direction of Swift?

Very well. The new protocols are much more consistent and cohesive than the
status quo.

> * If you have used other languages or libraries 

Re: [swift-evolution] Proposal: Deprecate optionals in string interpolation

2016-05-24 Thread Nicola Salmoria via swift-evolution
Charlie Monroe via swift-evolution  writes:

> 
> I've jotted up a proposal here:
> https://gist.github.com/charlieMonroe/82e1519dd2b57029f69bc7abe99d7385
> 
> Please let me know if there are any comments to it.

Hi, sorry for arriving late but I had missed this thread.

I happen to have submitted a couple PRs related to this problem just last week:
https://github.com/apple/swift/pull/2551
https://github.com/apple/swift-corelibs-xctest/pull/110

In this case, the issue is not just with Optional's string interpolation,
but with Swift's implicit promotion. XCTAssertEqual()'s signature is:

public func XCTAssertEqual(_ expression1: @autoclosure ()
throws -> T?, _ expression2: @autoclosure () throws -> T?, _ message:
@autoclosure () -> String = "", file: StaticString = #file, line: UInt =
#line) -> Void

so in a test you would call it like

XCTAssertEqual(1, 2, "message")

but then the values are implicitly promoted to Optional, and when the
test fails you get the confusing message

XCTAssertEqual failed: ("Optional(1)") is not equal to ("Optional(2)") - message

which is clearly unexpected, since the parameters weren't optionals at all.

My proposed solution to this was to add an overload to XCTAssertEqual()
where the parameters aren't optionals, to prevent implicit promotion and
produce the expected output. It hadn't occurred to me that it might have
been desirable to change the Optional string interpolation altogether.

Regarding the proposal:

> This proposal suggests deprecating string interpolation of Optional in
order to prevent unexpected results at compile time.

I assume you mean "at runtime" here?

I think the detailed design needs  some more thought. The "Uninterpolable"
protocol, and suggesting to cast "as Any" in a Fix-it both seem hacks.

I'm not even sure if the general direction of a compile time warning is the
right one, and if the problem wouldn't be better solved by simply not making
Optional put "Optional()" around the value in its .description.

Arguably, if you do this:

print([1, 2, 3])

you get "[1, 2, 3]", not "Array([1, 2, 3])". So why should Optional behave
differently?

It would seem to me that the most obvious solution would be to make Optional
conform to CustomStringConvertible, like this:

extension Optional: CustomStringConvertible {
public var description: String {
switch self {
case .some(let x): return "\(x)"
case .none: return "nil"
}
}
}

interestingly, this doesn't quite seem to work at the moment:

let o = Optional(1)

print(o.description)// "1", ok
print(o.debugDescription)   // "Optional(1)", ok
print(o)// "1", ok
debugPrint(o)   // "Optional(1)", ok
print("\(o)")   // "Optional(1)", why??


Nicola


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


Re: [swift-evolution] [Review] SE-0050: Decoupling Floating Point Strides from Generic Implementations

2016-05-19 Thread Nicola Salmoria via swift-evolution
> * What is your evaluation of the proposal?

+1. It might not be pretty, but it is an improvement.

The Proposed Solution doesn't compile with development snapshot 05-09
(SE-0067 hasn't landed yet, IIRC). I hacked it to get it to compile, and
tested it with two problematic cases:

Test #1:
let expected = Array(stride(from: 10, through: 20, by: 1).map { Float($0) *
0.1 })
// [1.0, 1.1002, 1.2005, 1.3007, 1.3998, 1.5, 1.6002,
1.7005, 1.8007, 1.8998, 2.0]

let actual = Array(stride(from: Float(1.0), through: 2.0, by: 0.1))
// old result: one iteration less than expected
// [1.0, 1.1002, 1.2005, 1.3007, 1.401, 1.5012,
1.6014, 1.7017, 1.8019, 1.9021]
// new result: correct
// [1.0, 1.1002, 1.2005, 1.2995, 1.3998, 1.5, 1.6002,
1.7005, 1.7995, 1.901, 2.0]

Test #2:
let expected = Array(stride(from: 10, to: 100, by: 9).map { Float($0) * 0.1 })
// [1.0, 1.8998, 2.7995, 3.7005, 4.599, 5.5, 6.401,
7.3019, 8.1981, 9.1038]

let actual = Array(stride(from: Float(1.0), to: 10.0, by: 0.9))
// old result: one iteration more than expected
// [1.0, 1.8998, 2.7995, 3.6981, 4.599, 5.5, 6.401,
7.3019, 8.1981, 9.0943, 9.9905]
// new result: correct
// [1.0, 1.8998, 2.7995, 3.6981, 4.599, 5.5, 6.3962,
7.2971, 8.1981, 9.0943]

So the proposed solution works as advertised.

I would suggest to include two cases like the above in the test suite.


> * Is the problem being addressed significant enough to warrant a change to
Swift?

Yes. This is a higher level abstraction, so it's important that it
guarantees the best possible accuracy. The current generic implementation
gives unacceptably surprising results.

> * Does this proposal fit well with the feel and direction of Swift?

Yes. It nicely follows the principle of least astonishment.

> * If you have used other languages or libraries with a similar feature,
how do you feel that this proposal compares to those?

I always flat-out avoided floating point loops in other languages, fearing
that they would be unreliable. It's good that with this change it'll be
possible to use them with more confidence.

> * How much effort did you put into your review? A glance, a quick reading,
or an in-depth study?

careful reading, tested the proposed solution, and read and contributed to
the relevant threads.

--
Nicola


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


Re: [swift-evolution] [Review] SE-0091: Improving operator requirements in protocols

2016-05-18 Thread Nicola Salmoria via swift-evolution
On Wed, May 18, 2016 at 10:36 PM, Matthew Johnson <matt...@anandabits.com>
wrote:

>
> On May 18, 2016, at 3:14 PM, Nicola Salmoria <nicola.salmo...@gmail.com>
> wrote:
>
>
>
> On Wed, May 18, 2016 at 10:03 PM, Matthew Johnson <matt...@anandabits.com>
>  wrote:
>
>>
>> On May 18, 2016, at 3:00 PM, Nicola Salmoria via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>
>>
>> On Wed, May 18, 2016 at 8:03 PM, Tony Allevato <allev...@google.com>
>> wrote:
>>
>>> On Wed, May 18, 2016 at 10:02 AM Nicola Salmoria via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>> > * What is your evaluation of the proposal?
>>>>
>>>> I'm generally in strong support, having long been a proponent of
>>>> removing
>>>> operators from protocols (the first occurrence was in this thread:
>>>> http://article.gmane.org/gmane.comp.lang.swift.evolution/7935)
>>>>
>>>> I have several comments about the details of the proposal, however.
>>>>
>>>> 1) At the beginning, in the "Proposed solution" section, the proposal
>>>> says
>>>> "This document does not propose that the current way of defining
>>>> operators
>>>> be removed or changed at this time. Rather, we describe an addition that
>>>> specifically provides improvements for protocol operator requirements."
>>>>
>>>> Later, however, there is a "Deprecation of non-static protocol
>>>> operators"
>>>> section which suggest to do exactly that, and this is reiterated in the
>>>> "Impact on existing code" section.
>>>>
>>>> Since I think that the deprecation of global operator overloads is the
>>>> crucial point of the proposal, I assume that the former is an oversight.
>>>>
>>>
>>> I could probably do a better job of clarifying the wording here. The
>>> proposal does *not* deprecate *all* global operator overloads. Global
>>> operators can still be implemented as they have been in Swift. So if you
>>> have a concrete type like `struct Matrix`, you can still define at the
>>> global level `func +(lhs: Matrix, rhs: Matrix) -> Matrix`.
>>>
>>> What's being deprecated is the current syntax used to define operator
>>> requirements inside protocols (by making the functions static) and the
>>> manner by which subtypes conform (ditto, through static methods instead of
>>> global functions).
>>>
>>
>> OK, I guess the unclear part is when you talk about "an addition that
>> specifically provides improvements for protocol operator requirements."
>> This is not just an addition; it's intended to completely replace the
>> protocol operator syntax.
>>
>>>
>>>
>>>> 2) The method signatures in the examples are not up to date with the
>>>> current
>>>> Swift 3 syntax. For example:
>>>>
>>>> protocol Equatable {
>>>>   static func ==(lhs: Self, rhs: Self) -> Bool
>>>> }
>>>>
>>>> should be:
>>>>
>>>> protocol Equatable {
>>>>   static func ==(_ lhs: Self, _ rhs: Self) -> Bool
>>>> }
>>>>
>>>
>>> Unless I'm mistaken, from looking at the Swift 3 branch of stdlib, the
>>> syntax changes don't appear to apply to operator functions. Since they are
>>> a special case that don't have argument labels, it wouldn't make sense to
>>> require them (or rather, the placeholders) here.
>>>
>>
>> I don't agree with this.
>>
>> Operators are called like this:
>>
>> x = y + z
>>
>> Of course it doesn't make sense to have parameter labels there.
>>
>> But the ones inside the protocol are not operators. They are methods, and
>> are called like methods. They happen to have funny names, but they are
>> still methods, and are called like this:
>>
>> x = T.+(y, z)
>>
>> In this case not only it makes sense for the parameters to have labels,
>> but making them behave differently from normal methods would be
>> inconsistent, and a step backwards from all the progress that has been made
>> in Swift 3 on that front.
>>
>>
>>>
>>>
>>>> 3) As has already been noted by many others, the suggested syntax for
>>>> prefix/postfix operators is overcomplicated. The proposal is:
>>>&

Re: [swift-evolution] [Review] SE-0091: Improving operator requirements in protocols

2016-05-18 Thread Nicola Salmoria via swift-evolution
On Wed, May 18, 2016 at 10:27 PM, Tony Allevato <allev...@google.com> wrote:

> On Wed, May 18, 2016 at 1:00 PM Nicola Salmoria <nicola.salmo...@gmail.com>
> wrote:
>
>> On Wed, May 18, 2016 at 8:03 PM, Tony Allevato <allev...@google.com>
>> wrote:
>>
>>> On Wed, May 18, 2016 at 10:02 AM Nicola Salmoria via swift-evolution <
>>> swift-evolution@swift.org> wrote:
>>>
>>>> > * What is your evaluation of the proposal?
>>>>
>>>> I'm generally in strong support, having long been a proponent of
>>>> removing
>>>> operators from protocols (the first occurrence was in this thread:
>>>> http://article.gmane.org/gmane.comp.lang.swift.evolution/7935)
>>>>
>>>> I have several comments about the details of the proposal, however.
>>>>
>>>> 1) At the beginning, in the "Proposed solution" section, the proposal
>>>> says
>>>> "This document does not propose that the current way of defining
>>>> operators
>>>> be removed or changed at this time. Rather, we describe an addition that
>>>> specifically provides improvements for protocol operator requirements."
>>>>
>>>> Later, however, there is a "Deprecation of non-static protocol
>>>> operators"
>>>> section which suggest to do exactly that, and this is reiterated in the
>>>> "Impact on existing code" section.
>>>>
>>>> Since I think that the deprecation of global operator overloads is the
>>>> crucial point of the proposal, I assume that the former is an oversight.
>>>>
>>>
>>> I could probably do a better job of clarifying the wording here. The
>>> proposal does *not* deprecate *all* global operator overloads. Global
>>> operators can still be implemented as they have been in Swift. So if you
>>> have a concrete type like `struct Matrix`, you can still define at the
>>> global level `func +(lhs: Matrix, rhs: Matrix) -> Matrix`.
>>>
>>> What's being deprecated is the current syntax used to define operator
>>> requirements inside protocols (by making the functions static) and the
>>> manner by which subtypes conform (ditto, through static methods instead of
>>> global functions).
>>>
>>
>> OK, I guess the unclear part is when you talk about "an addition that
>> specifically provides improvements for protocol operator requirements."
>> This is not just an addition; it's intended to completely replace the
>> protocol operator syntax.
>>
>>>
>>>
>>>> 2) The method signatures in the examples are not up to date with the
>>>> current
>>>> Swift 3 syntax. For example:
>>>>
>>>> protocol Equatable {
>>>>   static func ==(lhs: Self, rhs: Self) -> Bool
>>>> }
>>>>
>>>> should be:
>>>>
>>>> protocol Equatable {
>>>>   static func ==(_ lhs: Self, _ rhs: Self) -> Bool
>>>> }
>>>>
>>>
>>> Unless I'm mistaken, from looking at the Swift 3 branch of stdlib, the
>>> syntax changes don't appear to apply to operator functions. Since they are
>>> a special case that don't have argument labels, it wouldn't make sense to
>>> require them (or rather, the placeholders) here.
>>>
>>
>> I don't agree with this.
>>
>> Operators are called like this:
>>
>> x = y + z
>>
>> Of course it doesn't make sense to have parameter labels there.
>>
>> But the ones inside the protocol are not operators. They are methods, and
>> are called like methods. They happen to have funny names, but they are
>> still methods, and are called like this:
>>
>> x = T.+(y, z)
>>
>> In this case not only it makes sense for the parameters to have labels,
>> but making them behave differently from normal methods would be
>> inconsistent, and a step backwards from all the progress that has been made
>> in Swift 3 on that front.
>>
>
> What I'm saying is, if you look at the Swift 3 branch of stdlib, global
> operator functions still do not have argument labels. Picking one at
> random:
> https://github.com/apple/swift/blob/swift-3.0-branch/stdlib/public/core/String.swift#L329
>
> If you're arguing that those functions should be forced to include `_`
> placeholders, that's fine, but it's not accurate to say that the way
> they're written in this proposal is a step backwards from all the progr

Re: [swift-evolution] [Review] SE-0091: Improving operator requirements in protocols

2016-05-18 Thread Nicola Salmoria via swift-evolution
On Wed, May 18, 2016 at 10:03 PM, Matthew Johnson <matt...@anandabits.com>
wrote:

>
> On May 18, 2016, at 3:00 PM, Nicola Salmoria via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
>
> On Wed, May 18, 2016 at 8:03 PM, Tony Allevato <allev...@google.com>
> wrote:
>
>> On Wed, May 18, 2016 at 10:02 AM Nicola Salmoria via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> > * What is your evaluation of the proposal?
>>>
>>> I'm generally in strong support, having long been a proponent of removing
>>> operators from protocols (the first occurrence was in this thread:
>>> http://article.gmane.org/gmane.comp.lang.swift.evolution/7935)
>>>
>>> I have several comments about the details of the proposal, however.
>>>
>>> 1) At the beginning, in the "Proposed solution" section, the proposal
>>> says
>>> "This document does not propose that the current way of defining
>>> operators
>>> be removed or changed at this time. Rather, we describe an addition that
>>> specifically provides improvements for protocol operator requirements."
>>>
>>> Later, however, there is a "Deprecation of non-static protocol operators"
>>> section which suggest to do exactly that, and this is reiterated in the
>>> "Impact on existing code" section.
>>>
>>> Since I think that the deprecation of global operator overloads is the
>>> crucial point of the proposal, I assume that the former is an oversight.
>>>
>>
>> I could probably do a better job of clarifying the wording here. The
>> proposal does *not* deprecate *all* global operator overloads. Global
>> operators can still be implemented as they have been in Swift. So if you
>> have a concrete type like `struct Matrix`, you can still define at the
>> global level `func +(lhs: Matrix, rhs: Matrix) -> Matrix`.
>>
>> What's being deprecated is the current syntax used to define operator
>> requirements inside protocols (by making the functions static) and the
>> manner by which subtypes conform (ditto, through static methods instead of
>> global functions).
>>
>
> OK, I guess the unclear part is when you talk about "an addition that
> specifically provides improvements for protocol operator requirements."
> This is not just an addition; it's intended to completely replace the
> protocol operator syntax.
>
>>
>>
>>> 2) The method signatures in the examples are not up to date with the
>>> current
>>> Swift 3 syntax. For example:
>>>
>>> protocol Equatable {
>>>   static func ==(lhs: Self, rhs: Self) -> Bool
>>> }
>>>
>>> should be:
>>>
>>> protocol Equatable {
>>>   static func ==(_ lhs: Self, _ rhs: Self) -> Bool
>>> }
>>>
>>
>> Unless I'm mistaken, from looking at the Swift 3 branch of stdlib, the
>> syntax changes don't appear to apply to operator functions. Since they are
>> a special case that don't have argument labels, it wouldn't make sense to
>> require them (or rather, the placeholders) here.
>>
>
> I don't agree with this.
>
> Operators are called like this:
>
> x = y + z
>
> Of course it doesn't make sense to have parameter labels there.
>
> But the ones inside the protocol are not operators. They are methods, and
> are called like methods. They happen to have funny names, but they are
> still methods, and are called like this:
>
> x = T.+(y, z)
>
> In this case not only it makes sense for the parameters to have labels,
> but making them behave differently from normal methods would be
> inconsistent, and a step backwards from all the progress that has been made
> in Swift 3 on that front.
>
>
>>
>>
>>> 3) As has already been noted by many others, the suggested syntax for
>>> prefix/postfix operators is overcomplicated. The proposal is:
>>>
>>> // These are deprecated, of course, but used here just to serve as an
>>> // example.
>>> static prefix func ++(_ value: inout Self) -> Self
>>> static postfix func ++(_ value: inout Self) -> Self
>>>
>>> We don't need that. Since the 'operators' declared inside protocols are
>>> effectively just normal methods (apart from their names), we just need to
>>> name the parameters accordingly:
>>>
>>> static func ++(prefix value: inout Self) -> Self
>>> static func ++(postfix value: inout Self) -> Self
>>>
>>> 4) I

Re: [swift-evolution] [Review] SE-0091: Improving operator requirements in protocols

2016-05-18 Thread Nicola Salmoria via swift-evolution
> * What is your evaluation of the proposal?

I'm generally in strong support, having long been a proponent of removing
operators from protocols (the first occurrence was in this thread:
http://article.gmane.org/gmane.comp.lang.swift.evolution/7935)

I have several comments about the details of the proposal, however.

1) At the beginning, in the "Proposed solution" section, the proposal says
"This document does not propose that the current way of defining operators
be removed or changed at this time. Rather, we describe an addition that
specifically provides improvements for protocol operator requirements."

Later, however, there is a "Deprecation of non-static protocol operators"
section which suggest to do exactly that, and this is reiterated in the
"Impact on existing code" section.

Since I think that the deprecation of global operator overloads is the
crucial point of the proposal, I assume that the former is an oversight.

2) The method signatures in the examples are not up to date with the current
Swift 3 syntax. For example:

protocol Equatable {
  static func ==(lhs: Self, rhs: Self) -> Bool
}

should be:

protocol Equatable {
  static func ==(_ lhs: Self, _ rhs: Self) -> Bool
}

3) As has already been noted by many others, the suggested syntax for
prefix/postfix operators is overcomplicated. The proposal is:

// These are deprecated, of course, but used here just to serve as an
// example.
static prefix func ++(_ value: inout Self) -> Self
static postfix func ++(_ value: inout Self) -> Self

We don't need that. Since the 'operators' declared inside protocols are
effectively just normal methods (apart from their names), we just need to
name the parameters accordingly:

static func ++(prefix value: inout Self) -> Self
static func ++(postfix value: inout Self) -> Self

4) I don't agree with the request to limit to static methods for the
operator implementations.
I support this for symmetrical binary operators like +, but there are other
operators like += that seem to work better with members. That is, the
proposed declaration:

static func +=(_ lhs: inout Self, _ rhs: Self)

is more similar to the global += operator definition, but is less clear than:

mutating func +=(_ rhs: Self)

this is apparent also at the call site. With the proposed syntax, one would
need to do:

func +=(_ lhs: inout T, _ rhs: T) {
T.+=(lhs, rhs)
}

while with a member function this would read more naturally as:

func +=(_ lhs: inout T, _ rhs: T) {
lhs.+=(rhs)
}

5) the proposal mentions the open question of ambiguities between the dot
syntax to access methods and operators whose name starts with a dot.
This seems to be a real issue: I don't think

return T(minimum, maximum)

looks any good, even if the compiler was able to parse it.

However, this just means that the methods used to implement operators with
problematic names would need to use different names. Arguably, the only
cases where one would really want to use methods with operator names is for
arithmetical operators. Custom operators like ... are better expressed as
methods with more significant names.

6) It seems somewhat arbitrary to restrict method names to match an
operator, nor to put requirements on the function signature. I'd say there
are two cases, either the compiler can handle a method name that uses
special characters, or it can't. If it can't, matching an operator name
won't help. If it can, why put limits? There could be other creative uses of
such names, which we would be ruling out for no particular reason. This is
something that seems better left to the author of the protocol.

7) Automatic generation of trampoline functions is out of scope so I'm not
going to talk much about it, I only want to mention that it would make sense
to consider making such a feature as general as possible, instead of
focusing exclusively on operators.

For example, think of the common mathematical functions like sin, cos, etc.
It could make sense to give them the same treatment as operators, declaring
them as part of the FloatingPoint protocol but preserving the global
functions too.
It might even make sense to be able to create trampolines not only from
global space to a type, but also from one type to another type, or even for
all methods of a type (e.g. when boxing a value inside another type).

> * Is the problem being addressed significant enough to warrant a change to
Swift?

Absolutely. The handling of operators in protocols has been one of the worst
pain points in my use of Swift.

> * Does this proposal fit well with the feel and direction of Swift?

Yes; it significantly increases clarity and consistency.

> * If you have used other languages or libraries with a similar feature,
how do you feel that this proposal compares to those?

I only have experience with C++ operator overloading, which is much less
advanced.

> * How much effort did you put into your review? A glance, a quick reading,
or an in-depth study?

An in-depth study of the proposal, 

Re: [swift-evolution] [Review] SE-0081: Move where clause to end of declaration

2016-05-15 Thread Nicola Salmoria via swift-evolution
David Hart via swift-evolution  writes:

> 
> 
> Hi Karl,
> 
> As author of this proposal, the one about constraints on associated types,
and the one on type-aliases in protocols (all from the Generics Manifesto -
original authorship to Douglas Gregor) I’d like to provide additional
reasoning behind my wish to push this proposal through, as a whole.
> 
> First of all, there is a personal preference. I’ve used C# for many many
years, which has its where clause at the end of the declaration (like this
proposal), and I’ve used Swift since its unveiling. The experience with
using both styles for several years makes me favour this proposal’s syntax
because I find it much easier to read and format for readability.
> 
> Constraints on associated type will provide more expressivity but I doubt
it will greatly reduce protocol constraint clauses in a majority of cases.
And yes, type-aliases in protocols will shorten clauses, but I still think
they will more readable with the where clause at the end.
> 
> For example, here is a method I took (as-is) from the Standard Library
which has a few constraints, and which I further simplified if we imagine
that Sequence has an Element typealias for Iterator.Element:
> 
> 
> internal func _arrayOutOfPlaceReplace<
>  B : _ArrayBufferProtocol, C : Collection
>  where  C.Element == B.Element,
>  B.Index == Int
> >(  _ source: inout B, _ bounds: Range, _ newValues:
> C, _ insertCount: Int) {
> 
> See how the Standard Library authors formatted it for readability and how
as a consequence arguments which use the generic types are further apart
from the declaration of those generic types. But with this proposal, the
declaration might be formatted to:
> 
> internal func _arrayOutOfPlaceReplace(_ source: inout B,
> _ bounds: Range, _ newValues: C, _ insertCount: Int)
>  where
>  B : _ArrayBufferProtocol,
>  C : Collection,
>  C.Iterator.Element == B.Element,
>  B.Index == Int
> {
> 
> Do you need believe this is now more readable?
> 
> David.

Thanks for the real world example!

I think that the second arguably *looks* better. But is it more *readable*?
Not for me.

Let me try to do a brain dump while I mentally parse the declaration.

> internal func _arrayOutOfPlaceReplace(

Mmm, here we have a function that has something to do with arrays, generic
on two types. Maybe it will take an Array and output an Array?

> _ source: inout B,

Ah, the first argument is a B that will be changed. Maybe the function deals
with Array and will replace occurrences of 'source' with something else?

> _ bounds: Range,

Ok, this surely must be the range of the Array to operate on.

> _ newValues: C,

Oh, this parameter is called 'newValues', so C can't be a single value. It
must be a Collection, surely.

> _ insertCount: Int)

... I can't figure out what this could be.

>  where
>  B : _ArrayBufferProtocol,

Oh, B was some kind of buffer. OK so the function probably takes this
buffer, and replaces 'range' with 'newValues'

>  C : Collection,
>  C.Iterator.Element == B.Element,

Good, this confirms what I thought.

>  B.Index == Int

Looks like an implementation detail, I guess that's why 'range' is a
Range and 'insertCount' is an Int. Presumably the function needs to do
some operations that the generic Index doesn't guarantee.

So that's the end of it. I have a vague idea of what the function might do,
and had to revise my expectations a few times while reading its declaration.


Let's try again with the original declaration.

> internal func _arrayOutOfPlaceReplace<
>  B : _ArrayBufferProtocol, C : Collection

OK, here we have a function that deals with Arrays, generic on some buffer
thing and on a Collection. B is presumably what it needs to operate on, and
C will be the thing to replace with.

>  where  C.Element == B.Element,

Indeed thic confirms that B and C must be compatible.

>  B.Index == Int

Looks like an implementation detail, presumably we need to indicate the
position in the array where to do the replace.

> >(  _ source: inout B,

OK so this is a mutating function, and B is a buffer that will be modified.

> _ bounds: Range,

This is probably the range of the buffer that needs to be replaced, indeed
we had B.Index == Int.

> _ newValues: C,

And this collection contains what we need to insert in the buffer.

> _ insertCount: Int) {

Not sure what this might be, maybe the function will copy only the first
'insertCount' elements of C.

There we are. I read the declaration of the function from beginning to end
and gradually formed a rough understanding of it without needing to change
my expectations halfway through. I still have doubts about 'insertCount',
but I was at least able to formulate an hypothesis about its use.

YMMV, but as far as I'm concerned, the original declaration was much easier
to understand.

Now if we had generic typealiases, we could do something like

typealias CollectionOf = protocol where Collection.Element == T

and if my intuition 

Re: [swift-evolution] [Review] SE-0081: Move where clause to end of declaration

2016-05-14 Thread Nicola Salmoria via swift-evolution
> * What is your evaluation of the proposal?

-1.

I'm in strong agreement with what Karl Wagner and Jon Shier said.

The current 'where' syntax seems perfectly fine to me. It puts the
constraints in the logical place, next to the type declarations, which is
clear and intuitive.

The proposed change seems akin to declaring a variable:

var x

and then, several lines later, after unrelated code, specifying its type:

where x: Int

I can't see the advantage in doing that.

Yes, the 'where' statements can get long, but that's because they need to
express complex constraints. Moving them to a different place doesn't make
them any shorter, it just makes the problem less apparent by sweeping the
dirt under the carpet.

To make the 'where' statements better, what we need to do is make them
simpler. To do that, we need to reduce the complexity of the constraints
that need to be specified in a declaration.

The most obvious ways to do that are:
* add generic constraints to associatedtype;
* support typealias in protocols;
* add generic constraints to typealias.

Those improvements would allow to break up the complexity, making the
'where' clauses in declarations much shorter and simpler.

protocol Collection {
associatedtype Iterator: IteratorProtocol
typealias Element = Iterator.Element
associatedtype SubSequence: Sequence where SubSequence.Element == Element
}

typealias SortableCollection = protocol where
Collection.Element: Comparable

being able to use the above constructs would go a long way to making the
'where' clauses simpler without needing to change their syntax.

> * Is the problem being addressed significant enough to warrant a change to
Swift?

Yes, but the proposed change seems to do little to actually address the real
problem.

> * Does this proposal fit well with the feel and direction of Swift?

Swift excels at being terse and focused. The proposed change doesn't improve
terseness and reduces focus by putting related information in two different
places. So I don't think it is going in the right direction.

> * If you have used other languages or libraries with a similar feature,
how do you feel that this proposal compares to those?

I can't think of anything similar to this.

> * How much effort did you put into your review? A glance, a quick reading,
or an in-depth study?

A full reading of the proposal, a quick reading of the relevant threads, and
careful thought about the issue and my experience using Swift's type system.

Nicola


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


Re: [swift-evolution] [Draft] Introducing StaticSelf, an Invariant Self

2016-05-13 Thread Nicola Salmoria via swift-evolution
Matthew Johnson via swift-evolution  writes:

> I agree it’s a bit tricky.  But that’s better than not possible at all.
 You just need a typealias and a same type constraint to make this work as
expected / desired:
> 
> 
> protocol Makable {
> 
>   typealias RootMakable = StaticSelf
>   static func make(value: Int) -> StaticSelf
> }
>
> func makeWithZero(x: Int) -> T {
>   return T.make(value: 0) // works now
> }
> 
> 
> Now that we have a typealias we can refer to the binding of StaticSelf and
constrain it as necessary for whatever purpose we have in mind.  In some
cases that will be a same type constraint so that our code works properly
with class clusters.  I don’t have concrete examples of other use cases but
can imagine use cases constraining the typealias to a protocol, for example.

You can do that today:

protocol Makable {
associatedtype MadeType
static func make(value: Int) -> MadeType
}

func makeWithZero(x: Int) -> T {
return T.make(value: 0)
}

You can't currently constrain MadeType to be the same as the conforming
type, but, does it matter? What kind of extra guarantees would that give,
since you need to add the extra constraint anyway in generic code?

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


Re: [swift-evolution] [Draft] Introducing StaticSelf, an Invariant Self

2016-05-13 Thread Nicola Salmoria via swift-evolution
Matthew Johnson via swift-evolution  writes:

> Consider the following example, under the current system:
> protocol StringCreatable {
> static func createWithString(s: String) -> Self
> }
> 
> extension NSURL: StringCreatable {
>  // cannot conform because NSURL is non-final
>  // error: method 'createWithString' in non-final class 'NSURL' must
> return `Self` to conform to protocol 'A'
> }Introducing a static, invariant version of Self permits the desired
> conformance:
> protocol StringCreatable {
> static func createWithString(s: String) -> StaticSelf
> }

I'm not convinced by this example.

I think the problem to solve here is the interaction of protocols with
classes.
A related issue was illustrated by Tony Allevato here
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502
/016294.html

I think that before attempting to solve this specific problem introducing a
new notation, the general design of the interaction between protocols and
class inheritance should be reviewed.


Nicola

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


Re: [swift-evolution] [Review] SE-0073: Marking closures as executing exactly once

2016-05-04 Thread Nicola Salmoria via swift-evolution
> * What is your evaluation of the proposal?

-1. The proposed change seems to require a somewhat complex implementation
in the compiler, and I fail to see clear benefits in the change.

> * Is the problem being addressed significant enough to warrant a change to
Swift?

Frankly, I don't think the motivating example in the proposal is strong
enough. If the only purpose is to simplify certain imperative constructs, I
think there are better, functional-style, solutions.

The example related to autoreleasepool is particularly significant:

// Current Swift:
var x: Int = 0 // `var` declaration, with some irrelevant value
autoreleasepool {
x = 1
}

// Should SE-0061 be accepted:
let x = autoreleasepool {
return 1
}

// Should this proposal be accepted:
let x: Int
let y: String
autoreleasepool {
x = 1
y = "foo"
}

I would argue that of these three examples, the second is the clearest and
most readable; the last one, which should support the proposal, could simply
be rewritten as

let (x, y) = autoreleasepool {
return (1, "foo")
}

> * Does this proposal fit well with the feel and direction of Swift?

While it does build on the delayed initialization of let variables, which is
a peculiar feature of Swift, I don't think it fits the overall trend of
favoring functional constructs and discouraging reliance on side effects.

> * If you have used other languages or libraries with a similar feature,
how do you feel that this proposal
> compares to those?

I've never seen this kind of feature.

> * How much effort did you put into your review? A glance, a quick reading,
or an in-depth study?

A quick reading.

--
Nicola


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


[swift-evolution] [Proposal] Improving operator requirements in protocols

2016-05-03 Thread Nicola Salmoria via swift-evolution
> 4. What do you think about adding a rule to disallow defining member
> operators that don't satisfy a protocol requirement?
> 
> Dmitri

I’m wondering if we could go in the opposite direction, instead.

If I’m understanding the proposal correctly, it only boils down to relaxing the 
rules about naming of (static) methods: the other functionality needed to 
implement operators this way is already there.
What we are missing is that we currently have to use normal words to name the 
methods, because the Swift grammar reserves certain character to only be used 
by operators.

If I understood the rationale correctly, this limitation was a technical 
requirement to ensure the compiler doesn’t have to deal with ambiguous syntax.

It seems to me that if this proposal is taken to its logical conclusion, by 
completely forbidding operator declarations anywhere but at global scope, the 
source of the ambiguities should be removed, which should allow more freedom on 
method names.

To be clear, the rules would remain the same for global functions, but would 
become more relaxed for methods.

If we allowed this, it would be possible to revisit another proposal which was 
floated by some time ago to improve the names of functional vs. mutating 
methods. It would become possible to simply do e.g. instead of

func union(other: Self) -> Self
mutating func formUnion(other: Self)

we could simply to

func union(other: Self) -> Self
mutating func =union(other: Self)

and then

x = y.union(z)
y.=union(z) 

—
Nicola

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0067: Enhanced Floating Point Protocols

2016-04-26 Thread Nicola Salmoria via swift-evolution
On Tue, Apr 26, 2016 at 8:10 PM, Thorsten Seitz <tseit...@icloud.com> wrote:

> See inline.
>
> Am 26.04.2016 um 19:36 schrieb Nicola Salmoria via swift-evolution <
> swift-evolution@swift.org>:
>
> On Tue, Apr 26, 2016 at 4:28 PM, Tony Allevato <allev...@google.com>
> wrote:
>
>> On Sun, Apr 24, 2016 at 2:57 AM Nicola Salmoria via swift-evolution <
>> swift-evolution@swift.org> wrote:
>>
>>> > > func isEqual(to other: Self) ->Bool
>>> > > func isLess(than other: Self) ->Bool
>>> > > func isLessThanOrEqual(to other: Self) ->Bool
>>> >
>>> > I'm still not sure why these are methods instead of operators.
>>>
>>> I think this is an *excellent* choice, and I hope it is the first step
>>> to completely removing operators from protocols.
>>>
>>> IMHO throwing operators into protocols is inconsistent and confusing.
>>> Having regular methods and a single generic version of the operator that
>>> calls down on the type’s methods is clearer and guarantees that generic
>>> code can avoid ambiguities by calling the methods directly, instead of
>>> having to rely only on heavily overloaded global operators.
>>>
>>
>> I personally disagree on this point. To me, a protocol describes a set of
>> requirements for a type to fulfill, which includes things other than
>> methods. Just as a protocol can define initializers, properties, and
>> associated types that a type must define in order to conform, it makes
>> sense that a protocol would also define which operators a conforming type
>> must support.
>>
>
> Well, I'm not sure about that. A protocol describes what a type can do, so
> it's debatable whether a global function is within this scope.
>
> Operators are magically special: you can declare them inside a protocol
> and require them to be available for conformance, even if they don't belong
> to the type. You can't do the same thing for normal global functions, yet
> conceptually global functions and operators are the same thing.
>
>
>> Introducing a mapping between names and operators poses a few problems:
>>
>> – IMO, they are overly verbose and add noise to the definition. This
>> makes the language look less clean (I'm getting visions of NSDecimalNumber).
>> – They expose two ways to accomplish the same thing (writing
>> `x.isEqual(to: y)` and `x == y`).
>>
>
> That is my concern with this approach as well.
>
>
>
> – Do certain operators automatically get mapped to method names with
>> appropriate signatures across all types, or does a conforming type still
>> have to provide that mapping by implementing the operators separately? If
>> it's the latter, that's extra work for the author of the type writing the
>> protocol. If it's the former, does it make sense to automatically push
>> these operators for all types? Should any type that has an `add` method
>> automatically get `+` as a synonym as well? That may not be desirable.
>>
>
> The difference at the protocol declaration is between:
>
> protocol Equatable {
> func ==(lhs: Self, rhs: Self) -> Bool
> }
>
> and:
>
> protocol Equatable {
> func isEqual(to other: Self) -> Bool
> }
>
> func ==(lhs: T, rhs: T) -> Bool {
> return lhs.isEqual(to: rhs)
> }
>
> so the latter is a bit more verbose, but arguably clearer in intent, and
> not different from how you would define any generic global function using a
> protocol, or from how you can define protocol extensions with default
> implementations that take advantage of the protocol's core methods.
>
>
> The problem is that it is no longer clear whether to use the method or the
> operator to check for equality.
>
> Now if we had some access modifier to hide the isEqual method except for
> overwriting it and using it within the operator, maybe some variant of
> 'protected' (e.g. visible in implementors and the same file as the
> protocol) then that approach would be fine.
>
> -Thorsten
>

Why would you want to do that?

I see operators mostly as a convenience: a shortcut to express in a more
concise way something which should also be available through normal means.

It could be argued that generic code might prefer, for clarity, to use
explicit methods instead of vague global operators.

The approved but still unimplemented
https://github.com/apple/swift-evolution/blob/master/proposals/0042-flatten-method-types.md
also applies here, since the isEqual member method could also be used as a
static method for increased symmetry and clarity, i.e. instead of

_ = x.isEqual(to: y)

one could do

_ = Equ

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0067: Enhanced Floating Point Protocols

2016-04-26 Thread Nicola Salmoria via swift-evolution
On Tue, Apr 26, 2016 at 4:28 PM, Tony Allevato <allev...@google.com> wrote:

> On Sun, Apr 24, 2016 at 2:57 AM Nicola Salmoria via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> > > func isEqual(to other: Self) ->Bool
>> > > func isLess(than other: Self) ->Bool
>> > > func isLessThanOrEqual(to other: Self) ->Bool
>> >
>> > I'm still not sure why these are methods instead of operators.
>>
>> I think this is an *excellent* choice, and I hope it is the first step to
>> completely removing operators from protocols.
>>
>> IMHO throwing operators into protocols is inconsistent and confusing.
>> Having regular methods and a single generic version of the operator that
>> calls down on the type’s methods is clearer and guarantees that generic
>> code can avoid ambiguities by calling the methods directly, instead of
>> having to rely only on heavily overloaded global operators.
>>
>
> I personally disagree on this point. To me, a protocol describes a set of
> requirements for a type to fulfill, which includes things other than
> methods. Just as a protocol can define initializers, properties, and
> associated types that a type must define in order to conform, it makes
> sense that a protocol would also define which operators a conforming type
> must support.
>

Well, I'm not sure about that. A protocol describes what a type can do, so
it's debatable whether a global function is within this scope.

Operators are magically special: you can declare them inside a protocol and
require them to be available for conformance, even if they don't belong to
the type. You can't do the same thing for normal global functions, yet
conceptually global functions and operators are the same thing.


> Introducing a mapping between names and operators poses a few problems:
>
> – IMO, they are overly verbose and add noise to the definition. This makes
> the language look less clean (I'm getting visions of NSDecimalNumber).
> – They expose two ways to accomplish the same thing (writing
> `x.isEqual(to: y)` and `x == y`).
> – Do certain operators automatically get mapped to method names with
> appropriate signatures across all types, or does a conforming type still
> have to provide that mapping by implementing the operators separately? If
> it's the latter, that's extra work for the author of the type writing the
> protocol. If it's the former, does it make sense to automatically push
> these operators for all types? Should any type that has an `add` method
> automatically get `+` as a synonym as well? That may not be desirable.
>

The difference at the protocol declaration is between:

protocol Equatable {
func ==(lhs: Self, rhs: Self) -> Bool
}

and:

protocol Equatable {
func isEqual(to other: Self) -> Bool
}

func ==(lhs: T, rhs: T) -> Bool {
return lhs.isEqual(to: rhs)
}

so the latter is a bit more verbose, but arguably clearer in intent, and
not different from how you would define any generic global function using a
protocol, or from how you can define protocol extensions with default
implementations that take advantage of the protocol's core methods.

The difference for the conformance is between:

extension Foo : Equatable { }

func ==(lhs: Foo, rhs: Foo) -> Bool {
return 
}

and:

extension Bar : Equatable {
func isEqual(to: Bar) -> Bool {
return 
}
}

the former way to define the conformance can be confusing to newbies. The
latter is straightforward and consistent with the usual way to adopt a
protocol.

The == operator looks exactly the same at its use points, but the way how
it's implemented is different.
In the former case, it's many overloads of a global function, which can
stress the compiler's type inference and doesn't offer an obvious way to
disambiguate in case of ambiguities.
In the latter case, there is only one generic definition of ==, which
automatically applies to all types that conform to the protocol.

Nicola


> I'm very supportive of the floating-point protocol proposal in general,
> but I feel the arithmetic and comparison operations should be exposed by
> operators alone and not by methods, where there is a suitable operator that
> has the intended meaning.
>
>
>
>>
>> —
>> Nicola
>>
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


[swift-evolution] [Review #2] SE-0067: Enhanced Floating Point Protocols

2016-04-26 Thread Nicola Salmoria via swift-evolution
Forgive me if this has been answered already, but is

func isLessThanOrEqualTo(_ other: Self) -> Bool

really needed?

I understand the lack of trichotomy. But can’t this simply be implemented using 
the other existing methods?

Consider that the consumers of the types will normally use the global operators 
instead of the protocol methods. So instead of

func <= (lhs: T, rhs: T) -> Bool
{  
return lhs.isLessThanOrEqualTo(rhs)
}

it should be enough to do

func <= (lhs: T, rhs: T) -> Bool
{  
return lhs.isLess(than: rhs) || lhs.isEqual(to: rhs)
}

Or is there some case of x, y where (x <= y) is true but (x < y) and (x == y) 
are both false?

Thanks,
Nicola


> Hello Swift community,
> 
> Steve opted to revise his original proposal in order to incorporate great 
> feedback from the original review period. As such, we’re extending the review 
> period in order to get adequate consideration of his new changes. The 
> extended review of "SE-0067: Enhanced Floating Point Protocols" runs through 
> April 29. The proposal is available here:
> 
> https://github.com/apple/swift-evolution/blob/master/proposals/0067-floating-point-protocols.md
> 
> His previous revision is available here:
> 
> https://github.com/apple/swift-evolution/blob/fb1368a6a5474f57aa8f1846b5355d18753098f3/proposals/0067-floating-point-protocols.md
> 
> Reviews are an important part of the Swift evolution process. All reviews 
> should be sent to the swift-evolution mailing list at:
> 
> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> or, if you would like to keep your feedback private, directly to the review 
> manager.
> 
> What goes into a review?
> 
> The goal of the review process is to improve the proposal under review 
> through constructive criticism and, eventually, determine the direction of 
> Swift. When writing your review, here are some questions you might want to 
> answer in your review:
> 
> * What is your evaluation of the proposal?
> * Is the problem being addressed significant enough to warrant a change to 
> Swift?
> * Does this proposal fit well with the feel and direction of Swift?
> * If you have you used other languages or libraries with a similar feature, 
> how do you feel that this proposal compares to those?
> * How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> 
> More information about the Swift evolution process is available at
> 
> https://github.com/apple/swift-evolution/blob/master/process.md
> 
> Thank you,
> 
> -Chris Lattner
> Review Manager
> 
> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


[swift-evolution] [Review] SE-0066: Standardize function type argument syntax to require parentheses

2016-04-26 Thread Nicola Salmoria via swift-evolution
I agree with David.

I don’t think I’ve ever omitted parenthesis in the argument list of a closure; 
not only that, but I think that omitting them in that case *reduces* clarity, 
making the closure harder to parse visually.

Nicola

> What is your evaluation of the proposal?
> I reluctantly agree with the proposal with the following caveat: I do not 
> agree with the rationale to support being able to choose to omit the () for 
> the parameter list of the closure declaration.
> 
> I see no cohesive argument that says that the parens should be required in 
> some cases but not in others when talking about parameter lists.
> 
> I believe the proposal should be amended that the following should be the 
> only allowable forms:
> 
> y = x.sorted { (lhs : Int, rhs : Int) ->Bool in rhs y = x.sorted { (lhs, rhs) in rhs y = x.sorted { $1<$0 }
> 
> I’ve bolded the change above, today this is allowable:
> 
> y = x.sorted { lhs, rhs in rhs 
> I’ve read the argument about why it’s ok to elide the parens here, I simply 
> disagree with the author’s premise that this is a structurally significant 
> different form. Not requiring the parens for this parameter list begs the 
> question why other forms require them and provides a similar ambiguity of 
> whether the closure takes two parameters or a single tuple parameter from 
> both of these valid syntaxes today:
> 
> y = x.sorted { lhs, rhs in rhs y = x.sorted { (lhs, rhs) in rhs 
> I don’t see how this is fundamentally different than the example in the 
> “Motivation” section:
> 
> (Int, Float) ->Int // Takes two arguments, or takes one two-argument tuple?
> 
> While I will concede that `(lhs, rhs)` is not a valid tuple declaration, I’d 
> still argue that it’s too subtle of a difference to be used a primary means 
> of justification. If we are going to remove the ambiguity, let’s remove it 
> for all parameter list scenarios.
> 
> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> Potentially.
> 
> Does this proposal fit well with the feel and direction of Swift?
> Yes.
> 
> How much effort did you put into your review? A glance, a quick reading, or 
> an in-depth study?
> I participated in the original discussion thread as well as tested out many 
> different combinations function and closure syntax in the Swift Playground.
> 
> -David
> 
> 
> 
> > On Apr 25, 2016, at 9:22 PM, Douglas Gregor via 
> > swift-evolutionwrote:
> > 
> > Hello Swift community,
> > 
> > The review of SE-0066 "Standardize function type argument syntax to require 
> > parentheses" begins now and runs through May 2, 2016. The proposal is 
> > available here:
> > 
> > https://github.com/apple/swift-evolution/blob/master/proposals/0066-standardize-function-type-syntax.md
> > Reviews are an important part of the Swift evolution process. All reviews 
> > should be sent to the swift-evolution mailing list at
> > 
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> > or, if you would like to keep your feedback private, directly to the review 
> > manager. When replying, please try to keep the proposal link at the top of 
> > the message:
> > 
> > Proposal link:
> > 
> > https://github.com/apple/swift-evolution/blob/master/proposals/0066-standardize-function-type-syntax.md
> > Reply text
> > 
> > Other replies
> > What 
> > goes into a review?
> > 
> > The goal of the review process is to improve the proposal under review 
> > through constructive criticism and, eventually, determine the direction of 
> > Swift. When writing your review, here are some questions you might want to 
> > answer in your review:
> > 
> > What is your evaluation of the proposal?
> > Is the problem being addressed significant enough to warrant a change to 
> > Swift?
> > Does this proposal fit well with the feel and direction of Swift?
> > If you have used other languages or libraries with a similar feature, how 
> > do you feel that this proposal compares to those?
> > How much effort did you put into your review? A glance, a quick reading, or 
> > an in-depth study?
> > More information about the Swift evolution process is available at
> > 
> > https://github.com/apple/swift-evolution/blob/master/process.md
> > Thank you,
> > 
> > Doug Gregor
> > 
> > Review Manager
> > 
> > 
> > ___
> > swift-evolution mailing list
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org

[swift-evolution] [swift-evolution-announce] [Review] SE-0067: Enhanced Floating Point Protocols

2016-04-24 Thread Nicola Salmoria via swift-evolution
> > func isEqual(to other: Self) ->Bool
> > func isLess(than other: Self) ->Bool
> > func isLessThanOrEqual(to other: Self) ->Bool
>
> I'm still not sure why these are methods instead of operators.

I think this is an *excellent* choice, and I hope it is the first step to 
completely removing operators from protocols.

IMHO throwing operators into protocols is inconsistent and confusing. Having 
regular methods and a single generic version of the operator that calls down on 
the type’s methods is clearer and guarantees that generic code can avoid 
ambiguities by calling the methods directly, instead of having to rely only on 
heavily overloaded global operators.

—
Nicola

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


Re: [swift-evolution] [Proposal draft] Enhanced floating-point protocols

2016-04-16 Thread Nicola Salmoria via swift-evolution
> Oh, a couple more things I just thought of:
> 
> > public protocol Arithmetic: Equatable, IntegerLiteralConvertible {
> If your goals include supporting complex numbers, how is 
> IntegerLiteralConvertible going to fit in there?
> 
> > /// Initialize to zero
> > init()
> 0 is valuable as the additive identity. Should there also be a way to get 1, 
> the multiplicative identity? If you need both, should these be static 
> properties instead of initializers?

Interestingly, these two questions are related.

If you expose the multiplicative identity, you automatically expose a natural 
way to convert from an integer N: just add `one` to itself N times.
If N is negative, take the opposite.

For complex numbers the multiplicative identity is 1 + 0i, so this means that 
Complex(N) = N + 0i.

As an aside, a default generic implementation of IntegerLiteralConvertible 
would run in O(log N) steps, using the “double-and-add” algorithm:
https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Double-and-add.
Though I don’t think this is particularly useful for our use case :-)

—
Nicola

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


[swift-evolution] [Accepted] SE-0048: Generic Type Aliases

2016-04-16 Thread Nicola Salmoria via swift-evolution
> Proposal link: 
> https://github.com/apple/swift-evolution/blob/master/proposals/0048-generic-typealias.md
> 
> The review of SE-0048 “Generic Type aliases” ran from March 24…29, 2016. The 
> proposal received overwhelmingly positive feedback and has now been 
> implemented for Swift 3.
> 
> - Doug

Is this actually implemented fully?

The constraints on the typealias type don’t seem to work in the latest 
development snapshot (2016-04-12a):

typealias StringDict = Dictionary // error: type 'T' does not 
conform to protocol 'Hashable'
typealias StringDict = Dictionary   // error: type 
parameters may not be constrained in typealias argument list

—
Nicola

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


[swift-evolution] [Proposal draft] Enhanced floating-point protocols

2016-04-15 Thread Nicola Salmoria via swift-evolution
>   /// The quotient of `self` dividing by `rhs`.
>   //  Arithmetic provides a default implementation of this method in terms
>   //  of the mutating `divide` operation.
>   @warn_unused_result
>   func divided(by rhs: Self) -> Self
> 
>   /// Divides `self` by `rhs`.
>   mutating func divide(by rhs: Self)


When dealing with integer arithmetic, I often find useful a `divmod` function 
which produces a (quotient, remainder) pair.
It could be argued that such a pair is the primary result of division on 
integers. It would be great to have such a function included in the design.

> /// SignedArithmetic protocol will only be conformed to by signed numbers,
> /// otherwise it would be possible to negate an unsigned value.
> ///
> /// The only method of this protocol has the default implementation in an
> /// extension, that uses a parameterless initializer and subtraction.
> public protocol SignedArithmetic : Arithmetic {
>   func negate() -> Self
> }

It might make sense to also have a

public protocol InvertibleArithmetic : Arithmetic {
  func inverted() -> Self
}

FloatingPoint would conform to this protocol, returning 1/x, while integer 
types would not.

--
Nicola


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