Re: [swift-evolution] protocol-oriented integers (take 2)

2017-01-13 Thread Jacob Bandes-Storch via swift-evolution
Great work, all. I'm not sure I ever commented on SE-0104, so I've read
through this one more carefully. Here are some things that came to mind:

*## Arithmetic*

Why are ExpressibleByIntegerLiteral and init?(exactly:)
required? I could understand needing access to 0, but this could be
provided by a static property or nullary initializer. It doesn't seem like
all types supporting arithmetic operations would necessarily be convertible
from an arbitrary binary integer.


I tried to evaluate the Arithmetic protocol by considering what it means
for higher-dimensional types such as CGPoint and CGVector. My use case was
a linear interpolation function:

func lerp(from a: T, to b: T, by ratio: T) -> T {
return a + (b - a) * ratio
}

If I've read the proposal correctly, this definition works for integer and
floating-point values. But we can't make it work properly for CGVector (or,
perhaps less mathematically correct but more familiar, CGPoint). It's okay
to define +(CGVector, CGVector) and -(CGVector, CGVector), but *(CGVector,
CGVector) and /(CGVector, CGVector) don't make much sense. What we really
want is *(CGVector, *CGFloat*) and /(CGVector, *CGFloat*).

After consulting a mathematician, I believe what the lerp function really
wants is for its generic param to be an affine space
. I explored this a bit here:
https://gist.github.com/jtbandes/93eeb7d5eee8e1a7245387c660d
53b03#file-affine-swift-L16-L18

This approach is less restrictive and more composable than the proposed
Arithmetic protocol, which can be viewed as a special case with the
following definitions:

extension Arithmetic: AffineSpace, VectorSpace {  // not actually
allowed in Swift
typealias Displacement = Self
typealias Scalar = Self
}

It'd be great to be able to define a lerp() which works for all
floating-point and integer numbers, as well as points and vectors (assuming
a glorious future where CGPoint and CGVector have built-in arithmetic
operations). But maybe the complexity of these extra protocols isn't worth
it for the stdlib...


*## BinaryInteger*

I'm a little confused by the presence of init(extendingOrTruncating:) for
*all* binary integers. Why does it make sense to be able to write
UInt16(extendingOrTruncating: (-21 as Int8)) ? In my mind, sign-extension
only has meaning when the source and destination types are both signed.

Although I would not be against a clamp() function in the standard library,
"init(clamping:)" sounds strange to me. What about calling it
"init(nearestTo:)"?  One could also define a FloatingPoint version of
init(nearestTo:), i.e. lround(). For maximum annoyance and explicitness,
you could even rename the existing init(_:) to init(truncating:) to make it
clear that truncation, not regular rounding, occurs when converting from
floating-point.

*... masking shifts*

The example claims that "(30 as UInt8) &>> 11" produces 3, because it
right-shifts 30 by 3. But isn't the bitWidth of UInt8 always 8 since it's a
fixed-width type? Why should 11 get masked to 3 before the shift? (Also, it
might be a good idea to choose examples with numbers whose base-ten
representations don't look like valid binary. ) What use cases are there
for masking shifts? I was under the impression that "smart shifts" were
pretty much how the usual shift instructions already behaved.

(Minor: were the smart shift operators supposed to be included as
BinaryInteger protocol requirements? I only see them in the "heterogeneous
shifts" extension.)

*... init(_ source: T)*

Now a thought experiment: suppose you wanted to write an
arbitrary-precision BigInt, or any binary integer such as Int256. The
BinaryInteger protocol requires you to provide init(_
source: T). Given the source of type T, how do you access its bits? Is
repeated use of word(at:) the recommended way? If so, it might be nice to
include a "wordCount" returning the number of available words; otherwise I
suppose the user has to use something like bitWidth/(8*MemoryLayout.size),
which is pretty ugly.


*## FixedWidthInteger*

Why is popcount restricted to FixedWidthInteger? It seems like it could
theoretically apply to any UnsignedInteger.


*## Heterogenous shifts, equality, and comparison*

These look great. How will the default implementations be provided?
(Equivalent question: how would a user define their own heterogeneous
operators?) I suppose this works:

static func &>> (lhs: Self, rhs: Other) -> Self {
// delegate to the protocol requirement &>>(Self, Self)
return self &>> Self(extendingOrTruncating: rhs)
}

But for operations you can't delegate so easily... I'm imagining trying to
implement heterogeneous comparison (i.e. < ) and the best I can come up
with uses signum() and word(at:)...

Also, should these be protocol requirements so user-defined types can
specialize them?


*## Masking arithmetic*

Do &* and &+ and &- need their operands to have the same type, or could

Re: [swift-evolution] Generic Subscripts

2017-01-13 Thread Brent Royal-Gordon via swift-evolution
> On Jan 13, 2017, at 9:50 AM, John McCall via swift-evolution 
>  wrote:
> 
> I'm also not sure we'd ever want the element type to be inferred from context 
> like this.  Generic subscripts as I see it are about being generic over 
> *indexes*, not somehow about presenting a polymorphic value.

I think I have a pretty good use case for generic element types: you may want 
an index to carry the type of its element. For example, suppose you want to 
have a sort of dictionary whose keys are unique instances of a key class, and 
whose value type depends on the key instance:

struct TypedDictionary {
final class Key: Hashable {
init(of type: T.Type) {}

var hashValue: Int { return 
ObjectIdentifier(self).hashValue }
static func == (lhs: Key, rhs: Key) { return lhs === 
rhs }
}

private var storage: [AnyHashable: Any] = [:]

subscript(key: Key) -> T? {
get {
return storage[key] as! T?
}
set {
storage[key] = newValue as Any?
}
}
}

let messageKey = TypedDictionary.Key(of: String.self)
let answerKey = TypedDictionary.Key(of: Int.self)

var myDict = TypedDictionary()
myDict[messageKey] = "Hello, world!"
myDict[answerKey] = 42

I've wanted to do things like this in at least three or four different 
contexts; you could even imagine reflection being implemented this way, with 
typed `PropertyKey`s and a subscript available on all instances. You can work 
around it with methods, but it always feels unnatural, with vacuous method 
names like `value(for:)`.

I do agree that it is probably useless and certainly a little dangerous to have 
a generic parameter that's completely inferred from the return value, but you 
could make the same argument for methods, and yet we allow them there.

-- 
Brent Royal-Gordon
Architechies

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


Re: [swift-evolution] protocol-oriented integers (take 2)

2017-01-13 Thread Xiaodi Wu via swift-evolution
Thanks, that's very helpful. Yes, my question was more directed to those
situations that can't be optimized away. It's good to know that the maximum
total cost is an and and a shift, which is what it sounded like but wasn't
made explicit.
On Fri, Jan 13, 2017 at 17:25 Stephen Canon  wrote:

> > On Jan 13, 2017, at 5:14 PM, Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > [Resending to list with original message removed for length.]
> >
> > This is fantastic. Glad to see it take shape. Very neat and insightful
> to have trailingZeros on BinaryInteger but leadingZeros on
> FixedWidthInteger. A couple of questions on smart shifts: What is the
> performance penalty as compared to the existing operators? Beyond
> performance, what are the implications for migrating existing bit twiddling
> algorithms written in Swift 3?
>
> Hi Xiaodi —
>
> I don’t want to speak for Max and Dave, but I think I can provide some
> insight for your questions about shifts.
>
> First, the overwhelming majority of shifts have a compile-time-constant
> RHS. For these cases, there’s no performance change (except that the smart
> shifts may be able to optimize away the entire expression if the shift is
> overlarge).
>
> For smart shifts with non-constant right-hand sides, the compiler will
> frequently still be able to prove that the shift count is always positive
> or negative and less than word size (this handles a lot of the most common
> cases like normalizing an integer, reading from a bitstream, or shifting
> words of a bignum); again there’s no performance penalty.
>
> In the remaining cases where the compiler cannot bound the right-hand
> side, there will be some branches present; there may be a few regressions
> from these cases, but I expect most to be small (and the code
> simplifications are well worth it).  Users can always use the masking
> shifts, which lower to single instructions for 32b and 64b integers types
> on Intel and arm64, and which are at worst an and and a shift (two very
> cheap instructions) on other architectures.
>
> Basically, I expect there to be no perf impact for almost all code, and
> that the perf impact is relatively easily mitigated when it does occur.
> This is an easy tradeoff for fully-defined and sensible operator behavior.
>
> – Steve
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Tony Allevato via swift-evolution
Such a proposed syntax doesn't solve the general problem though, which is
that comparing two enum values requires enumerating all of the cases to
test whether they are (1) the same and (2) have the same associated values,
if any. The desire here is to get rid of the boilerplate that users must
write to implement simple equality (and hashability, in the case of my
proposal draft), similarly to how enums without associated values already
get Equatable and Hashable for free.


On Fri, Jan 13, 2017 at 3:37 PM Derrick Ho via swift-evolution <
swift-evolution@swift.org> wrote:

> I think it is better to create a syntax for getting the associated values
> and then comparing them.
>
> enum Option {
> case foo(String)
> case bar(Int)
> case zip
> }
>
> let op = Option.foo("hello")
> let bb = Option.foo("world")
>
> // proposed tuple-like syntax
>
> op.foo.0 // returns Optional("hello")
>
> // then we can compare values directly
>
> if op.foo.0 == bb.foo.0 {
> // ...
> }
>
> On Fri, Jan 13, 2017 at 5:44 PM Slava Pestov via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Jan 13, 2017, at 2:30 PM, David Sweeris via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> On Jan 13, 2017, at 15:10, Anton Zhilin via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> That seems pretty close to Rust’s derive. Why not invent a similar syntax
> in Swift? Otherwise it will make us look through all the sources to make
> sure deriving is used.
>
> enum Option: @derive Equatable {
> ...
> }
>
> Also, we can get better looking compilation errors, like:
>
> ERROR at line 1, col 14: could not derive Equatable for Option
> enum Option: @derive Equatable {
>  ^
>
>
> I think that idea came up once before... can't remember where, though, or
> what we thought of it at the time.
>
> As far as reducing enum boilerplate, what about borrowing the generic
> system's syntax and looking at it from the switch's PoV?
> func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
> switch  (lhs, rhs) {
> case (c(let lVal), c(let rVal)): // both lhs and rhs are "c" and the
> same case
> return lVal == rVal //syntax error if `==` isn't defined for the
> associated value types of every case
> default: return false
> }
> }
>
>
> I think initially, we would like to implement deriving these witnesses
> directly in the compiler, instead of trying to come up with a
> metaprogramming syntax for them.
>
> Slava
>
>
> - Dave Sweeris
> ___
> 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 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


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Derrick Ho via swift-evolution
I think it is better to create a syntax for getting the associated values
and then comparing them.

enum Option {
case foo(String)
case bar(Int)
case zip
}

let op = Option.foo("hello")
let bb = Option.foo("world")

// proposed tuple-like syntax

op.foo.0 // returns Optional("hello")

// then we can compare values directly

if op.foo.0 == bb.foo.0 {
// ...
}

On Fri, Jan 13, 2017 at 5:44 PM Slava Pestov via swift-evolution <
swift-evolution@swift.org> wrote:

> On Jan 13, 2017, at 2:30 PM, David Sweeris via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> On Jan 13, 2017, at 15:10, Anton Zhilin via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> That seems pretty close to Rust’s derive. Why not invent a similar syntax
> in Swift? Otherwise it will make us look through all the sources to make
> sure deriving is used.
>
> enum Option: @derive Equatable {
> ...
> }
>
> Also, we can get better looking compilation errors, like:
>
> ERROR at line 1, col 14: could not derive Equatable for Option
> enum Option: @derive Equatable {
>  ^
>
>
> I think that idea came up once before... can't remember where, though, or
> what we thought of it at the time.
>
> As far as reducing enum boilerplate, what about borrowing the generic
> system's syntax and looking at it from the switch's PoV?
> func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
> switch  (lhs, rhs) {
> case (c(let lVal), c(let rVal)): // both lhs and rhs are "c" and the
> same case
> return lVal == rVal //syntax error if `==` isn't defined for the
> associated value types of every case
> default: return false
> }
> }
>
>
> I think initially, we would like to implement deriving these witnesses
> directly in the compiler, instead of trying to come up with a
> metaprogramming syntax for them.
>
> Slava
>
>
> - Dave Sweeris
> ___
> 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 mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] protocol-oriented integers (take 2)

2017-01-13 Thread Stephen Canon via swift-evolution
> On Jan 13, 2017, at 5:14 PM, Xiaodi Wu via swift-evolution 
>  wrote:
> 
> [Resending to list with original message removed for length.]
> 
> This is fantastic. Glad to see it take shape. Very neat and insightful to 
> have trailingZeros on BinaryInteger but leadingZeros on FixedWidthInteger. A 
> couple of questions on smart shifts: What is the performance penalty as 
> compared to the existing operators? Beyond performance, what are the 
> implications for migrating existing bit twiddling algorithms written in Swift 
> 3?

Hi Xiaodi —

I don’t want to speak for Max and Dave, but I think I can provide some insight 
for your questions about shifts.

First, the overwhelming majority of shifts have a compile-time-constant RHS. 
For these cases, there’s no performance change (except that the smart shifts 
may be able to optimize away the entire expression if the shift is overlarge).

For smart shifts with non-constant right-hand sides, the compiler will 
frequently still be able to prove that the shift count is always positive or 
negative and less than word size (this handles a lot of the most common cases 
like normalizing an integer, reading from a bitstream, or shifting words of a 
bignum); again there’s no performance penalty.

In the remaining cases where the compiler cannot bound the right-hand side, 
there will be some branches present; there may be a few regressions from these 
cases, but I expect most to be small (and the code simplifications are well 
worth it).  Users can always use the masking shifts, which lower to single 
instructions for 32b and 64b integers types on Intel and arm64, and which are 
at worst an and and a shift (two very cheap instructions) on other 
architectures.

Basically, I expect there to be no perf impact for almost all code, and that 
the perf impact is relatively easily mitigated when it does occur. This is an 
easy tradeoff for fully-defined and sensible operator behavior.

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


Re: [swift-evolution] protocol-oriented integers (take 2)

2017-01-13 Thread Max Moiseev via swift-evolution
Hi Xiaodi,

>  What is the performance penalty as compared to the existing operators?

First of all, I don’t have the concrete numbers unfortunately. But…
If we are talking about concrete types, there should be very little difference 
between the two smart and masking shifts.
For example, the following functions:

public func foo(x: UInt) -> UInt {
  return x >> 32
}

public func bar(x: UInt) -> UInt {
  return x &>> 32
}

Produce equivalent SIL and LLVM IR when compiled with optimizations. Moreover, 
if you change 32 to 100, then foo will become something like:

foo(x: UInt) { return 0 }

whereas bar will still call the llvm.shl.

> Beyond performance, what are the implications for migrating existing bit 
> twiddling algorithms written in Swift 3?
Let’s take for example the ‘&>>” operator. There are 2 overloads: &>>(Self, 
Self) and &>>(Self, Other)
(In Swift 3 there is only one version of >>, that takes both arguments of the 
same type.)

So, in an expression `x &>> 32`, compiler assumes 32 to have type Int (which is 
the default type for the integer literals) and prefer the heterogeneous 
overload. It might not be too bad, as I showed in examples above, but in order 
to increase chances of success you might want to specify an explicit type 
context, as in `x &>> (32 as TypeOfX)`.

As always, only concrete benchmarks will tell. We spent many hours optimizing 
the implementation for our existing benchmark suite.

Max

> On Jan 13, 2017, at 2:14 PM, Xiaodi Wu  wrote:
> 
> [Resending to list with original message removed for length.]
> 
> This is fantastic. Glad to see it take shape. Very neat and insightful to 
> have trailingZeros on BinaryInteger but leadingZeros on FixedWidthInteger. A 
> couple of questions on smart shifts: What is the performance penalty as 
> compared to the existing operators? Beyond performance, what are the 
> implications for migrating existing bit twiddling algorithms written in Swift 
> 3?
> 

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


Re: [swift-evolution] Range and ClosedRange

2017-01-13 Thread Xiaodi Wu via swift-evolution
On Fri, Jan 13, 2017 at 2:05 PM, Max Moiseev via swift-evolution <
swift-evolution@swift.org> wrote:

> FWIW, the common RangeProtocol unifying both Range and ClosedRange existed
> for a while when the new collection indexing model was being implemented.
>
> Here is the commit removing it: https://github.com/apple/
> swift/pull/2108/commits/8e886a3bdded61e266678704a13edce00a4a8867
>
> Max
>

>From the commit: "The RangeProtocol was a very weak and fragile abstraction
because it didn't specify the interpretation of the endpoints.  To write a
non-trivial algorithm, one usually needed to consult that information."

As I argued (perhaps inarticulately) above, I think it may be worthwhile
revisiting the abstraction once conditional conformances become possible.
We can say more about the relationship between the endpoints of half-open
and closed _countable_ ranges than we can of uncountable ones.


>
> On Jan 12, 2017, at 12:11 PM, David Hart via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Hello,
>
> Since the release of Swift 3, I’ve seen quite a few people (me included)
> experience a lot of friction with the new types for representing ranges.
> I’ve seen people confused when writing an API that takes a Range as
> argument but then can’t pass in a ClosedRange. Sometimes this can be fixed
> because the API should be written against a more general protocol, but
> sometimes that’s not the case.
>
> Those new types definitely seem to cause more problems than they fixed
> (the Int.max problem). Has the Standard Library team put any thought into
> this?
>
> Regards,
> David.
> ___
> 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 mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Slava Pestov via swift-evolution

> On Jan 13, 2017, at 2:30 PM, David Sweeris via swift-evolution 
>  wrote:
> 
> 
> On Jan 13, 2017, at 15:10, Anton Zhilin via swift-evolution 
> > wrote:
> 
>> That seems pretty close to Rust’s derive. Why not invent a similar syntax in 
>> Swift? Otherwise it will make us look through all the sources to make sure 
>> deriving is used.
>> 
>> enum Option: @derive Equatable {
>> ...
>> }
>> Also, we can get better looking compilation errors, like:
>> 
>> ERROR at line 1, col 14: could not derive Equatable for Option
>> enum Option: @derive Equatable {
>>  ^
> 
> I think that idea came up once before... can't remember where, though, or 
> what we thought of it at the time.
> 
> As far as reducing enum boilerplate, what about borrowing the generic 
> system's syntax and looking at it from the switch's PoV?
> func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
> switch  (lhs, rhs) {
> case (c(let lVal), c(let rVal)): // both lhs and rhs are "c" and the same 
> case
> return lVal == rVal //syntax error if `==` isn't defined for the 
> associated value types of every case
> default: return false
> }
> }

I think initially, we would like to implement deriving these witnesses directly 
in the compiler, instead of trying to come up with a metaprogramming syntax for 
them.

Slava

> 
> - Dave Sweeris
> ___
> 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


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread David Sweeris via swift-evolution

> On Jan 13, 2017, at 15:10, Anton Zhilin via swift-evolution 
>  wrote:
> 
> That seems pretty close to Rust’s derive. Why not invent a similar syntax in 
> Swift? Otherwise it will make us look through all the sources to make sure 
> deriving is used.
> 
> enum Option: @derive Equatable {
> ...
> }
> Also, we can get better looking compilation errors, like:
> 
> ERROR at line 1, col 14: could not derive Equatable for Option
> enum Option: @derive Equatable {
>  ^

I think that idea came up once before... can't remember where, though, or what 
we thought of it at the time.

As far as reducing enum boilerplate, what about borrowing the generic system's 
syntax and looking at it from the switch's PoV?
func == (lhs: MyEnum, rhs: MyEnum) -> Bool {
switch  (lhs, rhs) {
case (c(let lVal), c(let rVal)): // both lhs and rhs are "c" and the same 
case
return lVal == rVal //syntax error if `==` isn't defined for the 
associated value types of every case
default: return false
}
}

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


Re: [swift-evolution] protocol-oriented integers (take 2)

2017-01-13 Thread Xiaodi Wu via swift-evolution
[Resending to list with original message removed for length.]

This is fantastic. Glad to see it take shape. Very neat and insightful to
have trailingZeros on BinaryInteger but leadingZeros on FixedWidthInteger.
A couple of questions on smart shifts: What is the performance penalty as
compared to the existing operators? Beyond performance, what are the
implications for migrating existing bit twiddling algorithms written in
Swift 3?
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Slava Pestov via swift-evolution

> On Jan 13, 2017, at 12:14 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I think the “when all their associated values were Equatable” is the 
> technical issue holding this type of thing up.  The ability to spell that 
> type of thing is on the generics roadmap, but I don’t know when it will 
> actually happen.  There seem to be a lot of things on hold because of it.

The proposal for conditional conformances was accepted. However, right now the 
generics feature being worked on is recursive conformances, together with a 
large overall cleanup of the generics implementation to fix bugs and improve 
correctness. Conditional conformances will come at some point after that.

Slava

> 
> Thanks,
> Jon
> 
>> On Jan 13, 2017, at 11:51 AM, Adam Shin via swift-evolution 
>> > wrote:
>> 
>> When using enums with associated values, it's often necessary to check for 
>> equality between two enum objects in some way. That can lead to boilerplate 
>> code like this:
>> 
>> enum Option {
>> case foo(String)
>> case bar(Int)
>>  case zip
>> }
>> 
>> func ==(lhs: Option, rhs: Option) -> Bool {
>> switch (lhs, rhs) {
>> case (.foo(let a), .foo(let b)) where a == b: return true
>> case (.bar(let a), .bar(let b)) where a == b: return true
>> case (.zip, .zip): return true
>> default: return false
>> }
>> }
>> 
>> ..which results in code duplication and opens the door to potential logic 
>> errors.
>> 
>> Instead, what if enums with associated values were automatically Equatable 
>> when all their associated values were Equatable? That would remove the need 
>> for such boilerplate code.
>> 
>> The Swift language guide states that custom classes and structs don't 
>> receive a default implementation of the == operator because the compiler 
>> can't guess what "equality" means for them. However, I think this could make 
>> sense for enums. An enum case, even with associated values, seems closer to 
>> a value itself than an object with logic and state.
>> 
>> I'd be interested to hear any thoughts on this. Would this be a beneficial 
>> addition?
>> ___
>> 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 mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Slava Pestov via swift-evolution

> On Jan 13, 2017, at 1:15 PM, Tony Allevato via swift-evolution 
>  wrote:
> 
> This is a request that comes up frequently; I wrote an early draft proposal 
> for it several months ago, with it covering all value types, not just enums, 
> and also including Hashable as well as Equatable:
> 
> https://gist.github.com/allevato/2fd10290bfa84accfbe977d8ac07daad 
> 
> 
> Since it's purely additive, it won't get much attention until phase 2 at the 
> earliest, but I'd like to revisit it then. Most of the discussion before 
> revolved around to what degree users should have to opt-in or opt-out of this 
> functionality.

I think if someone were to implement this though, we would be happy to merge it 
in. The code for deriving Equatable and Hashable conformances is in these files:

lib/Sema/CodeSynthesis.cpp
lib/Sema/DerivedConformances.cpp
lib/Sema/DerivedConformanceEquatableHashable.cpp

I agree it should be opt-in though (I would also argue that even the no-payload 
enum behavior should be opt-in, but that ship has sailed).

> 
> Re: generics, I don't think there's anything on the roadmap that goes into 
> such deep detail as "if every associated value of every enum case is 
> Equatable, then X is also Equatable", and I don't think there would be a 
> clean way to express that with the generics syntax. This would probably have 
> to be something that's baked into the compiler to synthesize == and hashValue 
> for types that satisfy the constraints.

The generics feature people are thinking of is conditional conformances:

extension Array : Equatable where Element == Equatable { … }

However it does not solve the problem for enums with associated values because 
as you said there’s no way to quantify over ‘all associated values’ in the 
language, and this is not planned.

Slava

> 
> 
> On Fri, Jan 13, 2017 at 12:31 PM David Sweeris via swift-evolution 
> > wrote:
> 
> 
> 
> Sent from my iPhone
> On Jan 13, 2017, at 13:51, Adam Shin via swift-evolution 
> > wrote:
> 
>> When using enums with associated values, it's often necessary to check for 
>> equality between two enum objects in some way. That can lead to boilerplate 
>> code like this:
>> 
>> enum Option {
>> case foo(String)
>> case bar(Int)
>>  case zip
>> }
>> 
>> func ==(lhs: Option, rhs: Option) -> Bool {
>> switch (lhs, rhs) {
>> case (.foo(let a), .foo(let b)) where a == b: return true
>> case (.bar(let a), .bar(let b)) where a == b: return true
>> case (.zip, .zip): return true
>> default: return false
>> }
>> }
>> 
>> ..which results in code duplication and opens the door to potential logic 
>> errors.
>> 
>> Instead, what if enums with associated values were automatically Equatable 
>> when all their associated values were Equatable? That would remove the need 
>> for such boilerplate code.
>> 
>> The Swift language guide states that custom classes and structs don't 
>> receive a default implementation of the == operator because the compiler 
>> can't guess what "equality" means for them. However, I think this could make 
>> sense for enums. An enum case, even with associated values, seems closer to 
>> a value itself than an object with logic and state.
>> 
>> I'd be interested to hear any thoughts on this. Would this be a beneficial 
>> addition?
> 
> I think it makes more sense to come up with some syntax for reducing that 
> kind of boilerplate code in general. In "pseudo-english", I'd write the == 
> function as "if lhs and rhs are the same case && their associated values are 
> the equal, return true, else return false".
> 
> What about doing something with the reflection system? Isn't that supposed to 
> get overhauled for Swift 4? I'm not sure what the performance implications 
> would be, though.
> 
> - Dave Sweeris 
> ___
> 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 mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Joe Groff via swift-evolution

> On Jan 13, 2017, at 1:10 PM, Anton Zhilin via swift-evolution 
>  wrote:
> 
> That seems pretty close to Rust’s derive. Why not invent a similar syntax in 
> Swift? Otherwise it will make us look through all the sources to make sure 
> deriving is used.
> 
> enum Option: @derive Equatable {
> ...
> }

My feeling on this is that it feels strange to treat compiler-provided default 
implementations as different from library-provided default implementations. If 
the library provides a protocol extension with an appropriate default 
implementation for your type, you get it without any work on your part. While 
the Equatable/Hashable/Comparable conformance would most practically compiler 
generated today, you could imagine a far future version of Swift having 
sufficiently powerful generic type traits to do this in the library.

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


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Anton Zhilin via swift-evolution
That seems pretty close to Rust’s derive. Why not invent a similar syntax
in Swift? Otherwise it will make us look through all the sources to make
sure deriving is used.

enum Option: @derive Equatable {
...
}

Also, we can get better looking compilation errors, like:

ERROR at line 1, col 14: could not derive Equatable for Option
enum Option: @derive Equatable {
 ^

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


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Tony Allevato via swift-evolution
This is a request that comes up frequently; I wrote an early draft proposal
for it several months ago, with it covering all value types, not just
enums, and also including Hashable as well as Equatable:

https://gist.github.com/allevato/2fd10290bfa84accfbe977d8ac07daad

Since it's purely additive, it won't get much attention until phase 2 at
the earliest, but I'd like to revisit it then. Most of the discussion
before revolved around to what degree users should have to opt-in or
opt-out of this functionality.

Re: generics, I don't think there's anything on the roadmap that goes into
such deep detail as "if every associated value of every enum case is
Equatable, then X is also Equatable", and I don't think there would be a
clean way to express that with the generics syntax. This would probably
have to be something that's baked into the compiler to synthesize == and
hashValue for types that satisfy the constraints.


On Fri, Jan 13, 2017 at 12:31 PM David Sweeris via swift-evolution <
swift-evolution@swift.org> wrote:

>
>
>
> Sent from my iPhone
> On Jan 13, 2017, at 13:51, Adam Shin via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> When using enums with associated values, it's often necessary to check for
> equality between two enum objects in some way. That can lead to boilerplate
> code like this:
>
> enum Option {
> case foo(String)
> case bar(Int)
> case zip
> }
>
> func ==(lhs: Option, rhs: Option) -> Bool {
> switch (lhs, rhs) {
> case (.foo(let a), .foo(let b)) where a == b: return true
> case (.bar(let a), .bar(let b)) where a == b: return true
> case (.zip, .zip): return true
> default: return false
> }
> }
>
> ..which results in code duplication and opens the door to potential logic
> errors.
>
> Instead, what if enums with associated values were automatically Equatable
> when all their associated values were Equatable? That would remove the need
> for such boilerplate code.
>
> The Swift language guide states that custom classes and structs don't
> receive a default implementation of the == operator because the compiler
> can't guess what "equality" means for them. However, I think this could
> make sense for enums. An enum case, even with associated values, seems
> closer to a value itself than an object with logic and state.
>
> I'd be interested to hear any thoughts on this. Would this be a beneficial
> addition?
>
>
> I think it makes more sense to come up with some syntax for reducing that
> kind of boilerplate code in general. In "pseudo-english", I'd write the ==
> function as "if lhs and rhs are the same case && their associated values
> are the equal, return true, else return false".
>
> What about doing something with the reflection system? Isn't that supposed
> to get overhauled for Swift 4? I'm not sure what the performance
> implications would be, though.
>
> - Dave Sweeris
> ___
> 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


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread David Sweeris via swift-evolution



Sent from my iPhone
> On Jan 13, 2017, at 13:51, Adam Shin via swift-evolution 
>  wrote:
> 
> When using enums with associated values, it's often necessary to check for 
> equality between two enum objects in some way. That can lead to boilerplate 
> code like this:
> 
> enum Option {
> case foo(String)
> case bar(Int)
>   case zip
> }
> 
> func ==(lhs: Option, rhs: Option) -> Bool {
> switch (lhs, rhs) {
> case (.foo(let a), .foo(let b)) where a == b: return true
> case (.bar(let a), .bar(let b)) where a == b: return true
> case (.zip, .zip): return true
> default: return false
> }
> }
> 
> ..which results in code duplication and opens the door to potential logic 
> errors.
> 
> Instead, what if enums with associated values were automatically Equatable 
> when all their associated values were Equatable? That would remove the need 
> for such boilerplate code.
> 
> The Swift language guide states that custom classes and structs don't receive 
> a default implementation of the == operator because the compiler can't guess 
> what "equality" means for them. However, I think this could make sense for 
> enums. An enum case, even with associated values, seems closer to a value 
> itself than an object with logic and state.
> 
> I'd be interested to hear any thoughts on this. Would this be a beneficial 
> addition?

I think it makes more sense to come up with some syntax for reducing that kind 
of boilerplate code in general. In "pseudo-english", I'd write the == function 
as "if lhs and rhs are the same case && their associated values are the equal, 
return true, else return false".

What about doing something with the reflection system? Isn't that supposed to 
get overhauled for Swift 4? I'm not sure what the performance implications 
would be, though.

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


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Jonathan Hull via swift-evolution
+1, with the caveat that you should still have to explicitly mark it Equatable.

I think the “when all their associated values were Equatable” is the technical 
issue holding this type of thing up.  The ability to spell that type of thing 
is on the generics roadmap, but I don’t know when it will actually happen.  
There seem to be a lot of things on hold because of it.

Thanks,
Jon

> On Jan 13, 2017, at 11:51 AM, Adam Shin via swift-evolution 
>  wrote:
> 
> When using enums with associated values, it's often necessary to check for 
> equality between two enum objects in some way. That can lead to boilerplate 
> code like this:
> 
> enum Option {
> case foo(String)
> case bar(Int)
>   case zip
> }
> 
> func ==(lhs: Option, rhs: Option) -> Bool {
> switch (lhs, rhs) {
> case (.foo(let a), .foo(let b)) where a == b: return true
> case (.bar(let a), .bar(let b)) where a == b: return true
> case (.zip, .zip): return true
> default: return false
> }
> }
> 
> ..which results in code duplication and opens the door to potential logic 
> errors.
> 
> Instead, what if enums with associated values were automatically Equatable 
> when all their associated values were Equatable? That would remove the need 
> for such boilerplate code.
> 
> The Swift language guide states that custom classes and structs don't receive 
> a default implementation of the == operator because the compiler can't guess 
> what "equality" means for them. However, I think this could make sense for 
> enums. An enum case, even with associated values, seems closer to a value 
> itself than an object with logic and state.
> 
> I'd be interested to hear any thoughts on this. Would this be a beneficial 
> addition?
> ___
> 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


Re: [swift-evolution] Equatability for enums with associated values

2017-01-13 Thread Sean Heber via swift-evolution
A million yes-es please.

l8r
Sean


> On Jan 13, 2017, at 1:51 PM, Adam Shin via swift-evolution 
>  wrote:
> 
> When using enums with associated values, it's often necessary to check for 
> equality between two enum objects in some way. That can lead to boilerplate 
> code like this:
> 
> enum Option {
> case foo(String)
> case bar(Int)
>   case zip
> }
> 
> func ==(lhs: Option, rhs: Option) -> Bool {
> switch (lhs, rhs) {
> case (.foo(let a), .foo(let b)) where a == b: return true
> case (.bar(let a), .bar(let b)) where a == b: return true
> case (.zip, .zip): return true
> default: return false
> }
> }
> 
> ..which results in code duplication and opens the door to potential logic 
> errors.
> 
> Instead, what if enums with associated values were automatically Equatable 
> when all their associated values were Equatable? That would remove the need 
> for such boilerplate code.
> 
> The Swift language guide states that custom classes and structs don't receive 
> a default implementation of the == operator because the compiler can't guess 
> what "equality" means for them. However, I think this could make sense for 
> enums. An enum case, even with associated values, seems closer to a value 
> itself than an object with logic and state.
> 
> I'd be interested to hear any thoughts on this. Would this be a beneficial 
> addition?
> ___
> 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


Re: [swift-evolution] Range and ClosedRange

2017-01-13 Thread Max Moiseev via swift-evolution
FWIW, the common RangeProtocol unifying both Range and ClosedRange existed for 
a while when the new collection indexing model was being implemented.

Here is the commit removing it: 
https://github.com/apple/swift/pull/2108/commits/8e886a3bdded61e266678704a13edce00a4a8867
 


Max

> On Jan 12, 2017, at 12:11 PM, David Hart via swift-evolution 
>  wrote:
> 
> Hello,
> 
> Since the release of Swift 3, I’ve seen quite a few people (me included) 
> experience a lot of friction with the new types for representing ranges. I’ve 
> seen people confused when writing an API that takes a Range as argument but 
> then can’t pass in a ClosedRange. Sometimes this can be fixed because the API 
> should be written against a more general protocol, but sometimes that’s not 
> the case.
> 
> Those new types definitely seem to cause more problems than they fixed (the 
> Int.max problem). Has the Standard Library team put any thought into this?
> 
> Regards,
> David.
> ___
> 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] Equatability for enums with associated values

2017-01-13 Thread Adam Shin via swift-evolution
When using enums with associated values, it's often necessary to check for
equality between two enum objects in some way. That can lead to boilerplate
code like this:

enum Option {
case foo(String)
case bar(Int)
case zip
}

func ==(lhs: Option, rhs: Option) -> Bool {
switch (lhs, rhs) {
case (.foo(let a), .foo(let b)) where a == b: return true
case (.bar(let a), .bar(let b)) where a == b: return true
case (.zip, .zip): return true
default: return false
}
}

..which results in code duplication and opens the door to potential logic
errors.

Instead, what if enums with associated values were automatically Equatable
when all their associated values were Equatable? That would remove the need
for such boilerplate code.

The Swift language guide states that custom classes and structs don't
receive a default implementation of the == operator because the compiler
can't guess what "equality" means for them. However, I think this could
make sense for enums. An enum case, even with associated values, seems
closer to a value itself than an object with logic and state.

I'd be interested to hear any thoughts on this. Would this be a beneficial
addition?
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal] Allow scoped properties from within computed properties

2017-01-13 Thread David Sweeris via swift-evolution

> On Jan 13, 2017, at 11:27, Joseph Newton via swift-evolution 
>  wrote:
> 
> Hi,
> 
> I've done a lot of Objective-C and have been been a fan of Swift since it's 
> come out, however, there's a small feature of Objective-C that I would really 
> like to see implemented in Swift:
> 
> In Objective-C you have a few options implementation-wise when creating 
> properties for your class. You could use the @synthesize statement to have 
> the compiler create the backing ivar along with the appropriate accessor 
> methods or your could use the @dynamic statement to tell the compiler that 
> you're going to create your own accessor methods and backing ivar (if needed).
> 
> Additionally, one could use the @synthesize statement to have the compiler 
> create the backing ivar, and then they could create custom accessor methods 
> to supply custom functionality or validation. I use this third case 
> extensively in my Objecitve-C code but there's not a concise way of doing 
> this in Swift.
> 
> For example, I might have an Objective-C implementation that looks like this:
> 
> @interface Foo : NSObject
> @property (nullable, copy) NSString *bar;
> @end
> 
> @implementation Foo
> @synthesize bar = _bar; // Creates ivar '_bar'
> 
> - (void)setBar:(NSString *)bar {
> if (bar.length < 100)
> _bar = nil;
> else
> _bar = [bar copy];
> }
> 
> @end
> 
> Currently, the only way to implement this in Swift - AFAIK - is as follows:
> 
> class Foo {
> private var _bar: String?
> public var bar: String? {
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
> 
> Although this works, it isn't exactly glamorous. The main drawback of this 
> implementation (unless intended) is that you now have any additional '_bar' 
> variable accessible within the scope of your class. 

I believe you can do this using didSet without the `_bar`:
class Foo {
public var bar: String? {
didSet {
if (bar?.characters.count ?? 0) < 100 {
bar = nil
}
}
}
}


> My proposal is to allow stored properties in the declaration block of 
> computed properties. For this example, the '_bar' declaration would simply be 
> moved inside of the declaration block for 'bar':
> 
> class Foo {
> public var bar: String? {
> var _bar: String?
> 
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
> 
> Only the getter and setter methods of 'bar' are allowed to access and modify 
> the stored '_bar' property. My proposal would also allow for multiple stored 
> properties of varying types within the scope of a single computed property. 
> This would also simply atomic synchronization for single variables:
> 
> class Foo {
> static var synchronizedBar: String? {
> var queue = DispatchQueue(label: "Foo.synchronizedBar")
> var bar: String?
> 
> get { return queue.sync { return bar } }
> set { queue.sync { bar = newValue } }
> }
> }
> 
> Are there any suggestions or arguments, for or against, for this proposal?

It's an interesting idea, for sure. Because of the persistent storage required 
for `_bar`, I think one way to look at what you're proposing is essentially as 
a way to allow for a variable to be declared publicly as one type, be 
implemented as another (anonymous, in this case) type under the hood, and to 
specify a mechanism for automatically converting between the two types.

- Dave Sweeris

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


Re: [swift-evolution] [Proposal] Allow scoped properties from within computed properties

2017-01-13 Thread Xiaodi Wu via swift-evolution
There was a proposal for custom behaviors using `@`, which if I recall
would offer encapsulation along the lines of what you're proposing. It was
an extensively designed system which was deferred for consideration, but
which would be in scope again in phase 2. The proposal is in the
swift-evolution repository--does that address your use case?
On Fri, Jan 13, 2017 at 11:27 Joseph Newton via swift-evolution <
swift-evolution@swift.org> wrote:

> Hi,
>
> I've done a lot of Objective-C and have been been a fan of Swift since
> it's come out, however, there's a small feature of Objective-C that I would
> really like to see implemented in Swift:
>
> In Objective-C you have a few options implementation-wise when creating
> properties for your class. You could use the *@synthesize *statement to
> have the compiler create the backing ivar along with the appropriate
> accessor methods or your could use the *@dynamic* statement to tell the
> compiler that you're going to create your own accessor methods and backing
> ivar (if needed).
>
> Additionally, one could use the *@synthesize* statement to have the
> compiler create the backing ivar, and then they could create custom
> accessor methods to supply custom functionality or validation. I use this
> third case extensively in my Objecitve-C code but there's not a concise way
> of doing this in Swift.
>
> For example, I might have an Objective-C implementation that looks like
> this:
>
> @interface Foo : NSObject
> @property (nullable, copy) NSString *bar;
> @end
>
> @implementation Foo
> @synthesize bar = _bar; // Creates ivar '_bar'
>
> - (void)setBar:(NSString *)bar {
> if (bar.length < 100)
> _bar = nil;
> else
> _bar = [bar copy];
> }
>
> @end
>
> Currently, the only way to implement this in Swift - AFAIK - is as follows:
>
> class Foo {
> private var _bar: String?
> public var bar: String? {
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
>
> Although this works, it isn't exactly glamorous. The main drawback of this
> implementation (unless intended) is that you now have any additional '_bar'
> variable accessible within the scope of your class.
>
> My proposal is to allow stored properties in the declaration block of
> computed properties. For this example, the '_bar' declaration would simply
> be moved inside of the declaration block for 'bar':
>
> class Foo {
> public var bar: String? {
> var _bar: String?
>
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
>
> Only the getter and setter methods of 'bar' are allowed to access and
> modify the stored '_bar' property. My proposal would also allow for
> multiple stored properties of varying types within the scope of a single
> computed property. This would also simply atomic synchronization for single
> variables:
>
> class Foo {
> static var synchronizedBar: String? {
> var queue = DispatchQueue(label: "Foo.synchronizedBar")
> var bar: String?
>
> get { return queue.sync { return bar } }
> set { queue.sync { bar = newValue } }
> }
> }
>
> Are there any suggestions or arguments, for or against, for this proposal?
>
> -- Joe Newton
> ___
> 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


Re: [swift-evolution] Generic Subscripts

2017-01-13 Thread Ben Cohen via swift-evolution

> On Jan 12, 2017, at 1:37 PM, Slava Pestov via swift-evolution 
>  wrote:
> 
>> Before I submit it, could someone let me know if adding generics to 
>> subscripts would influence the ABI? ( still feel pretty clueless in that 
>> area).
> 
> It won’t change the ABI of existing subscript calls, but if the standard 
> library introduces new generic subscripts that replace older non-generic 
> subscripts, it will impact ABI.
> 

Specifically, we currently have to have a _Hashable protocol that has a 
_toAnyHashable() method in order to implement Dictionary 
subscripting using concrete types as keys. A replacement subscript that was 
generic over all Hashable types would solve this more neatly, and would be 
source-compatible, but affects the ABI of the stdlib. 

https://github.com/apple/swift/blob/master/stdlib/public/core/Hashable.swift#L16

Generic subscripts would also make it easier to implement one-sided ranges e.g. 

myCollection[i...] // slice from i to the end


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


Re: [swift-evolution] Allow ' in variable/constant names?

2017-01-13 Thread Georgios Moschovitis via swift-evolution
Interesting background, I wasn’t aware of that.

George.

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


[swift-evolution] [Proposal] Allow scoped properties from within computed properties

2017-01-13 Thread Joseph Newton via swift-evolution
Hi,

I've done a lot of Objective-C and have been been a fan of Swift since it's
come out, however, there's a small feature of Objective-C that I would
really like to see implemented in Swift:

In Objective-C you have a few options implementation-wise when creating
properties for your class. You could use the *@synthesize *statement to
have the compiler create the backing ivar along with the appropriate
accessor methods or your could use the *@dynamic* statement to tell the
compiler that you're going to create your own accessor methods and backing
ivar (if needed).

Additionally, one could use the *@synthesize* statement to have the
compiler create the backing ivar, and then they could create custom
accessor methods to supply custom functionality or validation. I use this
third case extensively in my Objecitve-C code but there's not a concise way
of doing this in Swift.

For example, I might have an Objective-C implementation that looks like
this:

@interface Foo : NSObject
@property (nullable, copy) NSString *bar;
@end

@implementation Foo
@synthesize bar = _bar; // Creates ivar '_bar'

- (void)setBar:(NSString *)bar {
if (bar.length < 100)
_bar = nil;
else
_bar = [bar copy];
}

@end

Currently, the only way to implement this in Swift - AFAIK - is as follows:

class Foo {
private var _bar: String?
public var bar: String? {
get { return _bar }
set {
if (newValue?.characters.count ?? 0) < 100 {
_bar = nil
}
else {
_bar = newValue.copy() as! String
}
}
}
}

Although this works, it isn't exactly glamorous. The main drawback of this
implementation (unless intended) is that you now have any additional '_bar'
variable accessible within the scope of your class.

My proposal is to allow stored properties in the declaration block of
computed properties. For this example, the '_bar' declaration would simply
be moved inside of the declaration block for 'bar':

class Foo {
public var bar: String? {
var _bar: String?

get { return _bar }
set {
if (newValue?.characters.count ?? 0) < 100 {
_bar = nil
}
else {
_bar = newValue.copy() as! String
}
}
}
}

Only the getter and setter methods of 'bar' are allowed to access and
modify the stored '_bar' property. My proposal would also allow for
multiple stored properties of varying types within the scope of a single
computed property. This would also simply atomic synchronization for single
variables:

class Foo {
static var synchronizedBar: String? {
var queue = DispatchQueue(label: "Foo.synchronizedBar")
var bar: String?

get { return queue.sync { return bar } }
set { queue.sync { bar = newValue } }
}
}

Are there any suggestions or arguments, for or against, for this proposal?

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


Re: [swift-evolution] [Pitch] Named subscripts 2

2017-01-13 Thread Tony Freeman via swift-evolution
Thank you for your answer, but i just feel that options should be a property. 
I'm ok with my current solution but it can be simplified with named subscript.___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Throws? and throws!

2017-01-13 Thread Karl Wagner via swift-evolution

> On 13 Jan 2017, at 17:10, Joe Groff via swift-evolution 
>  wrote:
> 
> 
>> On Jan 12, 2017, at 2:58 PM, Jonathan Hull via swift-evolution 
>>  wrote:
>> 
>> I really like swift’s error handling system overall. It strikes a good 
>> balance between safety and usability.
>> 
>> There are some cases where it would be nice to throw errors, but errors are 
>> rarely expected in most use cases, so the overhead of ‘try’, etc… would make 
>> things unusable. Thus fatalError or optionals are used instead.  For 
>> example, operators like ‘+’ could never throw because adding ’try’ 
>> everywhere would make arithmetic unbearable. But in a few cases it would 
>> make my algorithm much cleaner if I just assume it will work and then catch 
>> overflow/underflow errors if they happen, and resolve each of them with 
>> special cases.  Or perhaps I am dealing with user entered values, and want 
>> to stop the calculation and display a user visible error (e.g. a symbol in a 
>> spreadsheet cell) instead of crashing.
>> 
>> I would like to propose adding ‘throws?’ and ‘throws!’ variants to ‘throws’.
>> 
>> These would be used for cases where error handling is not the default 
>> desired behavior, but having it as an option is desired occasionally.  
>> Essentially, the user would no longer have to preface the call with ‘try’, 
>> as the compiler would implicitly add ‘try?’ or ‘try!’ respectively.
>> 
>> Thus, the function would act like a non-throwing function (either trapping 
>> or returning an optional in the case of error), but the user could add ‘try’ 
>> to the call to override that behavior and deal with the error more 
>> explicitly.
>> 
>> Another example would be bounds checking on arrays.  If subscripting arrays 
>> was marked as ‘throws!’ then it would have the same default behavior it does 
>> now (trapping on bounds error).  But a user could add ‘try?’ to return nil 
>> for a bounds error in cases where they explicitly want that, or they could 
>> add ‘try’ to deal with it as an error using do-catch.
>> 
>> I think this would really increase the availability of error handling in 
>> areas where it is impractical right now…
>> 
>> Thanks,
>> Jon
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> Another place I can see this being useful is for higher-order functions which 
> "obviously" work on a throwing operation. The most obvious example would be a 
> constructor for a Result type that collects the success or error result from 
> a throwing closure:
> 
> enum Result {
>  case ok(T)
>  case error(Error)
> 
>  init(_ f: () throws -> T) {
>do {
>  self = .ok(try f())
>} catch {
>  self = .error(error)
>}
>  }
> }
> 
> Having to write `Result { try somethingThatMightFail() }` feels a bit silly 
> because "obviously" the operation you pass to Result is going to be able to 
> fail. Such a feature does feel like it could be easy to misuse, though.
> 
> -Joe
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

That works for single-expression closures, but as soon as the closure becomes 
more complex - say, if you want to transform the result of 
somethingThatMightFail() before returning it - it becomes valuable to see the 
point at which the entire operation might fail

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


Re: [swift-evolution] Throws? and throws!

2017-01-13 Thread Joe Groff via swift-evolution

> On Jan 12, 2017, at 2:58 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I really like swift’s error handling system overall. It strikes a good 
> balance between safety and usability.
> 
> There are some cases where it would be nice to throw errors, but errors are 
> rarely expected in most use cases, so the overhead of ‘try’, etc… would make 
> things unusable. Thus fatalError or optionals are used instead.  For example, 
> operators like ‘+’ could never throw because adding ’try’ everywhere would 
> make arithmetic unbearable. But in a few cases it would make my algorithm 
> much cleaner if I just assume it will work and then catch overflow/underflow 
> errors if they happen, and resolve each of them with special cases.  Or 
> perhaps I am dealing with user entered values, and want to stop the 
> calculation and display a user visible error (e.g. a symbol in a spreadsheet 
> cell) instead of crashing.
> 
> I would like to propose adding ‘throws?’ and ‘throws!’ variants to ‘throws’.
> 
> These would be used for cases where error handling is not the default desired 
> behavior, but having it as an option is desired occasionally.  Essentially, 
> the user would no longer have to preface the call with ‘try’, as the compiler 
> would implicitly add ‘try?’ or ‘try!’ respectively.
> 
> Thus, the function would act like a non-throwing function (either trapping or 
> returning an optional in the case of error), but the user could add ‘try’ to 
> the call to override that behavior and deal with the error more explicitly.
> 
> Another example would be bounds checking on arrays.  If subscripting arrays 
> was marked as ‘throws!’ then it would have the same default behavior it does 
> now (trapping on bounds error).  But a user could add ‘try?’ to return nil 
> for a bounds error in cases where they explicitly want that, or they could 
> add ‘try’ to deal with it as an error using do-catch.
> 
> I think this would really increase the availability of error handling in 
> areas where it is impractical right now…
> 
> Thanks,
> Jon
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

Another place I can see this being useful is for higher-order functions which 
"obviously" work on a throwing operation. The most obvious example would be a 
constructor for a Result type that collects the success or error result from a 
throwing closure:

enum Result {
  case ok(T)
  case error(Error)

  init(_ f: () throws -> T) {
do {
  self = .ok(try f())
} catch {
  self = .error(error)
}
  }
}

Having to write `Result { try somethingThatMightFail() }` feels a bit silly 
because "obviously" the operation you pass to Result is going to be able to 
fail. Such a feature does feel like it could be easy to misuse, though.

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


Re: [swift-evolution] Throws? and throws!

2017-01-13 Thread Karl Wagner via swift-evolution
I can see the appeal, but really throwable errors are just one kind of error 
that can happen in code.

Preconditions are a different thing. They represent axioms that must be kept 
for a sane program. It’s up to the programmer to decide whether something 
should be treated as an axiom or something recoverable. For a few particular 
operations (Array indexing, arithmetic), the standard library designers have 
decided that out-of-bounds values are to be considered axiom violations.

If that’s not convenient for your application, you could suggest changing the 
standard library to include throwing or optional-wrapped alternatives. You 
could also write your own:

extension Array {
subscript(unchecked index: Index) -> Iterator.Element? {   // 
Subscripts aren’t allowed to throw. There’s another proposal on that.
guard (startIndex.. On 12 Jan 2017, at 23:58, Jonathan Hull via swift-evolution 
>  wrote:
> 
> I really like swift’s error handling system overall. It strikes a good 
> balance between safety and usability.
> 
> There are some cases where it would be nice to throw errors, but errors are 
> rarely expected in most use cases, so the overhead of ‘try’, etc… would make 
> things unusable. Thus fatalError or optionals are used instead.  For example, 
> operators like ‘+’ could never throw because adding ’try’ everywhere would 
> make arithmetic unbearable. But in a few cases it would make my algorithm 
> much cleaner if I just assume it will work and then catch overflow/underflow 
> errors if they happen, and resolve each of them with special cases.  Or 
> perhaps I am dealing with user entered values, and want to stop the 
> calculation and display a user visible error (e.g. a symbol in a spreadsheet 
> cell) instead of crashing.
> 
> I would like to propose adding ‘throws?’ and ‘throws!’ variants to ‘throws’.
> 
> These would be used for cases where error handling is not the default desired 
> behavior, but having it as an option is desired occasionally.  Essentially, 
> the user would no longer have to preface the call with ‘try’, as the compiler 
> would implicitly add ‘try?’ or ‘try!’ respectively.
> 
> Thus, the function would act like a non-throwing function (either trapping or 
> returning an optional in the case of error), but the user could add ‘try’ to 
> the call to override that behavior and deal with the error more explicitly.
> 
> Another example would be bounds checking on arrays.  If subscripting arrays 
> was marked as ‘throws!’ then it would have the same default behavior it does 
> now (trapping on bounds error).  But a user could add ‘try?’ to return nil 
> for a bounds error in cases where they explicitly want that, or they could 
> add ‘try’ to deal with it as an error using do-catch.
> 
> I think this would really increase the availability of error handling in 
> areas where it is impractical right now…
> 
> Thanks,
> Jon
> ___
> 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


Re: [swift-evolution] Range and ClosedRange

2017-01-13 Thread David Hart via swift-evolution
I read this great post. But it shows an example where the problem is 
circumvented because the algorithm can work on a more general protocol. But the 
problem still persists for algorithms which make sense for any countable range 
(open and closed).

> On 13 Jan 2017, at 02:57, Adriano Ferreira  wrote:
> 
> Hi Dave,
> 
> I’m not arguing about correctness cause I understand the reasoning behind it, 
> but about the abstraction itself.
> 
> I believe a simplified interface would be more fun to use and less confusing. 
> This post from Ole Begemann talks a little bit about this interesting idea.
> 
> Best,
> 
> —A
> 
>>> On Jan 12, 2017, at 5:55 PM, David Sweeris  wrote:
>>> 
>>> 
>>> On Jan 12, 2017, at 15:44, Adriano Ferreira via swift-evolution 
>>>  wrote:
>>> 
>>> BTW, I agree with you, having the range type split is somewhat confusing, 
>>> specially for those new to the language.
>> 
>> Do you mean that you think having two types is confusing, or that the way we 
>> currently split them is confusing?
>> 
>> If it's the former, then I disagree... IIRC, open vs closed ranges is 
>> covered in high school math, and IMHO it's not too hard to see the 
>> usefulness of both "0..<5" and "1...5".
>> 
>> If it's the latter, I think it's only confusing because, well, partly 
>> because we only implement half the kinds of ranges ("lower" is always 
>> closed, but that's another thread), but mostly because we don't have generic 
>> protocols yet. If we could write
>>protocol Range where T : WhateverTheCurrentConstraintsAre {
>>var lower: T {get}
>>var upper: T {get}
>>}
>> Then we could define the concrete types as
>>struct CCRange: Range {...}
>>struct CORange: Range {...}
>>struct OCRange: Range {...}
>>struct OORange: Range {...}
>> (Or spell it out, "ClosedClosedRange", if you don't like the abbreviations.) 
>> Then in code, since `Range` doesn't have any "Self or associated type 
>> requirements", you can make just make it the type of a variable. In fact, if 
>> I'm not mistaken, the "..<" and "..." operators could even return a `Range` 
>> instead of the relevant concrete type
>>var x = 0..<5 // "..<" returns `CORange as Range`
>>x = 0...4 // "..." returns `CCRange as Range`, which is fine because x's 
>> type is `Range`, not `HalfOpenRange` (or whatever it's called now)
>> We'd get full polymorphism between all the types of range without losing the 
>> value semantics we want, and the current method of overloading functions is 
>> still available if you need the speed of static dispatch.
>> 
>> - Dave Sweeris 
>> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


[swift-evolution] [Pitch] Named subscripts 2

2017-01-13 Thread Tony Freeman via swift-evolution
Hello Swift community,


I found this very useful while wrapping c api, although this may simplify the 
code in other cases when subscript doesn't have it's own state and(or) share 
some state form the container.

here is an example: 
https://gist.github.com/tonyfreeman/949ce0a9aa374ab6fa2fc7de0dccaa27

another option would be use set/get functions, but it doesn't feel right.


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