Re: [swift-evolution] [swift-evolution-announce] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-19 Thread Kevin Ballard via swift-evolution
Isn’t this going to turn both structs and non-C-like enums into types that need 
to be auto-boxed (as the client won’t be able to rely on knowing the fixed size 
anymore)? This seems like a performance hazard.

-Kevin Ballard

> On Dec 19, 2017, at 5:35 PM, Slava Pestov <spes...@apple.com> wrote:
> 
> 
> 
>> On Dec 19, 2017, at 3:31 PM, Kevin Ballard via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>> So I guess I’m saying, I want more thought put on the topic of whether enums 
>> defined in Swift should actually default to non-exhaustive, and I’m now 
>> leaning towards the idea that they should remain exhaustive (but Obj-C enums 
>> will still default to non-exhaustive).
> 
> This would introduce an inconsistency between enums and structs. Structs will 
> not be fixed-contents by default (there’s a proposal coming for that), which 
> means you will be able to add stored properties after the fact. For this 
> reason it makes more sense to me to also make enums non-exhaustive by default 
> so that new cases can be added.
> 
> Slava
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE 0192 - Non-Exhaustive Enums

2017-12-19 Thread Kevin Ballard via swift-evolution

> On Dec 19, 2017, at 2:58 PM, Ted Kremenek  wrote:
> https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md
>  
> 
> What is your evaluation of the proposal?
> 

Overall I like it, but I have some issues.

I’m not completely sold yet on the idea that public enums should be 
non-exhaustive by default, as I believe every single public enum I’ve ever 
written definitely wants to be exhaustive. I’m tempted to say that enums 
exposed by frameworks that need to maintain future-compatibility (such as 
Apple’s frameworks) want non-exhaustive by default, but enums exposed by 
third-party frameworks that follow semantic versioning are likely to want 
exhaustive by default.

In fact, this brings to mind another difference between enums in Apple 
frameworks and enums in third-party Swift frameworks, which is the former is 
exclusively C-compatible enums whereas the latter is going to have a lot of 
enums that carry associated values. I have no data to support this but I’m 
inclined to think that it’s more likely for C-compatible enums to want to be 
non-exhaustive than it is for enums carrying associated values to want to be 
non-exhaustive.

So I guess I’m saying, I want more thought put on the topic of whether enums 
defined in Swift should actually default to non-exhaustive, and I’m now leaning 
towards the idea that they should remain exhaustive (but Obj-C enums will still 
default to non-exhaustive).

--

I don’t like that modules using @testable imports treat all enums as 
exhaustive. I can see why you want to do that, but being forced to handle 
non-exhaustive enums in unit tests seems like a valuable guard against 
accidentally publishing non-exhaustive enums that should be exhaustive.

--

I’m really not a fan of using a ‘default’ case in non-exhaustive enums. This 
means that if new cases are added, the compiler can’t help me find my switches. 
I’d really like to have an alternative way of saying “here’s how to behave in 
the event of an unknown enum case” without also making that a catch-all for 
unspecified-but-known cases. You already brought up this issue in the 
alternatives section, where you stated

> Ultimately I decided not to include this in the proposal with the expectation 
> is that switches over non-exhaustive enums should be uncommon.


But since non-exhaustive enums will be the default, I think this _will_ become 
quite common, if for no other reason than you’re using a library written by 
someone who forgot to mark enums as @exhaustive that really should be.

Regarding the comment that a ‘future’ case is impossible to test, so is a 
‘default’ case on a switch that is otherwise exhaustive. In the latter you can 
test it by commenting out one of your existing cases. But you can do that with 
‘future’ too, just by renaming it to ‘default’ first.

--

In the “Use-side” section it says that a switch without a default case will 
produce a warning in Swift 4 mode. But in Swift 4 mode all enums are exhaustive 
by default and the @exhaustive annotation does nothing. These two things can’t 
both be true or else Swift 4 mode will emit warnings on switches over enums 
that are very clearly supposed to be exhaustive enums.
> Is the problem being addressed significant enough to warrant a change to 
> Swift?
> 
Yes
> 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?
> 
A quick reading, followed by a few re-readings as I composed this email.

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


Re: [swift-evolution] [Review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-09 Thread Kevin Ballard via swift-evolution
On Wed, Nov 8, 2017, at 09:29 PM, Paul Cantrell via swift-evolution wrote:> The 
problem in the Doodads example is that *the name flatMap is used
> to identify two distinct intents*: concatenating arrays and filtering
> nils. One can argue that those two operations are, in some lofty
> abstract sense, if you squint, two instances of some more general
> pattern — but I don’t think it’s fair to say that they represent the
> same *intent*. These separate intents deserve separate names.
They absolutely represent the same intent if you think of an optional as
a collection of zero or one elements.
-Kevin Ballard
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-08 Thread Kevin Ballard via swift-evolution
On Wed, Nov 8, 2017, at 02:29 PM, Max Moiseev via swift-evolution wrote:> 
> 
>> On Nov 8, 2017, at 12:20 PM, Tino Heth <2...@gmx.de> wrote:
>> 
>> 
>>> This is a wonderful example! But it’s an argument for a different
>>> discussion (of general usefulness of implicit optional promotion).
>>> Thanks to the optional promotion, what the closure returns is not
>>> nil, but instead is .some(nil), and that is not filtered out.>> My point 
>>> is: The proposed filterMap isn’t a combination of map and
>> filter at all — or can you build it just out of map & filter, like
>> flatMap is constructed from map & flatten?> 
>> https://github.com/apple/swift/blob/master/stdlib/public/core/FlatMap.swift#L49>
>>  
> It *is* a combination of map and filter. It is purely for performance
> we don’t do the same thing on any Sequence, because that will allocate
> a temporary array or two.
Well, that certainly explains the nasty return type. I rather wish we
had a LazyFlatMapSequence type rather than using map(…).filter(…).map(…)
if for no other reason than it would produce a return type that's easier
to work with.
-Kevin Ballard

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


Re: [swift-evolution] [Review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-08 Thread Kevin Ballard via swift-evolution
On Wed, Nov 8, 2017, at 11:28 AM, Max Moiseev wrote:
> 
> 
>> On Nov 7, 2017, at 3:34 PM, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:>> 
>> On Tue, Nov 7, 2017, at 03:23 PM, John McCall via swift-
>> evolution wrote:>>>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md>>>
>>  
>>> • What is your evaluation of the proposal?
>> 
>> This proposal is going to cause an insane amount of code churn. The
>> proposal suggests this overload of flatMap is used "in certain
>> circumstances", but in my experience it's more like 99% of all
>> flatMaps on sequences are to deal with optionals, not to flatten
>> nested sequences.>> 
>>> • Is the problem being addressed significant enough to warrant a
>>> change to Swift?>> 
>> I don't think so. It's a fairly minor issue, one that really only
>> affects new Swift programmers anyway rather than all users, and it
>> will cause far too much code churn to be worthwhile.>> 
>> I'd much rather see a proposal to add a new @available type,
>> something like 'warning’,> Please write one, seriously!
> 
>> that lets you attach an arbitrary warning message to a call (which
>> you can kind of do with 'deprecated' except that makes the warning
>> message claim the API is deprecated). With that sort of thing we
>> could then declare>> 
>> extension Sequence {
>> @available(*, warning: "Use map instead")
>> func flatMap(_ f: (Element) -> U) -> [U] {
>> return map(f)
>> }
>> }
> FWIW: This was attempted in the past, and had to be reverted for the
> reason other than «deprecated» being a confusing message.> 
> https://github.com/apple/swift/pull/9390

Interesting. It looks like what's going on is, with the deprecated form,
`[a, b, c]` is immediately treated as `[Any]`, but without it, it's
treated as `[Int?]` (invoking optional hoisting on `a`) and the closure
itself is inferred as returning Any.
There's probably some shenanigans we could do like adding an
_ImplicitlyPromotedOptional type that takes precedence over
Optional for overloading purposes, which could then be used to
reintroduce the deprecated form of flatMap, but I'm not sure if it's
worth the additional complexity unless there are more functions than
just flatMap that we'd want to kill optional hoisting for.
-Kevin Ballard

> 
>> 
>> And now if someone writes flatMap in a way that invokes optional
>> hoisting, it'll match this overload instead and warn them.>> 
>>> • How much effort did you put into your review? A glance, a quick
>>> reading, or an in-depth study?>> 
>> A quick reading, and a couple of minutes testing overload behavior
>> with availability attributes (to confirm that we can't simply use
>> 'unavailable' for this).>> 
>> -Kevin Ballard
>> 
>> ___
>> 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] [Review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-08 Thread Kevin Ballard via swift-evolution
On Tue, Nov 7, 2017, at 05:23 PM, Tino Heth via swift-evolution wrote:
> -1
> 
> I guess breaking existing code will be the show stopper for this
> proposal — but I generally think that compatibility is a poor
> rationale to stop an improvement, so my personal reasons are
> different:> The name is just wrong.
> Just have a look at this simple example
> 
> extension Int {
> func justImagineError() throws -> Int {
> return self
> }
> }
> 
> let ints: [Int?] = [nil]
> 
> let result = ints.flatMap {
> return try? $0?.justImagineError()
> }
> print(result)
> 
> If flatMap would really filter out nil values, this should yield an
> empty array as result — but the actual output is *[nil]*
flatMap does filter out nil values. The problem is the return type of
your block is `Int??`, not `Int?`, so it's stripping off the outer layer
of optionals. Your example here is akin to one where your block returns
`[[[Int]]]` and asking why your resulting type is `[[Int]]`.
-Kevin Ballard
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-08 Thread Kevin Ballard via swift-evolution
On Tue, Nov 7, 2017, at 09:37 PM, John McCall wrote:
> 
>> On Nov 7, 2017, at 6:34 PM, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:>> 
>> On Tue, Nov 7, 2017, at 03:23 PM, John McCall via swift-
>> evolution wrote:>>>> 
>> https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md>>>
>>  
>>> • What is your evaluation of the proposal?
>> 
>> This proposal is going to cause an insane amount of code churn. The
>> proposal suggests this overload of flatMap is used "in certain
>> circumstances", but in my experience it's more like 99% of all
>> flatMaps on sequences are to deal with optionals, not to flatten
>> nested sequences.>> 
>>> • Is the problem being addressed significant enough to warrant a
>>> change to Swift?>> 
>> I don't think so. It's a fairly minor issue, one that really only
>> affects new Swift programmers anyway rather than all users, and it
>> will cause far too much code churn to be worthwhile.>> 
>> I'd much rather see a proposal to add a new @available type,
>> something like 'warning', that lets you attach an arbitrary warning
>> message to a call (which you can kind of do with 'deprecated' except
>> that makes the warning message claim the API is deprecated).> 
> As review manager, I generally try to avoid commenting on threads, but
> I find this point interesting in a way that, if you don't mind, I'd
> like to explore.> 
> Would this attribute not be a form of deprecation?  Certainly it acts
> to discourage current and subsequent use, since every such use will
> evoke a warning.> 
> Is the word "deprecation" just too strong?  Often we think of
> deprecated APIs as being ones with more *functional* problems, like an
> inability to report errors, or semantics that must have seemed like a
> good idea at the time.  Here it's just that the API has a name we
> don't like, and perhaps "deprecation" feels unnecessarily judgmental.
What I'm suggesting is that we don't change the API name at all. That's
why I don't want to use 'deprecated', because we're not actually
deprecating something. I'm just suggesting an alternative way of
flagging cases where the user tries to use flatMap but accidentally
invokes optional hoisting, and that's by making a new overload of
flatMap that works for non-optional (non-sequence) values and warns the
user that what they're doing is better done as a map. Using the
'deprecated' attribute for this would be confusing because it would make
it sound like flatMap itself is deprecated when it's not.
> Also, more practically, it conflates a relatively unimportant
> suggestion — that we should call the new method in order to make our
> code clearer — with a more serious one — that we should revise our
> code to stop using a problematic API.  Yes, the rename has a fix-it,
> but still: to the extent that these things demand limited attention
> from the programmer, that attention should clearly be focused on the
> latter set of problems.  Perhaps that sense of severity is something
> that an IDE should take into consideration when reporting problems.> 
> What else would you have in mind for this warning?

The main use for this warning would be for adding overloads to methods
that take optionals in order to catch the cases where people invoke
optional hoisting, so we can tell them that there's a better way to
handle it if they don't have an optional. flatMap vs map is the obvious
example, but I'm sure there are other cases where we can do this too.
But there are also other once-off uses. For example, in the past I've
written a function that should only ever be used for debugging, so I
marked it as deprecated with a message saying 'remove this before
committing your code'. This warning would have been better done using
the new 'warning' attribute instead of as a deprecation notice.
-Kevin Ballard

> John.
> 
>> With that sort of thing we could then declare
>> 
>> extension Sequence {
>> @available(*, warning: "Use map instead")
>> func flatMap(_ f: (Element) -> U) -> [U] {
>> return map(f)
>> }
>> }
>> 
>> And now if someone writes flatMap in a way that invokes optional
>> hoisting, it'll match this overload instead and warn them.>> 
>>> • How much effort did you put into your review? A glance, a quick
>>> reading, or an in-depth study?>> 
>> A quick reading, and a couple of minutes testing overload behavior
>> with availability attributes (to confirm that we can't simply use
>> 'unavailable' for this).>> 
>> -Kevin Ballard
>> 
>> ___
>> 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] [Review] SE-0187: Introduce Sequence.filterMap(_:)

2017-11-07 Thread Kevin Ballard via swift-evolution
On Tue, Nov 7, 2017, at 03:23 PM, John McCall via swift-evolution wrote:>> 
https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md>
 
> • What is your evaluation of the proposal?

This proposal is going to cause an insane amount of code churn. The
proposal suggests this overload of flatMap is used "in certain
circumstances", but in my experience it's more like 99% of all flatMaps
on sequences are to deal with optionals, not to flatten nested
sequences.
> • Is the problem being addressed significant enough to warrant a
> change to Swift?
I don't think so. It's a fairly minor issue, one that really only
affects new Swift programmers anyway rather than all users, and it will
cause far too much code churn to be worthwhile.
I'd much rather see a proposal to add a new @available type, something
like 'warning', that lets you attach an arbitrary warning message to a
call (which you can kind of do with 'deprecated' except that makes the
warning message claim the API is deprecated). With that sort of thing we
could then declare
extension Sequence {
@available(*, warning: "Use map instead")
func flatMap(_ f: (Element) -> U) -> [U] {
return map(f)
}
}

And now if someone writes flatMap in a way that invokes optional
hoisting, it'll match this overload instead and warn them.
> • How much effort did you put into your review? A glance, a quick
> reading, or an in-depth study?
A quick reading, and a couple of minutes testing overload behavior with
availability attributes (to confirm that we can't simply use
'unavailable' for this).
-Kevin Ballard

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


Re: [swift-evolution] [Announcement] Godbolt Compiler Explorer adds Swift support

2017-06-23 Thread Kevin Ballard via swift-evolution
I have a Vim plugin that does basically the same thing. It would just be
nice to have it in something like Godbolt so you can share with others
(and especially if it can highlight the SIL corresponding with a given
line like it does for assembly).
-Kevin Ballard

On Fri, Jun 23, 2017, at 01:35 AM, Alex Blewitt wrote:
> If you're interested in just having a look at SIL output, then I put a
> very basic GUI wrapper around invocations of swiftc -emit-sil and
> friends:> 
> https://github.com/alblue/SILInspector
> 
> It also supports piping them through the demangler and whether or not
> to enable optimisations, so you can see the effect of the options on
> the generated code. In addition, it prints out the command that is run
> at the bottom so you can do the same yourself outside of the GUI.> 
> Alex
> 
>> On 23 Jun 2017, at 02:58, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:>> 
>> That's pretty cool.
>> 
>> Any plans on adding support for looking at the SIL output?
>> 
>> -Kevin Ballard
>> 
>> On Thu, Jun 22, 2017, at 10:24 AM, Adam Nemecek via swift-
>> evolution wrote:>>> Howdy,
>>> Matt Godbolt and I have added Swift support to his compiler explorer
>>> project>>> 
>>> https://swift.godbolt.org/
>>> 
>>> It let's you interactively explore assembly emitted by the Swift
>>> compiler.>>> 
>>> Right now, if you want the compiler to emit Intel syntax
>>> instructions, pass "-emit-assembly -Xllvm --x86-asm-syntax=intel" to
>>> the compiler as a command line argument in the text field in the top
>>> right corner.>>> 
>>> Note that right now it's might still be kinda rough around the
>>> edges.>>> 
>>> You can contribute to the project here
>>> https://github.com/mattgodbolt/compiler-explorer>>> 
>>> Adam
>>> _
>>> 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] [Announcement] Godbolt Compiler Explorer adds Swift support

2017-06-22 Thread Kevin Ballard via swift-evolution
That's pretty cool.

Any plans on adding support for looking at the SIL output?

-Kevin Ballard

On Thu, Jun 22, 2017, at 10:24 AM, Adam Nemecek via swift-evolution wrote:> 
Howdy,
> Matt Godbolt and I have added Swift support to his compiler
> explorer project> 
> https://swift.godbolt.org/
> 
> It let's you interactively explore assembly emitted by the Swift
> compiler.> 
> Right now, if you want the compiler to emit Intel syntax instructions,
> pass "-emit-assembly -Xllvm --x86-asm-syntax=intel" to the compiler as
> a command line argument in the text field in the top right corner.> 
> Note that right now it's might still be kinda rough around the edges.> 
> You can contribute to the project here
> https://github.com/mattgodbolt/compiler-explorer> 
> Adam
> _
> 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] [swift-evolution-announce] [Revised and review extended] SE-0180 - String Index Overhaul

2017-06-22 Thread Kevin Ballard via swift-evolution
> https://github.com/apple/swift-evolution/blob/master/proposals/0180-string-index-overhaul.md
Given the discussion in the original thread about potentially having
Strings backed by something other than utf16 code units, I'm somewhat
concerned about having this kind of vague `encodedOffset` that happens
to be UTF16 code units. If this is supposed to represent an offset into
whatever code units the String is backed by, then it's going to be a
problem because the user isn't supposed to know or care what the
underlying storage for the String is. And I can imagine potential issues
with archiving/unarchiving where the unarchived String has a different
storage type than the archived one, and therefore `encodedOffset` would
gain a new meaning that screws up unarchived String.Index values.
The other problem with using this as utf16 is how am I supposed to
archive/unarchive a String.Index that comes from String.UTF8View? AFAICT
the only way to do that is to ignore encodedOffset entirely and instead
calculate the distance between s.utf8.startIndex and my index (and then
recreate the index later on by advancing from startIndex). But this RFC
explicitly says that archiving/unarchiving indices is one of the goals
of this overhaul.
--

The section on comparison still talks about how this is a weak ordering.
In the other thread it was explained as being done so because the
internal transcodedOffset isn't public, but that still makes this
explanation very odd. String.Index comparison should not be weak
ordering, because all indices can be expressed in the utf8View if
nothing else, and in that view they have a total order. So it should
just be defined as a total order, based on the position in the utf8View
that the index corresponds with.
--

The detailed design of the index has encodedOffset being mutable (and
this was confirmed in the other thread as intentional). I don't think
this is a good idea, because it makes the following code behave oddly:
  let x = index.encodedOffset
  index.encodedOffset = x

Specifically, this resets the private transcodedOffset, so if you do
this with an intra-code-unit Index taken from the utf8View, the modified
Index may point to a different byte.
I'm also not sure why you'd ever want to do this operation anyway. If
you want to change the encodedOffset, you can just say `index =
String.Index(encodedOffset: x)`.
-Kevin Ballard
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0180: String Index Overhaul

2017-06-09 Thread Kevin Ballard via swift-evolution
On Tue, Jun 6, 2017, at 10:57 AM, Dave Abrahams via swift-evolution wrote:
> 
> on Mon Jun 05 2017, Kevin Ballard  wrote:
> 
> > There’s also the curious case where I can have two String.Index values
> > that compare unequal but actually return the same value when used in a
> > subscript. 
> > For example, with the above string, if I have a
> > String.Index(encodedOffset: 0) and a String.Index(encodedOffset:
> > 1). This may not be a problem in practice, but it’s something to be
> > aware of.
> 
> I don't think this one even rises to that level.
> 
> let s = "aaa"
> var si = s.indices.makeIterator()
> let i0 = si.next()!
> let i1 = si.next()!
> print(i0 == i1)   // false
> print(s[i0] == s[i1]) // true.  Surprised?

Good point.

> > I’m also confused by the paragraph about index comparison. It talks
> > about if two indices are valid in a single String view, comparison
> > semantics are according to Collection, and otherwise indexes are
> > compared using encodedOffsets, and this means indexes aren’t totally
> > ordered. But I’m not sure what the first part is supposed to mean. How
> > is comparing indices that are valid within a single view any different
> > than comparing the encodedOffsets?
> 
> In today's String, encodedOffset is an offset in UTF-16.  Two indices
> into a UTF-8 view may be unequal yet have the same encodedOffset.

Ah, right. So a String.Index is actually something similar to

public struct Index {
public var encodedOffset: Int
private var byteOffset: Int // UTF-8 offset into the UTF-8 code unit
}

In this case, can't we still define String.Index comparison as merely being the 
lexicographical comparison of (encodedOffset, byteOffset)?

Also, as a side note, the proposal implies that encodedOffset is mutable. Is 
this actually the case? If so, I assume that mutating it would also reset the 
byteOffset?

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


Re: [swift-evolution] [Review] SE-0180: String Index Overhaul

2017-06-06 Thread Kevin Ballard via swift-evolution
https://github.com/apple/swift-evolution/blob/master/proposals/0180-string-index-overhaul.md
 


Overall it looks pretty good. But unfortunately the answer to "Will 
applications still compile but produce different behavior than they used to?" 
is actually "Yes", when using APIs provided by Foundation. This is because 
Foundation is currently able to return String.Index values that don't point to 
Character boundaries.

Specifically, in Swift 3, the following code:

import Foundation

let str = "e\u{301}galite\u{301}"
let r = str.rangeOfCharacter(from: ["\u{301}"])!
print(str[r] == "\u{301}")

will print “true”, because the returned range identifies the combining acute 
accent only. But with the proposed String.Index revisions, the `str[r]` 
subscript will return the whole "e\u{301}” combined character.

This is, of course, an edge case, but we need to consider the implications of 
this and determine if it actually affects anything that’s likely to be a 
problem in practice.

There’s also the curious case where I can have two String.Index values that 
compare unequal but actually return the same value when used in a subscript. 
For example, with the above string, if I have a String.Index(encodedOffset: 0) 
and a String.Index(encodedOffset: 1). This may not be a problem in practice, 
but it’s something to be aware of.

I’m also confused by the paragraph about index comparison. It talks about if 
two indices are valid in a single String view, comparison semantics are 
according to Collection, and otherwise indexes are compared using 
encodedOffsets, and this means indexes aren’t totally ordered. But I’m not sure 
what the first part is supposed to mean. How is comparing indices that are 
valid within a single view any different than comparing the encodedOffsets?

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


Re: [swift-evolution] [swift-evolution-announce] [swift-build-dev] [Review] SE-0175 Package Manager Revised Dependency Resolution

2017-05-03 Thread Kevin Ballard via swift-evolution
On Tue, May 2, 2017, at 07:22 PM, Rick Ballard wrote:
> Proposal link:
> https://github.com/apple/swift-evolution/blob/master/proposals/0175-package-manager-revised-dependency-resolution.md

> * What is your evaluation of the proposal?

Big +1. This makes the package manager behave much more like how I expect it to.

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

Yes.

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

Yes.

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

This seems pretty similar to Cargo, Rust's package manager (which I think is 
excellent), although it doesn't have an explicit `resolve` command.

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

A quick reading.

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0164: Remove final support in protocol extensions

2017-04-05 Thread Kevin Ballard via swift-evolution
On Wed, Apr 5, 2017, at 03:05 PM, Douglas Gregor wrote:
>  * What is your evaluation of the proposal?


It sounds like the keyword doesn't do anything right now, so +1.



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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0159: Fix Private Access Levels

2017-03-22 Thread Kevin Ballard via swift-evolution
On Wed, Mar 22, 2017, at 01:58 PM, Kevin Ballard wrote:

> On Mon, Mar 20, 2017, at 04:54 PM, Douglas Gregor wrote:
>>  * What is your evaluation of the proposal?
> 

> Huge -1, and I agree strongly with Drew Crockford's emails on
> this topic.


My apologies, Drew. It's Drew Crawford.



-Kevin Ballard


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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0159: Fix Private Access Levels

2017-03-22 Thread Kevin Ballard via swift-evolution
On Mon, Mar 20, 2017, at 04:54 PM, Douglas Gregor wrote:
>  * What is your evaluation of the proposal?


Huge -1, and I agree strongly with Drew Crockford's emails on
this topic.


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


Re: [swift-evolution] Replace named returns with `out` parameters?

2016-12-29 Thread Kevin Ballard via swift-evolution
I know you've already decided against this, but I think it deserves an
explanation for why the two are different.


Tuples in function parameters was basically a special case to the type
system. The function type was effectively modeled as taking one argument
which was a tuple, and a function of multiple arguments just had a multi-
element tuple. But this wasn't actually true. For one thing, you could
have a single named argument, but you cannot have a 1-element tuple
(named or no), which means the function argument isn't _really_ a tuple.
For another, this caused weird behavior when invoking functions with a
single tuple element. I don't remember the specifics anymore (I'm not
sure I ever truly understood the rules around this), but in some cases
you could pass a single tuple to a function expecting multiple
arguments, but in other cases you couldn't.


So ultimately, getting rid of the notion that a function's arguments is
a tuple was actually a simplification to the type system and to the
internals, and made the rules a lot more straightforward.


Now contrast that with the return type. The return type is just a single
value of *any* valid type. And a tuple is a valid type. Therefore, the
return type can be a tuple. That's a straightforward consequence of the
basic rules of the type system. Restricting it so functions couldn't
return a tuple would be a complication to the type system, and a rather
weird one at that. And that's without even considering the complexity
and syntactical issues with your proposed `out` parameter.


-Kevin Ballard



On Wed, Dec 28, 2016, at 03:09 AM, Anton Zhilin via swift-evolution wrote:
> Some people on the list wondered, why we have moved from tuples in
> function parameters, but multiple returns are still implemented using
> tuples? The following code still compiles:


> *func* *position*() -> (x: Int, y: Int) {  *return* (x: , y: ) }

> *let* (y, x) = position()
>
> (Maybe it’s a bad example, because naturally we’d use Point struct.
> Let’s pretend those two parameters don’t make sense as a struct.)
> What I want to discuss is if we should introduce out parameters *and*
> make them the default for multiple returns for Swift 4. The syntax
> would look like:


> *func* *position*(x: out Int, y: out Int) { x =  y =  }

> *var* y position(x: *let* x, y: y)
>
> out arguments can be any patterns allowed on the left side of
> assignment, including wildcard pattern and tuple destructuring
> pattern.
> 

> _

> 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] [Pitch] Changing NSObject dispatch behavior

2016-12-19 Thread Kevin Ballard via swift-evolution
On Fri, Dec 16, 2016, at 06:30 AM, Charles Srstka wrote:
>> On Dec 16, 2016, at 12:36 AM, Kevin Ballard  wrote:
>> 

>> On Thu, Dec 15, 2016, at 03:01 PM, Charles Srstka wrote:
 On Dec 15, 2016, at 4:33 PM, Kevin Ballard  wrote:
 

 The problem with that code isn't that `dynamic` doesn't work for
 computed properties. It does; if you mutate the `foo` property,
 you'll get the KVO notifications. The problem is you have one
 property that depends on another and you didn't set up the KVO
 machinery properly using automaticallyNotifiesObservers(forKey:) or
 automaticallyNotifiesObserversOf() (incidentally in Swift you
 can write the latter as a `static let`, since that becomes a class
 method in Obj-C).
>>> 

>>> You’ll only get the notifications if you mutate ‘foo’ directly.
>>> This, however, is fairly useless, because if you are watching ‘foo’,
>>> you want to be notified every time the value changes, not just when
>>> someone hits one particular accessor. Code relying on observation of
>>> ‘foo’ in the example I provided would be prone to breaking in
>>> mysterious and possibly horrible ways.
>> 

>> No, if you implement keyPathsForValuesAffecting()  then you get
>> "foo" KVO notifications when "bar" is mutated.  That's the whole
>> point of that method, and this is exactly what you have to do in Obj-
>> C as well.
> 

> Right… the sentence I was quoting was talking about code which uses
> ‘dynamic’ but *doesn’t* use keyPathsForValuesAffecting. You’ll
> get notifications if someone calls that one particular accessor, but
> otherwise you won’t.


You can always write buggy code. If you're using `dynamic` for KVO
purposes, then not implementing keyPathsForValuesAffecting in this
case is strictly a bug. If you're using `dynamic` for something other
than KVO, and your property won't end up supporting KVO properly by
default, then you should document it as such, given that the natural
assumption for a `dynamic` property is that it supports KVO.


 So yes, `dynamic` by itself doesn't mean that the property supports
 KVO. But there are very few reasons to use `dynamic` outside of
 supporting KVO, so it's a pretty good signal that the property does
 support it. And conversely, not having `dynamic` doesn't mean that
 it doesn't support KVO, though if it does have manual KVO support
 using will/didChangeValue(forKey:) then it should be documented as
 such.
>>> Use of the ‘dynamic’ keyword enables all manner of runtime hackery
>>> which someone may be employing. The trick to automatically add KVO
>>> conformance to accessors is probably the most common, but it’s
>>> hardly the only one. One also might want to declare things ‘dynamic’
>>> when working with Objective-C frameworks not under one’s control
>>> which might assume the ability to do metaprogramming on your classes
>> 

>> That is exceedingly rare. I can't even remember the last time I used
>> such a thing.
> 

> You used such a thing the last time you used KVO. ;-)



We were talking about metaprogramming other than KVO.



>>> I know it’s commonplace to use ‘dynamic’ all over the place wherever
>>> Core Data is involved.
>> 

>> It is? Why? Maybe you're confusing this with Obj-C's @dynamic
>> keyword, which is completely unrelated to Swift's `dynamic`. When
>> writing Swift NSManagedObject subclasses, you use the @NSManaged
>> property attribute, not the `dynamic` keyword (@NSManaged does
>> effectively the same thing that Obj-C's @dynamic, except it's
>> reserved for integration with CoreData instead of being as generic as
>> Obj-C's @dynamic is).
> 

> @NSManaged implies dynamic, though. Core Data is entirely built on the
> dynamic runtime, and is using it pretty much everywhere.


@NSManaged could easily be implemented by codegenning static-dispatch
methods that invoke the primitive accessors and will/didChange KVO
broadcasts. Presumably it doesn't (presumably it does literally the same
thing @dynamic does in Obj-C, which is that it makes the assumption that
the methods exist at runtime even though they're unknown at compile-
time), but there's nothing about @NSManaged that requires it to always
use dynamic dispatch. Core Data leverages the dynamic runtime for method
generation, but it doesn't actually require it (you can completely
ignore dynamicism and implement your properties in terms of
primitiveValue(forKey:) and setPrimitiveValue(_:forKey:), though the 
dynamically-
synthesized primitive accessors are supposed to be more efficient).


>>> Long story short, ‘dynamic’ does not guarantee KVO conformance in
>>> any way, shape, or form.
>> 

>> And declaring that your property returns a String doesn't guarantee
>> that it actually does either. You can always write broken code. But
>> `dynamic` is required for automatic KVO conformance, and it's
>> extremely rare to have a reason to use `dynamic` outside of KVO, so
>> it's a really really strong signal that 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Kevin Ballard via swift-evolution
On Thu, Dec 15, 2016, at 03:01 PM, Charles Srstka wrote:
>> On Dec 15, 2016, at 4:33 PM, Kevin Ballard  wrote:
>> 

>> The problem with that code isn't that `dynamic` doesn't work for
>> computed properties. It does; if you mutate the `foo` property,
>> you'll get the KVO notifications. The problem is you have one
>> property that depends on another and you didn't set up the KVO
>> machinery properly using automaticallyNotifiesObservers(forKey:) or
>> automaticallyNotifiesObserversOf() (incidentally in Swift you
>> can write the latter as a `static let`, since that becomes a class
>> method in Obj-C).
> 

> You’ll only get the notifications if you mutate ‘foo’ directly. This,
> however, is fairly useless, because if you are watching ‘foo’, you
> want to be notified every time the value changes, not just when
> someone hits one particular accessor. Code relying on observation of
> ‘foo’ in the example I provided would be prone to breaking in
> mysterious and possibly horrible ways.


No, if you implement keyPathsForValuesAffecting()  then you get
"foo" KVO notifications when "bar" is mutated.  That's the whole
point of that method, and this is exactly what you have to do in Obj-
C as well.


>> So yes, `dynamic` by itself doesn't mean that the property supports
>> KVO. But there are very few reasons to use `dynamic` outside of
>> supporting KVO, so it's a pretty good signal that the property does
>> support it. And conversely, not having `dynamic` doesn't mean that it
>> doesn't support KVO, though if it does have manual KVO support using
>> will/didChangeValue(forKey:) then it should be documented as such.
> Use of the ‘dynamic’ keyword enables all manner of runtime hackery
> which someone may be employing. The trick to automatically add KVO
> conformance to accessors is probably the most common, but it’s hardly
> the only one. One also might want to declare things ‘dynamic’ when
> working with Objective-C frameworks not under one’s control which
> might assume the ability to do metaprogramming on your classes


That is exceedingly rare. I can't even remember the last time I used
such a thing.


> I know it’s commonplace to use ‘dynamic’ all over the place wherever
> Core Data is involved.


It is? Why? Maybe you're confusing this with Obj-C's @dynamic keyword,
which is completely unrelated to Swift's `dynamic`. When writing Swift
NSManagedObject subclasses, you use the @NSManaged property attribute,
not the `dynamic` keyword (@NSManaged does effectively the same thing
that Obj-C's @dynamic, except it's reserved for integration with
CoreData instead of being as generic as Obj-C's @dynamic is).


> Long story short, ‘dynamic’ does not guarantee KVO conformance in any
> way, shape, or form.


And declaring that your property returns a String doesn't guarantee that
it actually does either. You can always write broken code. But `dynamic`
is required for automatic KVO conformance, and it's extremely rare to
have a reason to use `dynamic` outside of KVO, so it's a really really
strong signal that the property supports KVO. If you're using `dynamic`
on a property but don't support KVO correctly, as you showed in your
code example, that's a bug with your code.


-Kevin Ballard



> On Dec 15, 2016, at 4:35 PM, Kevin Ballard  wrote:

> 

>> 

>> Oops, I mean keyPathsForValuesAffectingValue(forKey:) and
>> keyPathsForValuesAffecting().
>> 

>> That said, your code as written actually sends 2 KVO change notices
>> for "bar", and you do still need to implement
>> automaticallyNotifiesObservers… to disable the automatic KVO notice
>> for "bar".
> 

> Only when the accessor is called from Objective-C, in which the message-
> send is *always* dynamic and the presence of the ‘dynamic’ keyword is
> fairly academic. The example, which was simplified for the purpose of
> clarity, was to illustrate how things work with respect to Swift’s
> vtable dispatch system. A real-world example could shut off the
> automatic notifications, or declare the property as @nonobjc, or
> similar.


What? No. You marked the property as `dynamic`, which means it'll always
go through message send, which means it'll invoke automatic KVO
conformance and trigger 2 KVO notifications. And you can't mark a
property both `@nonobjc` and `dynamic` as the latter implies the former.


-Kevin Ballard


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


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Kevin Ballard via swift-evolution
On Thu, Dec 15, 2016, at 02:33 PM, Kevin Ballard wrote:
> On Thu, Dec 15, 2016, at 02:29 PM, Charles Srstka wrote:
> > > On Dec 15, 2016, at 2:51 PM, Michael Ilseman via swift-evolution 
> > >  wrote:
> > > 
> > >> I don't think we should ever make it possible to mark an entire class as 
> > >> `dynamic`. This just reintroduces the Obj-C problem, where many 
> > >> properties support KVO, but not all, and there's no indication on the 
> > >> property itself as to whether it supports it.
> > >> 
> > > 
> > > I’m not familiar enough with these kinds of bugs. Kevin, do you think the 
> > > existing behavior aligns with or runs counter to safe-by-default?
> > 
> > The problem Kevin describes is still here; ‘dynamic’ itself is quite 
> > orthogonal to KVO as a concept. A method being declared ‘dynamic’ is no 
> > guarantee that it actually supports KVO, and likewise, a method does not 
> > need to be marked ‘dynamic’ in order to support KVO. You can, for example, 
> > either call willChangeValue() and didChangeValue() in your willSet and 
> > didSet accessors for a stored property, or for a computed property you can 
> > simply implement the proper accessor methods to describe the dependencies, 
> > as in the example below.
> > 
> > import Foundation
> > 
> > class Watcher: NSObject {
> > var kvoContext = 0
> > 
> > init(watched: Watched) {
> > super.init()
> > watched.addObserver(self, forKeyPath: "foo", options: [], 
> > context: )
> > }
> > 
> > override func observeValue(forKeyPath keyPath: String?, of object: 
> > Any?, change: [NSKeyValueChangeKey : Any]?, context: 
> > UnsafeMutableRawPointer?) {
> > if context ==  {
> > print("foo changed; now it's \((object as! 
> > Watched).foo)")
> > } else {
> > super.observeValue(forKeyPath: keyPath, of: object, 
> > change: change, context: context)
> > }
> > }
> > }
> > 
> > class Watched: NSObject {
> > // not a single ‘dynamic’ member in here:
> > 
> > class func keyPathsForValuesAffectingFoo() -> Set { return 
> > ["bar"] }
> > var foo: Int {
> > get { return self.bar }
> > set(foo) { self.bar = foo }
> > }
> > 
> > var bar: Int = 0 {
> > willSet { self.willChangeValue(forKey: "bar") }
> > didSet { self.didChangeValue(forKey: "bar") }
> > }
> > }
> > 
> > let watched = Watched()
> > let watcher = Watcher(watched: watched)
> > 
> > watched.bar = 5 // outputs: "foo changed; now it's 5”
> > 
> > - - - - - -
> > 
> > All ‘dynamic’ does for you vis a vis KVO conformance is to automatically 
> > add the willChangeValue() and didChangeValue() calls, *for a stored 
> > property.* For a computed property, that doesn’t help you, if the 
> > dependencies aren’t properly set up. For example, if we replace the Watched 
> > class with:
> > 
> > class Watched: NSObject {
> > dynamic var foo: Int {
> > get { return self.bar }
> > set(foo) { self.bar = foo }
> > }
> > 
> > dynamic var bar: Int = 0 {
> > willSet { self.willChangeValue(forKey: "bar") }
> > didSet { self.didChangeValue(forKey: "bar") }
> > }
> > }
> > 
> > - - - - - -
> > 
> > and then change the “bar” property, no notifications will be fired, even 
> > though the value of ‘foo’ has indeed changed. So to a client of the class 
> > who can only see its interface and not the source code, ‘dynamic’ is 
> > useless on its own for determining KVO conformance.
> 
> The problem with that code isn't that `dynamic` doesn't work for computed 
> properties. It does; if you mutate the `foo` property, you'll get the KVO 
> notifications. The problem is you have one property that depends on another 
> and you didn't set up the KVO machinery properly using 
> automaticallyNotifiesObservers(forKey:) or 
> automaticallyNotifiesObserversOf() (incidentally in Swift you can write 
> the latter as a `static let`, since that becomes a class method in Obj-C).

Oops, I mean keyPathsForValuesAffectingValue(forKey:) and 
keyPathsForValuesAffecting().

That said, your code as written actually sends 2 KVO change notices for "bar", 
and you do still need to implement automaticallyNotifiesObservers… to disable 
the automatic KVO notice for "bar".

-Kevin Ballard

> So yes, `dynamic` by itself doesn't mean that the property supports KVO. But 
> there are very few reasons to use `dynamic` outside of supporting KVO, so 
> it's a pretty good signal that the property does support it. And conversely, 
> not having `dynamic` doesn't mean that it doesn't support KVO, though if it 
> does have manual KVO support using will/didChangeValue(forKey:) then it 
> should be documented as such.
> 
> > Bottom line: we really do need a new KVO-replacement system for Swift, one 
> > that could actually advertise itself as part of the interface instead of 
> > relying 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Kevin Ballard via swift-evolution
On Thu, Dec 15, 2016, at 02:29 PM, Charles Srstka wrote:
> > On Dec 15, 2016, at 2:51 PM, Michael Ilseman via swift-evolution 
> >  wrote:
> > 
> >> I don't think we should ever make it possible to mark an entire class as 
> >> `dynamic`. This just reintroduces the Obj-C problem, where many properties 
> >> support KVO, but not all, and there's no indication on the property itself 
> >> as to whether it supports it.
> >> 
> > 
> > I’m not familiar enough with these kinds of bugs. Kevin, do you think the 
> > existing behavior aligns with or runs counter to safe-by-default?
> 
> The problem Kevin describes is still here; ‘dynamic’ itself is quite 
> orthogonal to KVO as a concept. A method being declared ‘dynamic’ is no 
> guarantee that it actually supports KVO, and likewise, a method does not need 
> to be marked ‘dynamic’ in order to support KVO. You can, for example, either 
> call willChangeValue() and didChangeValue() in your willSet and didSet 
> accessors for a stored property, or for a computed property you can simply 
> implement the proper accessor methods to describe the dependencies, as in the 
> example below.
> 
> import Foundation
> 
> class Watcher: NSObject {
>   var kvoContext = 0
>   
>   init(watched: Watched) {
>   super.init()
>   watched.addObserver(self, forKeyPath: "foo", options: [], 
> context: )
>   }
>   
>   override func observeValue(forKeyPath keyPath: String?, of object: 
> Any?, change: [NSKeyValueChangeKey : Any]?, context: 
> UnsafeMutableRawPointer?) {
>   if context ==  {
>   print("foo changed; now it's \((object as! 
> Watched).foo)")
>   } else {
>   super.observeValue(forKeyPath: keyPath, of: object, 
> change: change, context: context)
>   }
>   }
> }
> 
> class Watched: NSObject {
>   // not a single ‘dynamic’ member in here:
> 
>   class func keyPathsForValuesAffectingFoo() -> Set { return 
> ["bar"] }
>   var foo: Int {
>   get { return self.bar }
>   set(foo) { self.bar = foo }
>   }
>   
>   var bar: Int = 0 {
>   willSet { self.willChangeValue(forKey: "bar") }
>   didSet { self.didChangeValue(forKey: "bar") }
>   }
> }
> 
> let watched = Watched()
> let watcher = Watcher(watched: watched)
> 
> watched.bar = 5 // outputs: "foo changed; now it's 5”
> 
> - - - - - -
> 
> All ‘dynamic’ does for you vis a vis KVO conformance is to automatically add 
> the willChangeValue() and didChangeValue() calls, *for a stored property.* 
> For a computed property, that doesn’t help you, if the dependencies aren’t 
> properly set up. For example, if we replace the Watched class with:
> 
> class Watched: NSObject {
>   dynamic var foo: Int {
>   get { return self.bar }
>   set(foo) { self.bar = foo }
>   }
>   
>   dynamic var bar: Int = 0 {
>   willSet { self.willChangeValue(forKey: "bar") }
>   didSet { self.didChangeValue(forKey: "bar") }
>   }
> }
> 
> - - - - - -
> 
> and then change the “bar” property, no notifications will be fired, even 
> though the value of ‘foo’ has indeed changed. So to a client of the class who 
> can only see its interface and not the source code, ‘dynamic’ is useless on 
> its own for determining KVO conformance.

The problem with that code isn't that `dynamic` doesn't work for computed 
properties. It does; if you mutate the `foo` property, you'll get the KVO 
notifications. The problem is you have one property that depends on another and 
you didn't set up the KVO machinery properly using 
automaticallyNotifiesObservers(forKey:) or 
automaticallyNotifiesObserversOf() (incidentally in Swift you can write 
the latter as a `static let`, since that becomes a class method in Obj-C).

So yes, `dynamic` by itself doesn't mean that the property supports KVO. But 
there are very few reasons to use `dynamic` outside of supporting KVO, so it's 
a pretty good signal that the property does support it. And conversely, not 
having `dynamic` doesn't mean that it doesn't support KVO, though if it does 
have manual KVO support using will/didChangeValue(forKey:) then it should be 
documented as such.

> Bottom line: we really do need a new KVO-replacement system for Swift, one 
> that could actually advertise itself as part of the interface instead of 
> relying on documentation (especially since Apple isn’t interested in writing 
> it anymore; the number of classes and methods that just say “No overview 
> available.” in the documentation viewer in Sierra is really quite 
> astounding). Unfortunately, this is probably additive, and thus probably 
> won’t be heard until the next phase of swift-evolution.
> 
> Charles
> 
___
swift-evolution mailing list
swift-evolution@swift.org

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-15 Thread Kevin Ballard via swift-evolution
On Thu, Dec 15, 2016, at 12:51 PM, Michael Ilseman wrote:

> 

>> On Dec 14, 2016, at 6:32 PM, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:
>> 

>> I don't think we should ever make it possible to mark an entire class
>> as `dynamic`. This just reintroduces the Obj-C problem, where many
>> properties support KVO, but not all, and there's no indication on the
>> property itself as to whether it supports it.
> 

> I’m not familiar enough with these kinds of bugs. Kevin, do you think
> the existing behavior aligns with or runs counter to safe-by-default?


The existing behavior is safe-by-default. You have to opt-in to a
property supporting KVO, and the opt-in nature of this means that the
property is self-documenting as to whether it supports KVO. Of course,
it's possible to write a `dynamic` property that actually doesn't do KVO
properly (e.g. because it's a computed property that uses another
backing property, and you modify the backing property directly), but
since 99.9% of `dynamic` properties are only dynamic in order to support
KVO, I have no concerns about someone writing a `dynamic` property that
doesn't actually do KVO properly.


-Kevin Ballard


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


Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-14 Thread Kevin Ballard via swift-evolution
On Wed, Dec 14, 2016, at 05:54 PM, Brian King wrote:
> > Please no. Just because I have to subclass NSObject doesn't mean I want to 
> > discard the performance benefits of static dispatch, and it especially 
> > doesn't mean I want to actually change the semantics of method resolution. 
> > Taking an existing Swift class and changing its base class to NSObject 
> > should not change how its methods are dispatched.
> 
> Subclassing NSObject already changes how dispatch happens. NSObject
> extensions will use message dispatch for instance. I really don't
> think that table -> message dispatch will result in a real life
> performance impact, but I agree that consistency is valuable.
> 
> The static dispatch upgrade loss is disappointing. In practice
> however, I don't think that this has ever had an impact on my code. If
> performance is a consideration, most people just drop NSObject. If you
> are using NSObject, you are probably using it because of a large
> objective-c code base, in which case, I don't think the profiler is
> really going to notice the few statically dispatched functions.

Obj-C compatibility certainly is one reason to use NSObject, but perhaps a 
bigger reason is because you're subclassing some framework-provided class, like 
UIView or UIViewController. Just because I'm subclassing UIViewController 
doesn't mean I want my controller's API to be subject to Obj-C method dispatch 
unnecessarily.

And even in the cases where I'm subclassing NSObject for Obj-C compatibility, 
that doesn't mean that most of the calls to my object are coming from Obj-C. 
All that means is that at least one place my object is used is Obj-C, and 99% 
of the uses might be Swift. Or if I'm writing a library, it might mean that I 
simply want to preserve Obj-C compatibility in case a client wants it, even 
though I expect my clients to be primarily Swift (For example, this is how 
postmates/PMHTTP is written; Obj-C–compatible, but the expectation is most 
clients will probably be Swift).

> > Interaction with Obj-C runtime machinery stuff like KVO should be opt-in. 
> > In Obj-C it's ad-hoc, many classes support it for properties but many also 
> > don't, and very few properties have their KVO conformance documented. I 
> > don't view having to mark my properties as `dynamic` to participate in KVO 
> > to be a problem with Swift but rather a feature. It tells the reader that 
> > this property supports KVO.
> 
> This is an interesting point, and it would be an interesting semantic.
> However in practice, the majority of NSObject code is imported from
> obj-c, and it's generated interface does not follow this convention.

Just because framework classes don't follow this convention doesn't mean it's 
not a valuable convention to have in code written in Swift. There's a lot of 
things that Swift does better than Obj-C, and that you don't get when using an 
API imported from Obj-C, but that's not a reason to not do those things.

> Also, it's strange to conflate how something was dispatched and if it
> supported KVO. I think property delegates will be the future here and
> enable some exciting contracts if adopted.
> 
> Another approach is to just make it easier to opt into the full obj-c
> machinery. The addition of a class or extension level `dynamic`
> keyword would be great. If we could get buy in on this, then the
> debate becomes if NSObject should default to `dynamic` or not.

I don't think we should ever make it possible to mark an entire class as 
`dynamic`. This just reintroduces the Obj-C problem, where many properties 
support KVO, but not all, and there's no indication on the property itself as 
to whether it supports it.

-Kevin Ballard

> Brian
> 
> >
> > -Kevin Ballard
> >
> > On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution wrote:
> >> I wanted to follow up to a blog post I wrote about Message Dispatch in
> >> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
> >> mentioned some changes to NSObject that didn’t result in any
> >> objections, so I thought it was time to see what the SE mailing list
> >> thought.
> >>
> >> I’ve read a few conversations on SE mailing list that have morphed
> >> into abstract conversations about dynamic vs static dispatch. I want
> >> to focus specifically on how Swift NSObject subclasses behave.
> >>
> >> I think that there are 2 changes that will result in fewer bugs and
> >> will not have a substantial impact on performance:
> >>
> >>
> >> ## Remove Table Dispatch from NSObject
> >>
> >> NSObject subclasses use table dispatch for the initial class
> >> declaration block. I think that using message dispatch for NSObject
> >> subclasses everywhere will result in a much more consistent developer
> >> experience.
> >>
> >> ## Block NSObject Visibility Optimizations
> >>
> >> Swift upgrades method dispatch to final when the compiler can prove
> >> that the method is not subclassed. I would like to see Swift be more
> >> careful about the 

Re: [swift-evolution] [Pitch] Changing NSObject dispatch behavior

2016-12-14 Thread Kevin Ballard via swift-evolution
Please no. Just because I have to subclass NSObject doesn't mean I want to 
discard the performance benefits of static dispatch, and it especially doesn't 
mean I want to actually change the semantics of method resolution. Taking an 
existing Swift class and changing its base class to NSObject should not change 
how its methods are dispatched.

Interaction with Obj-C runtime machinery stuff like KVO should be opt-in. In 
Obj-C it's ad-hoc, many classes support it for properties but many also don't, 
and very few properties have their KVO conformance documented. I don't view 
having to mark my properties as `dynamic` to participate in KVO to be a problem 
with Swift but rather a feature. It tells the reader that this property 
supports KVO.

-Kevin Ballard

On Wed, Dec 14, 2016, at 03:15 PM, Brian King via swift-evolution wrote:
> I wanted to follow up to a blog post I wrote about Message Dispatch in
> Swift — https://www.raizlabs.com/dev/2016/12/swift-method-dispatch. I
> mentioned some changes to NSObject that didn’t result in any
> objections, so I thought it was time to see what the SE mailing list
> thought.
> 
> I’ve read a few conversations on SE mailing list that have morphed
> into abstract conversations about dynamic vs static dispatch. I want
> to focus specifically on how Swift NSObject subclasses behave.
> 
> I think that there are 2 changes that will result in fewer bugs and
> will not have a substantial impact on performance:
> 
> 
> ## Remove Table Dispatch from NSObject
> 
> NSObject subclasses use table dispatch for the initial class
> declaration block. I think that using message dispatch for NSObject
> subclasses everywhere will result in a much more consistent developer
> experience.
> 
> ## Block NSObject Visibility Optimizations
> 
> Swift upgrades method dispatch to final when the compiler can prove
> that the method is not subclassed. I would like to see Swift be more
> careful about the impact of these optimizations on message dispatch,
> and consider message dispatch non-upgradable.
> 
> 
> I thought it would help to frame this choice as a trade-off between
> Swift’s goals of safe, fast, and expressive.
> 
> ## Safe
> 
> Always using message dispatch for NSObject subclasses will fix a class
> of runtime errors in framework features that are designed around
> message passing (e.g. KVO). Arguments against using dynamic features
> like this are valid, but Cocoa frameworks still use dynamic features
> and the above behaviors result in actual bugs. As a bonus, this will
> resolve SR-584, where a table-dispatched method that is overridden by
> a message dispatch method doesn’t behave correctly.
> 
> ## Fast
> 
> The above changes will result in slower dispatch in NSObject
> subclasses. However, I don't think that these dispatch changes
> actually have a tangible impact on performance. Most NSObject
> subclasses sit on top of a lot of `objc_msgSend`, and if there is a
> specific hot spot, it would still be optimizable via the final
> keyword.
> 
> ## Expressive
> 
> Using table dispatch for NSObject without any source indication or
> library documentation is not very expressive. I think it’s important
> to weigh table dispatch behavior against all of the framework
> documentation and developer experience that assume message dispatch.
> This will also eliminate the need for a lot of `@objc` and `dynamic`
> annotations that are often inconsistently applied depending on if they
> are needed in the scope they are defined in (e.g. class vs extension).
> 
> 
> If this idea shows promise, I’d be glad to formalize a Swift Evolution
> Proposal and explore syntactic details. I think being able to flag a
> class with `dynamic` and applying this flag to `NSObject` may be the
> only syntactic change needed. However, it would be good to debate the
> merit of the behavior change before the syntax.
> 
> 
> Thanks!
> 
> 
> Brian King
> ___
> 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] [Pitch] Normalize Slice Types for Unsafe Buffers

2016-12-14 Thread Kevin Ballard via swift-evolution
On Fri, Dec 9, 2016, at 11:50 AM, Dave Abrahams via swift-evolution wrote:
> 
> on Fri Dec 09 2016, Andrew Trick  wrote:
> 
> >> On Dec 9, 2016, at 10:27 AM, Dave Abrahams via swift-evolution
> >  wrote:
> >> 
> >> 
> >> on Thu Dec 08 2016, Xiaodi Wu  >> > wrote:
> >> 
> >
> >>> On Thu, Dec 8, 2016 at 6:53 PM, Ben Cohen via swift-evolution <
> >>> swift-evolution@swift.org> wrote:
> >>> 
>  
>  On Dec 8, 2016, at 4:35 PM, Jordan Rose via swift-evolution <
>  swift-evolution@swift.org> wrote:
>  
>  Um, Sequence doesn’t have a subscript (or indexes). Sequences are
>  single-pass. So if this is important, it needs to stay a Collection.
>  
>  
>  Just because something fulfills one of the requirements of a Collection
>  does not mean it should be one. It needs to tick all the boxes before its
>  allowed to be elevated.
>  
>  But it’s still allowed to have subscripts (UnsafePointer has subscripting
>  but isn’t a collection) or be multi-pass (strides are multiples but are
>  only sequences). That’s OK
>  
>  In this case, yes it’s multi-pass, yes it has a subscript, but no it 
>  isn’t
>  a collection because it doesn’t meet the requirements for slicing i.e. 
>  that
>  indices of the slice be indices of the parent.
>  (relatedly… it appears this requirement is documented on the concrete
>  Slice type rather than on Collection… which is a documentation bug we
>  should fix).
>  
> >>> 
> >>> If this is indeed a requirement for Collection, then my vote would be for
> >>> Nate's option #1 and Andy's option #2, to give UnsafeRawBufferPointer a
> >>> Slice type that fulfills the requirement. It's the smallest change,
> >>> preserves the use of integer indices, and preserves what Andy stated as 
> >>> the
> >>> desired use case of making it easy for users to switch out code written 
> >>> for
> >>> [UInt8].
> >>> 
> >>> I'm not sure I fully understand yet why Dave finds the idea of Collection
> >>> conformance fishy, 
> >> 
> >> Because the memory can easily be already bound to another type than
> >> UInt8, and there's no obvious reason why UInt8 should be privileged as a
> >> type you can get out of a raw buffer without binding the memory.
> >
> > I strongly disagree with that statement. The overwhelmingly common use
> > case for raw buffers is to view them as a sequence of UInt8 *without*
> > binding the type.  Generally, at the point that you're dealing with a
> > raw buffer it's impossible to (re)bind memory because you don't know
> > what type it holds. 
> 
> Oh, you can't just rebind to UInt8 because that's not defined as
> universally compatible with all data.  OK, sorry.

If you're dealing with raw bytes to begin with then I'd hope you're working 
with types that can be safely expressed as a collection of bytes. And since 
this is an unsafe type, I don't think there's any problem with having the 
possibility of trying to express e.g. [NSObject] as a raw byte buffer.

> > The reason it's so important to have an UnsafeRawBufferPointer data
> > type is precisely so that users don't need mess about with binding
> > memory. It's easy to get that wrong even when it's possible.
> >
> > The only reason that UInt8 is special is that when users create
> > temporary typed buffers for bytes (e.g. they sometimes want a growable
> > array or just don't want to bother with manual allocation) they always
> > use UInt8 as the element type.
> >
> > That said, we could easily divide these concerns into two types as
> > you suggested. A raw buffer, which doesn't have any special UInt8
> > features, and a RawBytes collection that handles both buffer slicing
> > and UInt8 interoperability.
> 
> But, now that I think of it, that wouldn't really solve any problems,
> would it?

Agreed. If we have a separate RawBytes type, then I'm not really sure what the 
point of UnsafeRawBufferPointer is anymore. The whole point of that type is 
it's a collection of bytes rather than just being a tuple `(baseAddress: 
UnsafeRawPointer, count: Int)`.

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


Re: [swift-evolution] [Pitch] Normalize Slice Types for Unsafe Buffers

2016-11-30 Thread Kevin Ballard via swift-evolution
This sounds like a sensible idea. But there is one behavioral change you
haven't addressed, which is that this changes how indexes work on the
slice. With all other slice types that come to mind, the slice shares
the same indexes as the base, e.g.


  let ary = Array(0..<10)

  print(ary[3]) // prints 3

  print(ary[2..<5][3]) // still prints 3



UnsafeBufferPointer is indexed using 0-based integers, so with your
proposal, slicing an UnsafeBufferPointer produces a value that uses
different indexes. We could solve this by adding a new field, but that
would break the expectation that startIndex is always zero. But we can't
just ignore this problem, because algorithms that are designed around
collections may assume that slices preserve indexes.


In addition, since you point out that UnsafeRawBufferPointer is already
its own subsequence, and that type also guarantees that startIndex is
always zero, it sounds like we already have an instance of this problem
in the stdlib, and so this needs to be addressed with
UnsafeRawBufferPointer as well.


-Kevin Ballard



On Wed, Nov 30, 2016, at 09:15 AM, Nate Cook via swift-evolution wrote:
> Hello all—



> This is a proposal for a fairly minor change in slicing behavior for
> unsafe buffers.
> Nate



> 

> --

> 

> 

> This proposal changes Swift's typed UnsafeBufferPointers to be their
> own slice type, like the UnsafeRawBufferPointer types. This is a minor
> change in the subscript API of UnsafeBufferPointer and
> UnsafeMutableBufferPointer, but constitutes a change to the standard
> library's ABI, as it can't be solved through type aliasing.
> Motivation



> The standard library has parallel pointer and buffer types for working
> with raw and typed memory. These types have broadly similar APIs that
> streamline working with pointers, as some kinds of memory manipulation
> involve moving back and forth between the two. One significant
> difference between the two groups of buffer types, however, is that
> while UnsafeRawBufferPointers are their own slice type,
> UnsafeBufferPointers use the default Slice type as a wrapper.
> Using a Slice wrapper is a needless addition when working with
> buffers—the wrapper is most useful when used to prevent copying of a
> collection's stored data, but since UnsafeBufferPointers aren't owners
> of the memory they reference, there is no copying performed when
> simply creating a new buffer over a subrange of the memory. Moreover,
> the overhead of a Slice wrapper around an UnsafeBufferPointer is
> almost certainly higher than another UnsafeBufferPointer. instance.
> The Slice wrapper makes using buffer pointers as parameters more
> cumbersome than necessary. To pass a slice of a buffer to a function
> taking a buffer, you need to create a new buffer manually:
> func _operateOnBuffer(_ buffer: UnsafeMutableBufferPointer) {
> // ... }

> let buffer: UnsafeMutableBufferPointer = ...
> _operateOnBuffer(buffer)// okay
> _operateOnBuffer(buffer[..<16])// error: type mismatch let
> subBuffer = UnsafeMutableBufferPointer(start: buffer, count: 16)
> _operateOnBuffer(subBuffer) // okay
> The wrapper complicates subscript assignment, as well. Instead of
> using simple assignment to copy all the elements of one buffer into a
> memory range of another, you must either manually create a slice or
> subscript the source buffer with its full range:
> let biggerBuffer: UnsafeMutableBufferPointer = ... let
> smallerBuffer: UnsafeMutableBufferPointer = ...
> biggerBuffer[.. smallerBuffer[.. Proposed solution



> The proposed solution is to switch the UnsafeBufferPointers to be
> their own slice type. This uses less overhead than the Slice type,
> which needs to store both the original buffer and a bounding range.
> The operations above are simpler with this change:



> _operateOnBuffer(buffer[..<16])// subscripting okay
>
> // no need to subscript 'smallerBuffer'
> biggerBuffer[.. Detailed design



> The change follows the example of the raw buffer pointer types:



> struct UnsafeBufferPointer : Collection, ... {  // other
> declarationssubscript(bounds: Range) -> UnsafeBufferPointer {
> get {  // check boundsreturn UnsafeMutableBufferPointer(
> start: self + bounds.lowerBound,  count: bounds.count) } } }

> struct UnsafeMutableBufferPointer : Collection, ... {  //
> other declarationssubscript(bounds: Range) ->
> UnsafeMutableBufferPointer {  get {  // check boundsreturn
> UnsafeMutableBufferPointer(  start: self + bounds.lowerBound,  count:
> bounds.count) }  set {  // check bounds
> _writeBackMutableSlice(, bounds: bounds, slice: newValue) } } }
> Impact on existing code



> Any existing code that works with slices of UnsafeMutableBufferPointer
> and specifies the Slice type explicitly will need to change that
> specification. This isn't a terribly common thing to do (I can't find
> 

Re: [swift-evolution] private & fileprivate

2016-10-19 Thread Kevin Ballard via swift-evolution
On Fri, Oct 14, 2016, at 02:54 PM, Nevin Brackett-Rozinsky via swift-evolution 
wrote:
> On Fri, Oct 14, 2016 at 11:51 AM, Daniel Duan  wrote:
>>
>>
>> On Oct 13, 2016, at 9:03 PM, Nevin Brackett-Rozinsky
>>  wrote:
>>> Daniel, I would be interested to hear what, exactly, are the
>>> benefits your project has realized from the new “private” compared
>>> to the old “private” (which is now called “fileprivate”).
>>
>> There's no amazing insight here. The benefit is more granular
>> control. The more people work on a project, the more useful this
>> becomes.
>>
>
> More granular control *within a single file*. That is where I have a
> hard time imagining the benefits, and thus am asking for details.
>
> If there are multiple types within a single file, it is usually
> because they need to share implementation details.

Just because they need to share some implementation details doesn't mean
they should share all of them. Or better yet, a private/fileprivate type
in a file doesn't have to share any implementation details, it can
define a proper API that it exposes to the rest of the file while
keeping its implementation details private, just as it would if it were
an internal or public type.

> The only things that I see which scope-based access (the new
> “private”) brings to the table are:
> • Scope-private members from other parts of the file are unavailable
> (and thus don’t show in autocomplete).
> • Different extensions of a type can have scope-private members with
> the same name as each other.
>
> The former seems negligible, because you are working *within the same
> file*. The API that a type vends within its own file is hardly worth
> optimizing for.
>
> And the latter I would say is an anti-feature. Using multiple
> different members with the same name in extensions just makes it
> harder to rearrange the implementation, because those scope-private
> members will collide if moved into the same extension.
>
> So I *really* don’t see the benefits. Yes, I understand that there is
> now more granular control over access within a single file. I am
> asking for examples of how that additional granularity provides
> *benefits*.

Just because you're within a single file doesn't mean you need to throw
away the principles of API design. Sure, it's not nearly as important as
something that's more widely-visible, but that's not the same thing as
saying it's not important at all. Careful control of implementation
details vs exposed API even within a single file is still useful, either
because it's much easier to make the type public if desired, or because
it makes any future refactoring much easier. And it also helps you to
reason about the code as you're looking at it, because when you're
looking at a private declaration, you only have to consider the
immediate enclosing scope, as opposed to a fileprivate declaration where
you have to consider the whole file.

-Kevin Ballard

>  On Fri, Oct 14, 2016 at 11:51 AM, Daniel Duan
>   wrote:
>>
>> You might as well ask "why not make everything public" if private and
>> fileprivate makes no difference to you.
>
> That is not a fair assertion at all. The API which a type vends to
> other files within its module, and to clients outside its module, are
> significant parts of a quality and maintainable design.
>
> I do not think the API which a type vends *within its own file*
> warrants such lofty prioritization.
>
>
>> On Fri, Oct 14, 2016 at 11:51 AM, Daniel Duan
>>  wrote:
>>>
>>>
>>> On Oct 13, 2016, at 9:03 PM, Nevin Brackett-Rozinsky
>>>  wrote:
>>>
>>> As I see it, two significant drawbacks of the new “private” are
>>> increased complexity in the access control model, and encumbrance of
>>> the old “private” with the unwieldy moniker “fileprivate”.
>>
>> The first drawback is a truism: every language addition of feature
>> makes it more complex.
>
> You can’t just write off the complexity cost like that. The new scope-
> based “private” access level brings *substantial* complexity, to both
> the implementation and the mental programming model. It creates
> *unutterable* access levels, where a scope can see a member of another
> scope, but cannot create its own member with the same access level.
>
>
>> On Fri, Oct 14, 2016 at 11:51 AM, Daniel Duan
>>  wrote:
>>
>>
>> So we need to measure the benefit with other costs, which brings us
>> to your second "drawback". I'm having a hard time understanding it.
>> Is it too hard to type? If so, as an Objective-C survivor I disagree.
>> The experience of reading code is harder and therefore more important
>> than that of authoring code. "fileprivate" was chosen over many other
>> alternatives because it's obvious to the reader. A shorter but
>> equally obvious name would have been nice. But "unwieldy" is not
>> enough reason to justify such source-breaking change at the moment.
>
> Right, 

Re: [swift-evolution] [Review] SE-0144: Allow Single Dollar Sign as a Valid Identifier

2016-10-19 Thread Kevin Ballard via swift-evolution
I'm actually vaguely surprised that the other currency symbols are
considered valid identifiers, since they're not alphanumeric symbols.
As for turning them into operators, it's a cute idea, but it doesn't
work for any symbol that's used by multiple countries. For example,
would $3.50 be USD, AUD, CAD, or any of the other dozens of countries
that use dollars?

-Kevin Ballard

On Tue, Oct 18, 2016, at 09:39 AM, Nevin Brackett-Rozinsky via swift-evolution 
wrote:
> It seems natural to me that currency symbols should be operators. This
> would allow, for example, prefix and postfix operators that take a
> number and return a “Currency” instance:
>
> let inMyPocket = $20
> let lochNess = £3.50
> let twoBits = 25¢
>
> if (inMyPocket - lochNess) > twoBits { … }
>
> Of course, the unnamed closure parameter identifiers would conflict
> with that use of the dollar sign. However, I think Anton has the right
> idea. We already use the number sign for compiler magic, so it would
> make sense to call the closure parameters #0, #1, etc. In my view
> those even read better than what we have now.
>
> Nevin
>
>
> On Tue, Oct 18, 2016 at 12:19 PM, Dave Abrahams via swift-evolution
>  wrote:
>>
>> on Mon Oct 17 2016, Jean-Denis Muys > evolut...@swift.org> wrote:
>>
>>  > While I already tersely supported this proposal, following all the
>>  > negative reactions, I feel compelled to revisit my position. The
>>  > main reason is that it strikes me that most points of view so far,
>>  > including mine, were really culturally short sighted, and far too
>>  > much US-centric.
>>  >
>>  > I totally agree that '$' being use by one (or even several) piece
>>  > of code is not reason enough to change the language. But I also
>>  > think that it being used by only one piece of code is no reason to
>>  > reject the change.
>>  >
>>  > Most of us, including me, have been blinded by two things:
>>  >
>>  > 1- the use of the $ sign in other programming languages 2- the use
>>  > of the $ sign in Swift as a prefix for implicitly declared closure
>>  > parameters
>>  >
>>  > I think this second use is not Swifty at all. It clearly (to me)
>>  > would fail the litmus test "if it wasn't there, would you add it
>>  > to the language?". Of course, it has been blessed by time, and it
>>  > has *become* Swifty, by usage because it's a useful feature,
>>  > despite the choice of its syntax being so ugly (to my non-american
>>  > eyes).
>>
>> I don't think it's un-swifty by any measure.  It's not particularly
>>  beautiful, I agree, but what would make a better, extremely
>>  terse, way
>>  to refer to a posiitional parameter of a closure?  Unless we
>>  can think
>>  of something that's obviously better, then it is thoroughly
>>  swifty: a
>>  pragmatic solution for an important problem.  Unless we can think
>>  of something that's obviously better, then it certainly *is* what we
>>  would have added to the language.
>>
>>  > Similarly, I believe the use of the $ in other language should not
>>  > be a guide in the decision here, either positively, nor
>>  > negatively. We may pay some mild attention to the concern that we
>>  > should perhaps avoid some confusion. I haven't seen much of that.
>>  >
>>  > Now for the elephant in the room: '$' is a currency symbol. As
>>  > such it should be handled like any other currency symbol. Thinking
>>  > otherwise would be very culturally offensive.
>>
>> 
>>
>>  >
>>  > In conclusion, I believe this proposal must be accepted, and
>>  > actually expanded to include ¥, ¢, £, and also to make it explicit
>>  > that currency symbols can be used in variable names as first and
>>  > only character, as first of many characters, and at any position.
>>  >
>>  > This would make $0, $1, $2… legal variable names. I believe this
>>  > is OK.
>>  >
>>  > What would happen to implicitly declared closure parameters then?
>>  > Nothing. They would continue to be implicitly declared in the
>>  > context of closures that do not declare their parameters
>>  > explicitly, similarly to `self` being implicitly declared in the
>>  > context of a class. A user willing to use $0 there would be facing
>>  > a name collision, which is OK.
>>  >
>>  > Note that such a change is purely additive: no legal source code
>>  > today would fail with this change.
>>
>> That is actually a relatively un-swifty answer in some ways.
>> It means
>>  there are magic identifiers that are usable in all contexts
>>  but given
>>  special meaning in some contexts.  I think making the lexical
>>  roles of
>>  various currency symbols more consistent is a worthy goal, but
>>  I'm not
>>  sure this is the way to do it.
>>
>>  > I hope that at the very least, I opened a new perspective on this
>>  > proposal, and I hope we can find a way to be less culturally
>>  > biased.
>>
>> If there's cultural bias here, it's a bias based on programming
>> language
>>  precedent. \$[0-9] has a long history of use as a positional
>>  

Re: [swift-evolution] [Review] SE-0144: Allow Single Dollar Sign as a Valid Identifier

2016-10-19 Thread Kevin Ballard via swift-evolution
On Mon, Oct 17, 2016, at 11:25 PM, Jean-Denis Muys via swift-evolution wrote:
> Now for the elephant in the room: '$' is a currency symbol. As such it
> should be handled like any other currency symbol. Thinking otherwise
> would be very culturally offensive.
>
> So can I use € as an variable name in Swift? According to Xcode
> 8.1B3, yes.
> Can I use any currency symbol as an variable name in Swift? According
> to Xcode 8.1B3, not quite, but almost all of them.
>
> [snip]
>
> Of course, this is just a data point, and Xcode8.1B3 should not be the
> arbiter here. But I believe whether Swift accepts currency symbols as
> variable names should be consistent. Either it accepts all of them, or
> it includes all of them.
>
> I see no reason to exclude them. On the contrary, it was a design
> feature of Swift to relieve use from the shackles of the ASCII
> character set.
>
> In conclusion, I believe this proposal must be accepted, and actually
> expanded to include ¥, ¢, £, and also to make it explicit that
> currency symbols can be used in variable names as first and only
> character, as first of many characters, and at any position.

Swift doesn't care about currency symbols. The Currency_Symbol general
category is not special to Swift. And the fact that $, ¥, ¢, and £ (and
don't forget about ¤, which you didn't list) aren't valid identifiers is
a consequence of how they're categorized by Unicode, not some
intentional decision by Swift. Specifically, all of the currency symbols
that are in the Basic Latin block (e.g. any currency symbol in the range
U+–U+00FF) have the Pattern_Syntax property. And the Pattern_Syntax
property is defined by Unicode (see UAX #31) as a stable set of
characters that are appropriate to use for syntax in
patterns/expressions (e.g. programming language syntax, regular
expressions, ICU number formats, etc). I don't have a good way to test
this (UnicodeChecker has no way to search for all characters with the
Pattern_Syntax property), but AFAIK all Pattern_Syntax characters are
not legal identifiers in Swift, with any character not already reserved
for use by the Swift grammar (e.g. $ being used for positional
parameters) being available for operators.

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0144: Allow Single Dollar Sign as a Valid Identifier

2016-10-14 Thread Kevin Ballard via swift-evolution
On Fri, Oct 14, 2016, at 12:59 PM, Chris Lattner wrote:
>   * What is your evaluation of the proposal?

-1. I agree with the reasons for removal, and do not consider the existence of 
a single library that depends on undocumented behavior to be sufficient reason 
for this change.

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

A quick reading.

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


Re: [swift-evolution] private & fileprivate

2016-10-13 Thread Kevin Ballard via swift-evolution
On Sat, Oct 8, 2016, at 07:42 AM, Anton Zhilin via swift-evolution wrote:
> As far as I can see, almost all people, who talk here, agree that
> private / fileprivate distinction brought more harm than good. Despite
> corresponding proposal being accepted.
> I think, it means that current mailing-list system is failing. Let's
> accept it, gmane looks and feels ugly by comparison to forums. And
> using email limits the number of people involved by an order of
> magnitude.
> What we need is popularization of SE, reaching as many developers as
> we can, using simple voting, likes, and so on.

This is a bad conclusion. Discussions like this naturally attract people
who are unhappy with the status quo. So it's no surprise that you're
seeing a lot of people say they don't like private. Personally, I *love*
having the new private and I use it almost everywhere. It's very rare
for me to write fileprivate and when I do, it's an intentional decision.
And the only reason I even saw this thread is because someone linked it
to me on Slack.

-Kevin Ballard

> 2016-10-08 12:31 GMT+03:00 Haravikk via swift-evolution  evolut...@swift.org>:
>>
>> > On 7 Oct 2016, at 22:44, Tony Allevato via swift-evolution > > evolut...@swift.org> wrote:
>>  > personally I thought `private` was fine the way it was when it
>>  > meant `fileprivate` and I had no real need for `private` as it
>>  > exists in Swift 3.
>>
>> I have to agree with this; I wasn't especially comfortable with the
>> change (or the eventual choice of keyword style) and in practice I
>> just don't find it useful. I haven't used the new "private" even once
>> since it was added, except by accident, the only form of private I
>> use is fileprivate.
>>
>>  I've happily embraced the conform through extension style in Swift,
>>  and really when it comes down to it the new private access level
>>  just isn't compatible with that style of development. It's only
>>  really useful for hiding details of something you add in one
>>  specific section, which I almost never do (and when I do I just mark
>>  it fileprivate in case I can re-use it).
>>
>>  Maybe some people do find it useful, but I'd prefer fileprivate to
>>  be the default behaviour of private; the current (scoped?) private
>>  access level seems far more limited, thus more deserving of a less
>>  convenient keyword, or some kind of modifier on private. But
>>  personally I'd be fine with removing it, as I don't think it really
>>  adds anything that fileprivate doesn't already cover.
> _
> 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] [Proposal draft] Disallow Optionals in String Interpolation Segments

2016-10-04 Thread Kevin Ballard via swift-evolution
On Tue, Oct 4, 2016, at 12:01 PM, Xiaodi Wu wrote:
> On Tue, Oct 4, 2016 at 1:49 PM, Kevin Ballard <ke...@sb.org> wrote:
>> __
>> On Tue, Oct 4, 2016, at 11:34 AM, Xiaodi Wu wrote:
>>> On Tue, Oct 4, 2016 at 1:06 PM, Kevin Ballard via swift-evolution
>>> <swift-evolution@swift.org> wrote:
>>>> __
>>>>
>>>> On Tue, Oct 4, 2016, at 10:44 AM, Mark Lacey wrote:
>>>>>
>>>>>> On Oct 4, 2016, at 10:29 AM, Kevin Ballard via swift-evolution
>>>>>> <swift-evolution@swift.org> wrote:
>>>>>>
>>>>>> On Tue, Oct 4, 2016, at 10:28 AM, Nate Cook wrote:
>>>>>>>> On Oct 3, 2016, at 5:49 PM, Kevin Ballard via swift-evolution
>>>>>>>> <swift-evolution@swift.org> wrote:
>>>>>>>>
>>>>>>>> On Mon, Oct 3, 2016, at 03:18 PM, Jordan Rose wrote:
>>>>>>>>>>
>>>>>>>>>> ...
>>>>>>>>>>
>>>>>>>>> We had this at one point, but we took it out because people
>>>>>>>>> would forget to test the nil case. I think `?? ""` or `?? nil`
>>>>>>>>> really is the best answer here.
>>>>>>>>
>>>>>>>> But you can't write that, unless you're dealing specifically
>>>>>>>> with an Optional.  If you try you'll get an error:
>>>>>>>>
>>>>>>>> unnamed.swift:2:19: error: binary operator '??' cannot be
>>>>>>>> applied to operands of type 'Int?' and 'String'
>>>>>>>> print("x: \(x ?? "nil")")
>>>>>>>> ~ ^  ~
>>>>>>>> unnamed.swift:2:19: note: overloads for '??' exist with these
>>>>>>>> partially matching parameter lists: (T?, @autoclosure () throws
>>>>>>>> -> T), (T?, @autoclosure () thro
>>>>>>>> ws -> T?)
>>>>>>>> print("x: \(x ?? "nil")")
>>>>>>>>   ^
>>>>>>>> This leads to writing code like "…
>>>>>>>> \(x.map(String.init(describing:)) ?? "nil")" which is pretty
>>>>>>>> gross.
>>>>>>>
>>>>>>> I think that if we're going to add this warning we should make
>>>>>>> it possible to provide a string as an alternative. It seems like
>>>>>>> it should be possible to build a ?? operator with a (T?, String)
>>>>>>> -> _StringInterpolationSomething signature that works only in a
>>>>>>> string interpolation context.
>>>>>>>
>>>>>>> There are some types that aren't trivially constructible, or
>>>>>>> don't have clear alternatives for the nil case. Other times it
>>>>>>> might just not make sense to build a new instance simply to turn
>>>>>>> it into a string. If we're going to make people provide an
>>>>>>> alternative for optionals in this otherwise simple-to-use
>>>>>>> construct, let's make it simple to do so.
>>>>>>>
>>>>>>> This is undoubtedly a more complex approach that could be
>>>>>>> considered separately, but I think it would be a valuable part
>>>>>>> of how developers could transition their code.
>>>>>
>>>>> That’s definitely more complex, and seems like a completely
>>>>> orthogonal feature request.
>>>>>
>>>>>>>
>>>>>> I like this idea. This combined with the warning for naively
>>>>>> interpolating an Optional would be a good solution, because now
>>>>>> when I see the warning I can trivially solve it with `?? "nil”`.
>>>>>
>>>>> If you can suppress the warning with `as T?` (where T? is the type
>>>>> of the thing being warned on), you wouldn’t need a form that
>>>>> specifically printed “nil”, correct?
>>>>
>>>>
>>>> How many times do I need to repeat myself? I'm looking for a
>>>> solution to the problem where printing Optionals sanely (e.g. no
>>>> "Optional(…)" wrapper for .some values) is a PITA right now.
>>>> Getting rid of the warning does not solve this problem. This is why
>>>> I like Nate Cook's idea to enable `?? "nil"` in string
>>>> interpolations, because it *does* solve my problem. And with this
>>>> tool, now the warning on printing Optionals becomes useful because
>>>> it tells me where to add `?? "nil"`. Getting rid of the warning
>>>> without the ability to add `?? "nil"` is not helpful to me, because
>>>> I don't want to print "Optional(…)".
>>>
>>> I'm confused. Why not just add this to your project?
>>>
>>> ```
>>> extension Optional : CustomStringConvertible {
>>> public var description: String {
>>> guard let some = self else { return "nil" }
>>> return String(describing: some)
>>> }
>>> }
>>> ```
>>
>> Because that's globally changing the behavior of Optional in a way
>> that's very surprising.
>
> Agreed, but I thought that's what you were asking for above?

I wanted to change the behavior of string interpolation specifically,
not the behavior of `String(describing: someOptionalValue)`.

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


Re: [swift-evolution] [Proposal draft] Disallow Optionals in String Interpolation Segments

2016-10-04 Thread Kevin Ballard via swift-evolution
On Tue, Oct 4, 2016, at 11:34 AM, Xiaodi Wu wrote:
> On Tue, Oct 4, 2016 at 1:06 PM, Kevin Ballard via swift-evolution  evolut...@swift.org> wrote:
>> __
>>
>> On Tue, Oct 4, 2016, at 10:44 AM, Mark Lacey wrote:
>>>
>>>> On Oct 4, 2016, at 10:29 AM, Kevin Ballard via swift-evolution >>> evolut...@swift.org> wrote:
>>>>
>>>> On Tue, Oct 4, 2016, at 10:28 AM, Nate Cook wrote:
>>>>>> On Oct 3, 2016, at 5:49 PM, Kevin Ballard via swift-evolution >>>>> evolut...@swift.org> wrote:
>>>>>>
>>>>>> On Mon, Oct 3, 2016, at 03:18 PM, Jordan Rose wrote:
>>>>>>>>
>>>>>>>> ...
>>>>>>>>
>>>>>>> We had this at one point, but we took it out because people
>>>>>>> would forget to test the nil case. I think `?? ""` or `?? nil`
>>>>>>> really is the best answer here.
>>>>>>
>>>>>> But you can't write that, unless you're dealing specifically with
>>>>>> an Optional.  If you try you'll get an error:
>>>>>>
>>>>>> unnamed.swift:2:19: error: binary operator '??' cannot be applied
>>>>>> to operands of type 'Int?' and 'String'
>>>>>> print("x: \(x ?? "nil")")
>>>>>> ~ ^  ~
>>>>>> unnamed.swift:2:19: note: overloads for '??' exist with these
>>>>>> partially matching parameter lists: (T?, @autoclosure () throws
>>>>>> -> T), (T?, @autoclosure () thro
>>>>>> ws -> T?)
>>>>>> print("x: \(x ?? "nil")")
>>>>>>   ^
>>>>>> This leads to writing code like "…
>>>>>> \(x.map(String.init(describing:)) ?? "nil")" which is pretty
>>>>>> gross.
>>>>>
>>>>> I think that if we're going to add this warning we should make it
>>>>> possible to provide a string as an alternative. It seems like it
>>>>> should be possible to build a ?? operator with a (T?, String) ->
>>>>> _StringInterpolationSomething signature that works only in a
>>>>> string interpolation context.
>>>>>
>>>>> There are some types that aren't trivially constructible, or don't
>>>>> have clear alternatives for the nil case. Other times it might
>>>>> just not make sense to build a new instance simply to turn it into
>>>>> a string. If we're going to make people provide an alternative for
>>>>> optionals in this otherwise simple-to-use construct, let's make it
>>>>> simple to do so.
>>>>>
>>>>> This is undoubtedly a more complex approach that could be
>>>>> considered separately, but I think it would be a valuable part of
>>>>> how developers could transition their code.
>>>
>>> That’s definitely more complex, and seems like a completely
>>> orthogonal feature request.
>>>
>>>>>
>>>> I like this idea. This combined with the warning for naively
>>>> interpolating an Optional would be a good solution, because now
>>>> when I see the warning I can trivially solve it with `?? "nil”`.
>>>
>>> If you can suppress the warning with `as T?` (where T? is the type
>>> of the thing being warned on), you wouldn’t need a form that
>>> specifically printed “nil”, correct?
>>
>>
>> How many times do I need to repeat myself? I'm looking for a solution
>> to the problem where printing Optionals sanely (e.g. no "Optional(…)"
>> wrapper for .some values) is a PITA right now. Getting rid of the
>> warning does not solve this problem. This is why I like Nate Cook's
>> idea to enable `?? "nil"` in string interpolations, because it *does*
>> solve my problem. And with this tool, now the warning on printing
>> Optionals becomes useful because it tells me where to add `?? "nil"`.
>> Getting rid of the warning without the ability to add `?? "nil"` is
>> not helpful to me, because I don't want to print "Optional(…)".
>
> I'm confused. Why not just add this to your project?
>
> ```
> extension Optional : CustomStringConvertible {
> public var description: String {
> guard let some = self else { return "nil" }
> return String(describing: some)
> }
> }
> ```

Because that's globally changing the behavior of Optional in a way
that's very surprising.

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


Re: [swift-evolution] [Proposal draft] Disallow Optionals in String Interpolation Segments

2016-10-04 Thread Kevin Ballard via swift-evolution
On Tue, Oct 4, 2016, at 10:28 AM, Nate Cook wrote:
>> On Oct 3, 2016, at 5:49 PM, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:
>>
>> On Mon, Oct 3, 2016, at 03:18 PM, Jordan Rose wrote:
>>>>
>>>> ...
>>>>
>>> We had this at one point, but we took it out because people would
>>> forget to test the nil case. I think `?? ""` or `?? nil` really is
>>> the best answer here.
>>
>> But you can't write that, unless you're dealing specifically with an
>> Optional.  If you try you'll get an error:
>>
>> unnamed.swift:2:19: error: binary operator '??' cannot be applied to
>> operands of type 'Int?' and 'String'
>> print("x: \(x ?? "nil")")
>> ~ ^  ~
>> unnamed.swift:2:19: note: overloads for '??' exist with these
>> partially matching parameter lists: (T?, @autoclosure () throws ->
>> T), (T?, @autoclosure () thro
>> ws -> T?)
>> print("x: \(x ?? "nil")")
>>   ^
>> This leads to writing code like "… \(x.map(String.init(describing:))
>> ?? "nil")" which is pretty gross.
>
> I think that if we're going to add this warning we should make it
> possible to provide a string as an alternative. It seems like it
> should be possible to build a ?? operator with a (T?, String) ->
> _StringInterpolationSomething signature that works only in a string
> interpolation context.
>
> There are some types that aren't trivially constructible, or don't
> have clear alternatives for the nil case. Other times it might just
> not make sense to build a new instance simply to turn it into a
> string. If we're going to make people provide an alternative for
> optionals in this otherwise simple-to-use construct, let's make it
> simple to do so.
>
> This is undoubtedly a more complex approach that could be considered
> separately, but I think it would be a valuable part of how developers
> could transition their code.

I like this idea. This combined with the warning for naively
interpolating an Optional would be a good solution, because now when I
see the warning I can trivially solve it with `?? "nil"`.

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


Re: [swift-evolution] [Proposal draft] Disallow Optionals in String Interpolation Segments

2016-10-03 Thread Kevin Ballard via swift-evolution
On Mon, Oct 3, 2016, at 06:49 PM, Robert Widmann wrote:
>
>> On Oct 3, 2016, at 8:49 PM, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:
>>
>> I assume you meant that as a reply to me?
>>
>> The problem is twofold:
>>
>> 1. Printing the value without adornment, or "nil" for nil, is a
>>very common thing to want to do and we shouldn't have to write
>>code like `\(x.map(String.init(describing:)) ?? "nil")` to
>>accomplish it.
>
> My point is before you were unable to do this without the ‘uglyness’
> presented here anyway [you would have gotten “Optional(“value”)”], so
> I don’t see the point of raising this concern.  If you want the old
> behavior, just ask for it with an explicit cast or
> `.debugDescription`.

This proposal was done because the current behavior of Optionals in
string interpolation isn't very useful for most people. You're proposing
banning it outright (with an escape hatch to recover the current
behavior). I'm saying that, since it isn't very useful for most people,
instead of banning it we could make it useful.

-Kevin

>> 2. Due to the changes made to IUOs, if you use a IUO in a string
>>interpolation, previously it would print as desired (either the
>>value or the string `"nil"`) but now it prints as Optional (e.g.
>>with the `"Optional(…)"` wrapper).
>
> IUOs are not in the scope for this proposal, but I get your point.
>
>>
>> -Kevin
>>
>> On Mon, Oct 3, 2016, at 05:43 PM, Robert Widmann via swift-
>> evolution wrote:
>>> Under our proposal you can return to the old semantics of printing
>>> nil with an explicit optional cast - one which we will offer to
>>> insert for you.
>>>
>>> Otherwise if you actually intend for a default value that value
>>> would have type Int, not String.  Under the current regime if you
>>> want to print something custom the for nil the way you've got it now
>>> you're going to have to go through the reflecting initializer anyway
>>> so I don't see a problem here.
>>>
>>> ~Robert Widmann
>>>
>>> 2016/10/03 19:25、Charlie Monroe via swift-evolution >> evolut...@swift.org> のメッセージ:
>>>> I've already suggested this quite some time back and was told that
>>>> this doesn't need to go through evolution. It's filed here:
>>>> https://bugs.swift.org/browse/SR-1882
>>>>
>>>> Unfortunately, I haven't had time to look into it myself and I'm
>>>> unlikely to have the time anytime soon...
>>>>
>>>>> On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution >>>> evolut...@swift.org> wrote:
>>>>>
>>>>>
>>>>> Hey all,
>>>>>
>>>>> Julio Carrettoni, Robert Widmann, and I have been working on a
>>>>> proposal to mitigate something that's burned us all since Swift 1.
>>>>> We'd love some feedback!
>>>>>
>>>>> It's available here:
>>>>> https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd
>>>>>
>>>>> I've posted the current draft below.
>>>>>
>>>>> Thanks,
>>>>> Harlan Haskins
>>>>>
>>>>> Disallow Optionals in String Interpolation Segments


>>>>>  * Proposal: SE-[1]
>>>>>  * Authors: Harlan Haskins[2], Julio Carrettoni[3], Robert
>>>>>Widmann[4]
>>>>>  * Review Manager: TBD
>>>>>  * Status: Awaiting revie
>>>>> Introduction
>>>>> Swift developers frequently use string interpolation as a
>>>>> convenient, concise syntax for interweaving variable values with
>>>>> strings. The interpolation machinery, however, has surprising
>>>>> behavior in one specific case: Optional. If a user puts an
>>>>> optional value into a string interpolation segment, it will insert
>>>>> either "Optional("value")" or "nil" in the resulting string.
>>>>> Neither of these is particularly desirable, so we propose a
>>>>> warning and fix-it to surface solutions to these potential
>>>>> mistakes.
>>>>> Swift-evolution thread: Discussion thread topic for that
>>>>> proposal[5]
>>>>> Motivation
>>>>> *The Swift Programming Language* defines string interpolation
>>>>> segments as "a way to construct a new String value from a mix of
>>

Re: [swift-evolution] [Proposal draft] Introducing `indexed()` collections

2016-10-03 Thread Kevin Ballard via swift-evolution
On Mon, Oct 3, 2016, at 02:51 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Mon Oct 03 2016, Kevin Ballard  wrote:
> 
> > On Fri, Sep 30, 2016, at 08:53 PM, Dave Abrahams via swift-evolution wrote:
> >> 
> >> on Wed Sep 28 2016, Erica Sadun  wrote:
> >> 
> >> > Indices have a specific, fixed meaning in Swift, which are used to 
> >> > create valid collection
> >> > subscripts. This proposal introduces indexed() to produce a more 
> >> > semantically relevant sequence
> > by
> >
> >> > pairing a collection's indices with its members. While it is trivial to 
> >> > create a solution in Swift,
> >> > the most common developer approach shown here calculates indexes twice:
> >> >
> >> > extension Collection {
> >> > /// Returns a sequence of pairs (*idx*, *x*), where *idx* represents 
> >> > a
> >> > /// consecutive collection index, and *x* represents an element of
> >> > /// the sequence.
> >> > func indexed() -> Zip2Sequence {
> >> > return zip(indices, self)
> >> > }
> >> > }
> >> 
> >> How does this calculate indices twice?
> >
> > It calculates indices twice for any collection that uses
> > IndexingIterator as its iterator. 
> 
> Yes.  Not in general; just in that particular case.
> 
> > And for collections that doesn't, it still does the moral equivalent,
> > because it's calculating an index offset along with whatever work the
> > Iterator does to calculate the next element.
> 
> Indexing is supposed to be cheap; almost free.  Lazy filtered
> collections are an anomaly.  They're arguably not even legal
> Collections, because advancing an index may not be O(1).  They exist
> because they're useful, but you shouldn't pass them out without
> understanding the consequences.

Using an index is supposed to be cheap/free. Calculating the next index is not 
guaranteed to be so. If you want another example of something that's not lazy, 
try String.CharacterView. Calculating the next index may be arbitrarily complex 
since I can string as many combining marks together as I want, though in 
practice it will be pretty cheap. But even this "pretty cheap" is still work, 
and depending on what I'm doing in the loop, calculating character indexes may 
be a significant fraction of the work performed.

> > As an example, if my collection is `someArray.lazy.filter(…)` then
> > zip(col.indices, col) will run the filter twice over the collection.
> 
> Okay.
> 
> >> > Incrementing an index in some collections can be unnecessarily
> >> > costly. 
> >> 
> >> Seems like it's only *unnecessarily* costly in badly implemented
> >> collections?
> >
> > A collection doesn't have to be badly-implemented to have a
> > non-trivial cost for calculating the next element. 
> > As above, someArray.lazy.filter(…) is a good example of such a
> > collection.
> 
> Its conformance to Collection is quite sketchy.

But it's not the only collection where calculating indexes is non-trivial.

-Kevin Ballard

> >> > In a lazy filtered collection, an index increment is potentially
> >> > O(N). We feel this is better addressed introducing a new function into
> >> > the Standard Library to provide a more efficient design that avoids
> >> > the attractive nuisance of the "obvious" solution.
> >> 
> >> I am generally opposed to adding this.  The usual solution developers
> >> will reach for here is:
> >> 
> >> for i in x.indices {
> >> somethingWith(x[i])
> >> }
> >> 
> >> zip(indices, self) is only suboptimal for lazy filtered sequences, which
> >> should be used with care anyhow (see the note here:
> >> http://swiftdoc.org/v3.0/type/LazyFilterCollection/).
> >
> > It's suboptimal for any collection with a non-trivial index.
> 
> Which should be an exceedingly rare thing.
> 
> >> If you really need a lazy sequence of pairs that's optimal with lazy
> >> filtered sequences, 
> >> 
> >> x.indices.lazy.map { ($0, x[$0]) }
> >> 
> >> is a good solution and pretty easy to write.
> >
> > And yet people will write zip(x.indices, x) instead because it's
> > shorter and not immediately obvious that it may be suboptimal
> > depending on the collection.
> >
> > Why are you opposed to adding this? 
> 
> Mostly because it's additional API complexity, the usefulness appears to
> be marginal, and it's optimizing for what should be a rare corner case
> (collections that don't conform to efficiency expectations).
> 
> I'm not dead-set against adding it, but ATM it doesn't seem like there
> are important use-cases that will benefit substantially from having it.
> Convince me this is addressing a real need, and we'll talk.  In phase 2
> :-).
> 
> > The ability to work around its lack doesn't mean it doesn't have
> > value, and the fact that the simplest workaround is not the best one
> > is I think a good reason to make the easiest solution into the best
> > one (by providing .indexed()). Add to that the fact that a lot of
> > people probably use 

Re: [swift-evolution] [Proposal draft] Disallow Optionals in String Interpolation Segments

2016-10-03 Thread Kevin Ballard via swift-evolution
I assume you meant that as a reply to me?

The problem is twofold:

1. Printing the value without adornment, or "nil" for nil, is a very
   common thing to want to do and we shouldn't have to write code like
   `\(x.map(String.init(describing:)) ?? "nil")` to accomplish it.
2. Due to the changes made to IUOs, if you use a IUO in a string
   interpolation, previously it would print as desired (either the value
   or the string `"nil"`) but now it prints as Optional (e.g. with the
   `"Optional(…)"` wrapper).

-Kevin

On Mon, Oct 3, 2016, at 05:43 PM, Robert Widmann via swift-evolution wrote:
> Under our proposal you can return to the old semantics of printing
> nil with an explicit optional cast - one which we will offer to
> insert for you.
>
> Otherwise if you actually intend for a default value that value would
> have type Int, not String.  Under the current regime if you want to
> print something custom the for nil the way you've got it now you're
> going to have to go through the reflecting initializer anyway so I
> don't see a problem here.
>
> ~Robert Widmann
>
> 2016/10/03 19:25、Charlie Monroe via swift-evolution  evolut...@swift.org> のメッセージ:
>> I've already suggested this quite some time back and was told that
>> this doesn't need to go through evolution. It's filed here:
>> https://bugs.swift.org/browse/SR-1882
>>
>> Unfortunately, I haven't had time to look into it myself and I'm
>> unlikely to have the time anytime soon...
>>
>>> On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution >> evolut...@swift.org> wrote:
>>>
>>>
>>> Hey all,
>>>
>>> Julio Carrettoni, Robert Widmann, and I have been working on a
>>> proposal to mitigate something that's burned us all since Swift 1.
>>> We'd love some feedback!
>>>
>>> It's available here:
>>> https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd
>>>
>>> I've posted the current draft below.
>>>
>>> Thanks,
>>> Harlan Haskins
>>>
>>> Disallow Optionals in String Interpolation Segments


>>>  * Proposal: SE-[1]
>>>  * Authors: Harlan Haskins[2], Julio Carrettoni[3], Robert
>>>Widmann[4]
>>>  * Review Manager: TBD
>>>  * Status: Awaiting revie
>>> Introduction
>>> Swift developers frequently use string interpolation as a
>>> convenient, concise syntax for interweaving variable values with
>>> strings. The interpolation machinery, however, has surprising
>>> behavior in one specific case: Optional. If a user puts an
>>> optional value into a string interpolation segment, it will insert
>>> either "Optional("value")" or "nil" in the resulting string. Neither
>>> of these is particularly desirable, so we propose a warning and fix-
>>> it to surface solutions to these potential mistakes.
>>> Swift-evolution thread: Discussion thread topic for that proposal[5]
>>> Motivation
>>> *The Swift Programming Language* defines string interpolation
>>> segments as "a way to construct a new String value from a mix of
>>> constants, variables, literals, and expressions". There is one type
>>> that runs counter to this definition: Optional. The .none case in
>>> particular is used to indicate the absence of a value. Moreover, its
>>> inclusion in interpolation segments leads to the dreaded "nil" in
>>> output that is often fed to UI elements. Even barring that,
>>> interpolating a non-nil optional value yields "Optional("value")", a
>>> result that is not useful even in logged output.
>>> Given that the Optional type is never fit for display to the end
>>> user, and can often be a surprising find in the console, we propose
>>> that requesting an Optional's debug description be an explicit act.
>>> This proposal now requires a warning when using an expression of
>>> Optional type within a string interpolation segment.
>>> Proposed solution
>>> The user will be warned after attempting to use an expression with
>>> type Optional in a string interpolation segment. They will then
>>> be offered a fixit suggesting they explicitly request the
>>> debugDescription of the Optional value instead.
>>> Detailed design
>>> Semantic analysis currently does not do much but guarantee the well-
>>> formedness of expressions in interpolation segments. These are then
>>> fed directly to String.init(stringInterpolationSegment:) and are run
>>> through the runtime reflection system to generate a description.
>>> Semantic analysis will be tweaked to inspect the result of solving
>>> an interpolation segment for an Optional and will offer a fixit in
>>> that case.
>>> Impact on existing code
>>> As this is a warning, code written before this proposal will
>>> continue to compile and run with the same semantics as before.
>>> Authors of code that makes use of this unsafe pattern will be
>>> offered a migration path to the safer, more explicit form.
>>> Alternatives considered


>>>  * A fixit that suggests a default value be inserted would be
>>>entirely appropriate (following the style of the fixit introduced
>>>in SE-0140[6]).


>>>  * Forbidding this 

Re: [swift-evolution] [Proposal draft] Disallow Optionals in String Interpolation Segments

2016-10-03 Thread Kevin Ballard via swift-evolution
On Mon, Oct 3, 2016, at 03:18 PM, Jordan Rose wrote:
>
>> On Oct 3, 2016, at 14:41, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:
>>
>> On Mon, Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-
>> evolution wrote:
>>> Swift developers frequently use string interpolation as a
>>> convenient, concise syntax for interweaving variable values with
>>> strings. The interpolation machinery, however, has surprising
>>> behavior in one specific case: Optional. If a user puts an
>>> optional value into a string interpolation segment, it will insert
>>> either "Optional("value")" or "nil" in the resulting string. Neither
>>> of these is particularly desirable, so we propose a warning and fix-
>>> it to surface solutions to these potential mistakes.
>>
>> Is there any way we could instead allow Optionals but just print
>> them the way we print ImplicitlyUnwrappedOptionals? That's almost
>> always how I want my Optionals to work when interpolating. To be
>> specific, this means for .some(x) we just print x, and for .none we
>> print "nil".
> We had this at one point, but we took it out because people would
> forget to test the nil case. I think `?? ""` or `?? nil` really is the
> best answer here.

But you can't write that, unless you're dealing specifically with an
Optional.  If you try you'll get an error:

unnamed.swift:2:19: error: binary operator '??' cannot be applied to
operands of type 'Int?' and 'String'
print("x: \(x ?? "nil")")
~ ^  ~
unnamed.swift:2:19: note: overloads for '??' exist with these partially
matching parameter lists: (T?, @autoclosure () throws -> T), (T?,
@autoclosure () thro
ws -> T?)
print("x: \(x ?? "nil")")
  ^
This leads to writing code like "… \(x.map(String.init(describing:)) ??
"nil")" which is pretty gross.

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


Re: [swift-evolution] [Proposal draft] Disallow Optionals in String Interpolation Segments

2016-10-03 Thread Kevin Ballard via swift-evolution
On Mon, Oct 3, 2016, at 10:52 AM, Harlan Haskins via swift-evolution wrote:
> Swift developers frequently use string interpolation as a convenient,
> concise syntax for interweaving variable values with strings. The
> interpolation machinery, however, has surprising behavior in one
> specific case: Optional. If a user puts an optional value into a
> string interpolation segment, it will insert either
> "Optional("value")" or "nil" in the resulting string. Neither of these
> is particularly desirable, so we propose a warning and fix-it to
> surface solutions to these potential mistakes.

Is there any way we could instead allow Optionals but just print them
the way we print ImplicitlyUnwrappedOptionals? That's almost always how
I want my Optionals to work when interpolating. To be specific, this
means for .some(x) we just print x, and for .none we print "nil".

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


Re: [swift-evolution] [Proposal draft] Introducing `indexed()` collections

2016-10-03 Thread Kevin Ballard via swift-evolution
On Fri, Sep 30, 2016, at 08:53 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Wed Sep 28 2016, Erica Sadun  wrote:
> 
> > Indices have a specific, fixed meaning in Swift, which are used to create 
> > valid collection
> > subscripts. This proposal introduces indexed() to produce a more 
> > semantically relevant sequence by
> > pairing a collection's indices with its members. While it is trivial to 
> > create a solution in Swift,
> > the most common developer approach shown here calculates indexes twice:
> >
> > extension Collection {
> > /// Returns a sequence of pairs (*idx*, *x*), where *idx* represents a
> > /// consecutive collection index, and *x* represents an element of
> > /// the sequence.
> > func indexed() -> Zip2Sequence {
> > return zip(indices, self)
> > }
> > }
> 
> How does this calculate indices twice?

It calculates indices twice for any collection that uses IndexingIterator as 
its iterator. And for collections that doesn't, it still does the moral 
equivalent, because it's calculating an index offset along with whatever work 
the Iterator does to calculate the next element.

As an example, if my collection is `someArray.lazy.filter(…)` then 
zip(col.indices, col) will run the filter twice over the collection.

> > Incrementing an index in some collections can be unnecessarily
> > costly. 
> 
> Seems like it's only *unnecessarily* costly in badly implemented
> collections?

A collection doesn't have to be badly-implemented to have a non-trivial cost 
for calculating the next element. As above, someArray.lazy.filter(…) is a good 
example of such a collection.

> > In a lazy filtered collection, an index increment is potentially
> > O(N). We feel this is better addressed introducing a new function into
> > the Standard Library to provide a more efficient design that avoids
> > the attractive nuisance of the "obvious" solution.
> 
> I am generally opposed to adding this.  The usual solution developers
> will reach for here is:
> 
> for i in x.indices {
> somethingWith(x[i])
> }
> 
> zip(indices, self) is only suboptimal for lazy filtered sequences, which
> should be used with care anyhow (see the note here:
> http://swiftdoc.org/v3.0/type/LazyFilterCollection/).

It's suboptimal for any collection with a non-trivial index.

> If you really need a lazy sequence of pairs that's optimal with lazy
> filtered sequences, 
> 
> x.indices.lazy.map { ($0, x[$0]) }
> 
> is a good solution and pretty easy to write.

And yet people will write zip(x.indices, x) instead because it's shorter and 
not immediately obvious that it may be suboptimal depending on the collection.

Why are you opposed to adding this? The ability to work around its lack doesn't 
mean it doesn't have value, and the fact that the simplest workaround is not 
the best one is I think a good reason to make the easiest solution into the 
best one (by providing .indexed()). Add to that the fact that a lot of people 
probably use .enumerated() to produce indexes when working with arrays, and 
this is a pitfall when working with other types, such as ArraySlice which still 
has Int indexes but is no longer zero-based.

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


Re: [swift-evolution] [Proposal draft] Introducing `indexed()` collections

2016-09-29 Thread Kevin Ballard via swift-evolution
Well you kind of did say it should be removed. If we came up with a new
design that produced an Int for sequences and an Index for collections,
then you can't get an Int for collections (without wrapping the
collection in AnySequence), which is basically the same thing as just
removing enumerated() for collections.

-Kevin

On Wed, Sep 28, 2016, at 07:08 PM, Colin Barrett wrote:
> I’m aware, which is why I didn’t say it should be removed. (And if I
> hadn’t been aware, this wouldn’t have helped me discover them. :-)
>
>> On Sep 28, 2016, at 8:58 PM, Kevin Ballard  wrote:
>>
>> There's more uses for enumerated() than just producing Array indices.
>>
>> -Kevin
>>
>> On Wed, Sep 28, 2016, at 05:49 PM, Colin Barrett via swift-
>> evolution wrote:
>>> Definitely well motivated. It seems like having both .enumerated()
>>> and .indexed() methods would still leave open the possibility of
>>> novices using .enumerated and making the same mistake as before. I
>>> realize that because of where .enumerated() sits it has to work the
>>> way it does, but is there perhaps a better design (with constrained
>>> extensions?) for a single method that can give an Int for a Sequence
>>> and an appropriate Index for a Collection?
>>>
>>> -Colin
>>>
 On Sep 28, 2016, at 1:55 PM, Erica Sadun via swift-evolution >>> evolut...@swift.org> wrote:

 Gist here:
 https://gist.github.com/erica/2b2d92e6db787d001c689d3e37a7c3f2

 Introducing indexed() collections


  * Proposal: TBD
  * Author: Erica Sadun[1], Nate Cook[2], Jacob Bandes-Storch[3],
Kevin Ballard[4]
  * Status: TBD
  * Review manager: TBD
 Introduction
 This proposal introduces indexed() to the standard library, a
 method on collections that returns an (index, element) tuple
 sequence.
 Swift-evolution thread: TBD[5]
 Motivation
 The standard library's enumerated() method returns a sequence of
 pairs enumerating a sequence. The pair's first member is a
 monotonically incrementing integer starting at zero, and the second
 member is the corresponding element of the sequence. When working
 with arrays, the integer is coincidentally the same type and value
 as an Array index but the enumerated value is not generated with
 index-specific semantics. This may lead to confusion when
 developers attempt to subscript a non-array collection with
 enumerated integers. It can introduce serious bugs when developers
 use enumerated()-based integer subscripting with non-zero-based
 array slices.
 Indices have a specific, fixed meaning in Swift, which are used to
 create valid collection subscripts. This proposal introduces
 indexed() to produce a more semantically relevant sequence by
 pairing a collection's indices with its members. While it is
 trivial to create a solution in Swift, the most common developer
 approach shown here calculates indexes twice:


 extension Collection { /// Returns a sequence of pairs (*idx*,
 *x*), where *idx* represents a /// consecutive collection index,
 and *x* represents an element of /// the sequence. func indexed()
 -> Zip2Sequence { return zip(indices, self) } }

 Incrementing an index in some collections can be unnecessarily
 costly. In a lazy filtered collection, an index increment is
 potentially O(N). We feel this is better addressed introducing a
 new function into the Standard Library to provide a more efficient
 design that avoids the attractive nuisance of the "obvious"
 solution.
 Detailed Design
 Our vision of indexed() bypasses duplicated index generation with
 their potentially high computation costs. We'd create an iterator
 that calculates each index once and then applies that index to
 subscript the collection. Implementation would take place through
 IndexedSequence, similar to EnumeratedSequence.
 Impact on Existing Code
 This proposal is purely additive and has no impact on existing
 code.
 Alternatives Considered
 Not yet
 ___
 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
>>


Links:

  1. https://github.com/erica
  2. https://github.com/natecook1000
  3. https://github.com/jtbandes
  4. https://github.com/kballard
  5. https://gist.github.com/erica/tbd
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal draft] Introducing `indexed()` collections

2016-09-28 Thread Kevin Ballard via swift-evolution
There's more uses for enumerated() than just producing Array indices.

-Kevin

On Wed, Sep 28, 2016, at 05:49 PM, Colin Barrett via swift-evolution wrote:
> Definitely well motivated. It seems like having both .enumerated() and
> .indexed() methods would still leave open the possibility of novices
> using .enumerated and making the same mistake as before. I realize
> that because of where .enumerated() sits it has to work the way it
> does, but is there perhaps a better design (with constrained
> extensions?) for a single method that can give an Int for a Sequence
> and an appropriate Index for a Collection?
>
> -Colin
>
>> On Sep 28, 2016, at 1:55 PM, Erica Sadun via swift-evolution > evolut...@swift.org> wrote:
>>
>> Gist here:
>> https://gist.github.com/erica/2b2d92e6db787d001c689d3e37a7c3f2
>>
>> Introducing indexed() collections


>>  * Proposal: TBD
>>  * Author: Erica Sadun[1], Nate Cook[2], Jacob Bandes-Storch[3],
>>Kevin Ballard[4]
>>  * Status: TBD
>>  * Review manager: TBD
>> Introduction
>> This proposal introduces indexed() to the standard library, a method
>> on collections that returns an (index, element) tuple sequence.
>> Swift-evolution thread: TBD[5]
>> Motivation
>> The standard library's enumerated() method returns a sequence of
>> pairs enumerating a sequence. The pair's first member is a
>> monotonically incrementing integer starting at zero, and the second
>> member is the corresponding element of the sequence. When working
>> with arrays, the integer is coincidentally the same type and value as
>> an Array index but the enumerated value is not generated with index-
>> specific semantics. This may lead to confusion when developers
>> attempt to subscript a non-array collection with enumerated integers.
>> It can introduce serious bugs when developers use enumerated()-based
>> integer subscripting with non-zero-based array slices.
>> Indices have a specific, fixed meaning in Swift, which are used to
>> create valid collection subscripts. This proposal introduces
>> indexed() to produce a more semantically relevant sequence by pairing
>> a collection's indices with its members. While it is trivial to
>> create a solution in Swift, the most common developer approach shown
>> here calculates indexes twice:


>> extension Collection { /// Returns a sequence of pairs (*idx*, *x*),
>> where *idx* represents a /// consecutive collection index, and *x*
>> represents an element of /// the sequence. func indexed() ->
>> Zip2Sequence { return zip(indices, self) } }
>>
>> Incrementing an index in some collections can be unnecessarily
>> costly. In a lazy filtered collection, an index increment is
>> potentially O(N). We feel this is better addressed introducing a new
>> function into the Standard Library to provide a more efficient design
>> that avoids the attractive nuisance of the "obvious" solution.
>> Detailed Design
>> Our vision of indexed() bypasses duplicated index generation with
>> their potentially high computation costs. We'd create an iterator
>> that calculates each index once and then applies that index to
>> subscript the collection. Implementation would take place through
>> IndexedSequence, similar to EnumeratedSequence.
>> Impact on Existing Code
>> This proposal is purely additive and has no impact on existing code.
>> Alternatives Considered
>> Not yet
>> ___
>> 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


Links:

  1. https://github.com/erica
  2. https://github.com/natecook1000
  3. https://github.com/jtbandes
  4. https://github.com/kballard
  5. https://gist.github.com/erica/tbd
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal draft] Introducing `indexed()` collections

2016-09-28 Thread Kevin Ballard via swift-evolution
On Wed, Sep 28, 2016, at 02:27 PM, plx via swift-evolution wrote:
> +1 to have something *like* this, but a few questions.
>
> Is there a specific reason `IndexedSequence` isn’t
> `IndexedCollection`, conforming to `Collection` (and once conditional
> conformances are available picking up `BidirectionalCollection` and
> `RandomAccessCollection` when possible?).

This is already being discussed in this thread, but the simple answer is
that adds complexity and it's not obvious that it's worth the additional
complexity.

> Secondly, can you provide more detail on the proposed implementation?
>
> Are you just walking the index forward and subscripting the base in
> the iterator, or something fancier?

Yeah, that's what it would be. Something like

sequence(state: base.indices, next: {
guard let idx = $0.next() else { return nil }
return (idx, base[idx])
})

except done as a concrete type.

-Kevin

>> On Sep 28, 2016, at 12:55 PM, Erica Sadun via swift-evolution > evolut...@swift.org> wrote:
>>
>> Gist here:
>> https://gist.github.com/erica/2b2d92e6db787d001c689d3e37a7c3f2
>>
>> Introducing indexed() collections


>>  * Proposal: TBD
>>  * Author: Erica Sadun[1], Nate Cook[2], Jacob Bandes-Storch[3],
>>Kevin Ballard[4]
>>  * Status: TBD
>>  * Review manager: TBD
>> Introduction
>> This proposal introduces indexed() to the standard library, a method
>> on collections that returns an (index, element) tuple sequence.
>> Swift-evolution thread: TBD[5]
>> Motivation
>> The standard library's enumerated() method returns a sequence of
>> pairs enumerating a sequence. The pair's first member is a
>> monotonically incrementing integer starting at zero, and the second
>> member is the corresponding element of the sequence. When working
>> with arrays, the integer is coincidentally the same type and value as
>> an Array index but the enumerated value is not generated with index-
>> specific semantics. This may lead to confusion when developers
>> attempt to subscript a non-array collection with enumerated integers.
>> It can introduce serious bugs when developers use enumerated()-based
>> integer subscripting with non-zero-based array slices.
>> Indices have a specific, fixed meaning in Swift, which are used to
>> create valid collection subscripts. This proposal introduces
>> indexed() to produce a more semantically relevant sequence by pairing
>> a collection's indices with its members. While it is trivial to
>> create a solution in Swift, the most common developer approach shown
>> here calculates indexes twice:


>> extension Collection { /// Returns a sequence of pairs (*idx*, *x*),
>> where *idx* represents a /// consecutive collection index, and *x*
>> represents an element of /// the sequence. func indexed() ->
>> Zip2Sequence { return zip(indices, self) } }
>>
>> Incrementing an index in some collections can be unnecessarily
>> costly. In a lazy filtered collection, an index increment is
>> potentially O(N). We feel this is better addressed introducing a new
>> function into the Standard Library to provide a more efficient design
>> that avoids the attractive nuisance of the "obvious" solution.
>> Detailed Design
>> Our vision of indexed() bypasses duplicated index generation with
>> their potentially high computation costs. We'd create an iterator
>> that calculates each index once and then applies that index to
>> subscript the collection. Implementation would take place through
>> IndexedSequence, similar to EnumeratedSequence.
>> Impact on Existing Code
>> This proposal is purely additive and has no impact on existing code.
>> Alternatives Considered
>> Not yet
>> ___
>> 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


Links:

  1. https://github.com/erica
  2. https://github.com/natecook1000
  3. https://github.com/jtbandes
  4. https://github.com/kballard
  5. https://gist.github.com/erica/tbd
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Proposal draft] Introducing `indexed()` collections

2016-09-28 Thread Kevin Ballard via swift-evolution
On Wed, Sep 28, 2016, at 02:10 PM, Tim Vermeulen wrote:
>
>> On 28 Sep 2016, at 23:03, Kevin Ballard  wrote:
>>
>> On Wed, Sep 28, 2016, at 02:02 PM, Tim Vermeulen wrote:
>>>
 On 28 Sep 2016, at 22:57, Kevin Ballard  wrote:

 On Wed, Sep 28, 2016, at 01:54 PM, Tim Vermeulen wrote:
>
>> On 28 Sep 2016, at 22:46, Kevin Ballard  wrote:
>>
>> That's a bunch of complexity for no benefit. Why would you ever
>> use this as a collection?
>
> I think there is a benefit. Something like
> `collection.indexed().reversed()` would benefit from that, and I
> think that could be useful.

 Perhaps, though you could just say
 `collection.reversed().indexed()` instead.
>>>
>>> This isn’t necessarily the same though, is it? The reversed
>>> collection might use different indices than the original collection.
>>
>> Either way you write it you're dealing with reversed indices.
>
> `collection.indexed().reversed()` will contain indices from the
> original collection (but in reversed order).
> `collection.reversed().indexed()` will contain indices from the
> collection returned by `reversed()`, which may have a different type
> than `Base.Index`. It’s a distinction.
>
> This would compile:
>
> let characters = "Swift".characters
>
> for (index, character) in characters.indexed().reversed() {
> print(characters[index], character)
> }
>
> This wouldn’t:
>
> let characters = "Swift".characters
>
> for (index, character) in characters.reversed().indexed() {
> print(characters[index], character)
> }

Oh you're right.

Still, it's a fair amount of complexity (handling bidirectional and random-
access collections on top of the regular collection) and I'm not sure
it's worth the complexity just for reversed(). After all, you can always
fall back to the slightly uglier

for index in characters.indices.reversed() {
let character = characters[index]
...
}

And it's worth pointing out that enumerated() doesn't return a
collection but nobody's been clamoring for reversed() support there.

-Kevin

>>
>> -Kevin
>>
>> The whole point is to be used in a for loop. If it was a
>> collection then you'd need to have an index for that collection,
>> so now you have an index that lets you get the index for another
>> collection, which is pretty useless because you could just be
>> using that underlying index to begin with.
>
> Rather than introducing a new index for this, we can simply use
> the index of the base collection for subscripting.

 That's actually a good idea, and if we do make it a collection this
 is probably how we should handle it. But I still argue that the
 ability to make something a collection doesn't mean it should be a
 collection, if there's no good reason for anyone to actually try to
 use it as such.

 -Kevin

>> On Wed, Sep 28, 2016, at 01:38 PM, Tim Vermeulen via swift-
>> evolution wrote:
>>> +1 for `indexed()`, but I’m not sure about `IndexedSequence`.
>>> Why not `IndexedCollection`, which could also conform to
>>> Collection? With conditional conformances to
>>> BidirectionalCollection and RandomAccessCollection. This
>>> wouldn’t penalise the performance with respect to a simple
>>> `IndexedSequence`, would it?
>>>
 Gist here:
 https://gist.github.com/erica/2b2d92e6db787d001c689d3e37a7c3f2

 Introducingindexed()collections
 Proposal: TBD
 Author:Erica Sadun(https://github.com/erica),Nate Cook
 (https://github.com/natecook1000),Jacob Bandes-Storch
 (https://github.com/jtbandes),Kevin Ballard
 (https://github.com/kballard)
 Status: TBD
 Review manager: TBD

 Introduction

 This proposal introducesindexed()to the standard library, a
 method on collections that returns an (index, element) tuple
 sequence.


 Swift-evolution thread:TBD(https://gist.github.com/erica/tbd)

 Motivation

 The standard library'senumerated()method returns a sequence of
 pairs enumerating a sequence. The pair's first member is a
 monotonically incrementing integer starting at zero, and the
 second member is the corresponding element of the sequence.
 When working with arrays, the integer is coincidentally the
 same type and value as anArrayindex but the enumerated value is
 not generated with index-specific semantics. This may lead to
 confusion when developers attempt to subscript a non-array
 collection with enumerated integers. It can introduce serious
 bugs when developers useenumerated()-based integer subscripting
 with non-zero-based array slices.


 Indices have a specific, fixed meaning in Swift, which are used
 to create 

Re: [swift-evolution] [Proposal draft] Introducing `indexed()` collections

2016-09-28 Thread Kevin Ballard via swift-evolution
On Wed, Sep 28, 2016, at 02:02 PM, Tim Vermeulen wrote:
> 
> > On 28 Sep 2016, at 22:57, Kevin Ballard  wrote:
> > 
> > On Wed, Sep 28, 2016, at 01:54 PM, Tim Vermeulen wrote:
> >> 
> >>> On 28 Sep 2016, at 22:46, Kevin Ballard  wrote:
> >>> 
> >>> That's a bunch of complexity for no benefit. Why would you ever use this 
> >>> as a collection?
> >> 
> >> I think there is a benefit. Something like 
> >> `collection.indexed().reversed()` would benefit from that, and I think 
> >> that could be useful.
> > 
> > Perhaps, though you could just say `collection.reversed().indexed()` 
> > instead.
> 
> This isn’t necessarily the same though, is it? The reversed collection might 
> use different indices than the original collection.

Either way you write it you're dealing with reversed indices.

-Kevin

> >>> The whole point is to be used in a for loop. If it was a collection then 
> >>> you'd need to have an index for that collection, so now you have an index 
> >>> that lets you get the index for another collection, which is pretty 
> >>> useless because you could just be using that underlying index to begin 
> >>> with.
> >> 
> >> Rather than introducing a new index for this, we can simply use the index 
> >> of the base collection for subscripting.
> > 
> > That's actually a good idea, and if we do make it a collection this is 
> > probably how we should handle it. But I still argue that the ability to 
> > make something a collection doesn't mean it should be a collection, if 
> > there's no good reason for anyone to actually try to use it as such.
> > 
> > -Kevin
> > 
> >>> On Wed, Sep 28, 2016, at 01:38 PM, Tim Vermeulen via swift-evolution 
> >>> wrote:
>  +1 for `indexed()`, but I’m not sure about `IndexedSequence`. Why not 
>  `IndexedCollection`, which could also conform to Collection? With 
>  conditional conformances to BidirectionalCollection and 
>  RandomAccessCollection. This wouldn’t penalise the performance with 
>  respect to a simple `IndexedSequence`, would it?
>  
> > Gist here:https://gist.github.com/erica/2b2d92e6db787d001c689d3e37a7c3f2
> > 
> > Introducingindexed()collections
> > Proposal: TBD
> > Author:Erica Sadun(https://github.com/erica),Nate 
> > Cook(https://github.com/natecook1000),Jacob 
> > Bandes-Storch(https://github.com/jtbandes),Kevin 
> > Ballard(https://github.com/kballard)
> > Status: TBD
> > Review manager: TBD
> > 
> > Introduction
> > 
> > This proposal introducesindexed()to the standard library, a method on 
> > collections that returns an (index, element) tuple sequence.
> > 
> > 
> > Swift-evolution thread:TBD(https://gist.github.com/erica/tbd)
> > 
> > Motivation
> > 
> > The standard library'senumerated()method returns a sequence of pairs 
> > enumerating a sequence. The pair's first member is a monotonically 
> > incrementing integer starting at zero, and the second member is the 
> > corresponding element of the sequence. When working with arrays, the 
> > integer is coincidentally the same type and value as anArrayindex but 
> > the enumerated value is not generated with index-specific semantics. 
> > This may lead to confusion when developers attempt to subscript a 
> > non-array collection with enumerated integers. It can introduce serious 
> > bugs when developers useenumerated()-based integer subscripting with 
> > non-zero-based array slices.
> > 
> > 
> > Indices have a specific, fixed meaning in Swift, which are used to 
> > create valid collection subscripts. This proposal introducesindexed()to 
> > produce a more semantically relevant sequence by pairing a 
> > collection'sindiceswith its members. While it is trivial to create a 
> > solution in Swift, the most common developer approach shown here 
> > calculates indexes twice:
> > 
> > extension Collection {   /// Returns a sequence of pairs (*idx*, *x*), 
> > where *idx* represents a   /// consecutive collection index, and *x* 
> > represents an element of   /// the sequence.   func indexed() 
> > ->Zip2Sequence{ return zip(indices, self)   } }
> > 
> > Incrementing an index in some collections can be unnecessarily costly. 
> > In a lazy filtered collection, an index increment is potentially O(N). 
> > We feel this is better addressed introducing a new function into the 
> > Standard Library to provide a more efficient design that avoids the 
> > attractive nuisance of the "obvious" solution.
> > 
> > Detailed Design
> > 
> > Our vision ofindexed()bypasses duplicated index generation with their 
> > potentially high computation costs. We'd create an iterator that 
> > calculates each index once and then applies that index to subscript the 
> > collection. Implementation would take place 

Re: [swift-evolution] [Proposal draft] Introducing `indexed()` collections

2016-09-28 Thread Kevin Ballard via swift-evolution
On Wed, Sep 28, 2016, at 01:54 PM, Tim Vermeulen wrote:
> 
> > On 28 Sep 2016, at 22:46, Kevin Ballard  wrote:
> > 
> > That's a bunch of complexity for no benefit. Why would you ever use this as 
> > a collection?
> 
> I think there is a benefit. Something like `collection.indexed().reversed()` 
> would benefit from that, and I think that could be useful.

Perhaps, though you could just say `collection.reversed().indexed()` instead.

> > The whole point is to be used in a for loop. If it was a collection then 
> > you'd need to have an index for that collection, so now you have an index 
> > that lets you get the index for another collection, which is pretty useless 
> > because you could just be using that underlying index to begin with.
> 
> Rather than introducing a new index for this, we can simply use the index of 
> the base collection for subscripting.

That's actually a good idea, and if we do make it a collection this is probably 
how we should handle it. But I still argue that the ability to make something a 
collection doesn't mean it should be a collection, if there's no good reason 
for anyone to actually try to use it as such.

 -Kevin

> > On Wed, Sep 28, 2016, at 01:38 PM, Tim Vermeulen via swift-evolution wrote:
> >> +1 for `indexed()`, but I’m not sure about `IndexedSequence`. Why not 
> >> `IndexedCollection`, which could also conform to Collection? With 
> >> conditional conformances to BidirectionalCollection and 
> >> RandomAccessCollection. This wouldn’t penalise the performance with 
> >> respect to a simple `IndexedSequence`, would it?
> >> 
> >>> Gist here:https://gist.github.com/erica/2b2d92e6db787d001c689d3e37a7c3f2
> >>> 
> >>> Introducingindexed()collections
> >>> Proposal: TBD
> >>> Author:Erica Sadun(https://github.com/erica),Nate 
> >>> Cook(https://github.com/natecook1000),Jacob 
> >>> Bandes-Storch(https://github.com/jtbandes),Kevin 
> >>> Ballard(https://github.com/kballard)
> >>> Status: TBD
> >>> Review manager: TBD
> >>> 
> >>> Introduction
> >>> 
> >>> This proposal introducesindexed()to the standard library, a method on 
> >>> collections that returns an (index, element) tuple sequence.
> >>> 
> >>> 
> >>> Swift-evolution thread:TBD(https://gist.github.com/erica/tbd)
> >>> 
> >>> Motivation
> >>> 
> >>> The standard library'senumerated()method returns a sequence of pairs 
> >>> enumerating a sequence. The pair's first member is a monotonically 
> >>> incrementing integer starting at zero, and the second member is the 
> >>> corresponding element of the sequence. When working with arrays, the 
> >>> integer is coincidentally the same type and value as anArrayindex but the 
> >>> enumerated value is not generated with index-specific semantics. This may 
> >>> lead to confusion when developers attempt to subscript a non-array 
> >>> collection with enumerated integers. It can introduce serious bugs when 
> >>> developers useenumerated()-based integer subscripting with non-zero-based 
> >>> array slices.
> >>> 
> >>> 
> >>> Indices have a specific, fixed meaning in Swift, which are used to create 
> >>> valid collection subscripts. This proposal introducesindexed()to produce 
> >>> a more semantically relevant sequence by pairing a 
> >>> collection'sindiceswith its members. While it is trivial to create a 
> >>> solution in Swift, the most common developer approach shown here 
> >>> calculates indexes twice:
> >>> 
> >>> extension Collection {   /// Returns a sequence of pairs (*idx*, *x*), 
> >>> where *idx* represents a   /// consecutive collection index, and *x* 
> >>> represents an element of   /// the sequence.   func indexed() 
> >>> ->Zip2Sequence{ return zip(indices, self)   } }
> >>> 
> >>> Incrementing an index in some collections can be unnecessarily costly. In 
> >>> a lazy filtered collection, an index increment is potentially O(N). We 
> >>> feel this is better addressed introducing a new function into the 
> >>> Standard Library to provide a more efficient design that avoids the 
> >>> attractive nuisance of the "obvious" solution.
> >>> 
> >>> Detailed Design
> >>> 
> >>> Our vision ofindexed()bypasses duplicated index generation with their 
> >>> potentially high computation costs. We'd create an iterator that 
> >>> calculates each index once and then applies that index to subscript the 
> >>> collection. Implementation would take place throughIndexedSequence, 
> >>> similar toEnumeratedSequence.
> >>> 
> >>> Impact on Existing Code
> >>> 
> >>> This proposal is purely additive and has no impact on existing code.
> >>> 
> >>> Alternatives Considered
> >>> Not yet
> >>> 
> >>> 
> >>> 
> >>> 
> >> ___
> >> swift-evolution mailing list
> >> swift-evolution@swift.org
> >> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
___
swift-evolution mailing list
swift-evolution@swift.org

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0142: Permit where clauses to constrain associated types

2016-09-27 Thread Kevin Ballard via swift-evolution
On Fri, Sep 23, 2016, at 04:50 PM, Douglas Gregor wrote:
>  * What is your evaluation of the proposal?

+1. This looks like a great addition.

I'm not fond of the shorthand syntax in the Alternatives section though

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

Yes.

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

Yes.

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

Nothing comes to mind.

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

A quick reading.

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


Re: [swift-evolution] [Accepted] SE-0121: Remove Optional Comparison Operators

2016-08-29 Thread Kevin Ballard via swift-evolution
On Sun, Aug 28, 2016, at 01:28 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Fri Aug 26 2016, Kevin Ballard  wrote:
> 
> > Goddammit. I completely missed this thread, because Pipermail
> > regularly decides not to deliver the swift-evolution-announce version
> > of review threads (which means they bypass my inbox). Why does it do
> > this? Most of the emails get delivered, but it just skips some of
> > them, and I keep ending up missing review threads because of it.
> >
> > This change is going to have a HUGE impact for me. I use this sort of
> > comparison _all the time_ and find it incredibly useful, and have had
> > literally zero bugs caused by this. Surely I can't be the only one who
> > uses this. I am not looking forward to copying & pasting a
> > reimplementation of the comparison functions into every single project
> > I work on.
> 
> It's very easy to write your own versions of these operators, should you
> choose to keep using them.  From that standpoint, I don't see why the
> impact has to be huge.

You could make the same argument for a lot of stuff the stdlib provides. For 
example, let's remove Optional.map since it's trivial to reimplement.

The problem is, if I have to reimplement this thing in every single project I 
touch, that's a huge impact. I shouldn't have to copy & paste a bunch of code 
into every single project. I'm already doing this with my replace(_:with:) 
function that you guys (Swift core team; I forget exactly who) didn't like, but 
that's at least simpler than the Optional comparison operators, and is only one 
function (and it's easier to work around the lack of this function if I don't 
want to reimplement it for a particular use).

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


Re: [swift-evolution] [Accepted] SE-0121: Remove Optional Comparison Operators

2016-08-29 Thread Kevin Ballard via swift-evolution
On Mon, Aug 29, 2016, at 03:26 AM, Patrick Smith wrote:
> A little nicer I think is:
> 
> if request?.httpVersion.map({ $0 < HTTPVersion(1.0) }) ?? true {
> 
> It’s very explicit what the fallback is too, the original’s ambiguity makes 
> me uncomfortable.

I find that much less readable.

> BTW, did you want to be checking for <= 1.0? With HTTP 1.0, it’s opt in. 
> https://en.wikipedia.org/wiki/HTTP_persistent_connection

Yes I did. I have a different check for == 1.0 where I check the Connection 
header. The full expression looks like (from the Swift 2.2 version):

  if response.headers["Connection"]?.caseInsensitiveCompare("close") == 
.OrderedSame
  || (request?.httpVersion == HTTPVersion(1,0) && 
response.headers["Connection"]?.caseInsensitiveCompare("keep-alive") != 
.OrderedSame)
  || request?.httpVersion < HTTPVersion(1,0)
  {

-Kevin

> Patrick
> 
> > On 28 Aug 2016, at 1:20 PM, Kevin Ballard via swift-evolution 
> > <swift-evolution@swift.org> wrote:
> > 
> > As for optional comparisons making the code cleaner, I end up using them 
> > all over the place. The case that motivated my email looked something along 
> > the lines of
> > 
> >  if request?.httpVersion < HTTPVersion(1.0) {
> >// no keepalive
> >disconnect()
> >  }
> > 
> > This particular case could be trivially replaced with
> > 
> >  if request.map({ $0.httpVersion < HTTPVersion(1.0) }) ?? true {
> > 
> > but it’s uglier and harder to read.
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Accepted] SE-0121: Remove Optional Comparison Operators

2016-08-27 Thread Kevin Ballard via swift-evolution
On Sat, Aug 27, 2016, at 07:07 AM, Javier Soto via swift-evolution wrote:
> My biggest issue with Optional conforming to Comparable is that while
> a default implementation may sometimes be useful, it may not
> necessarily be the one you want.

Isn't that true for almost everything? I could use the same argument to
say String shouldn't implement <, because it's not always the comparison
you want. For example, with the lastName example, you probably want case-
insensitive comparisons instead of case-sensitive comparisons, so you
probably shouldn't be using < at all.

> In that last example with lastName, if you wanted to change the policy
> for whether users without last name appear first or last, you'd have
> to write more verbose code anyway. Generally, reading that code with
> just "<" I would never remember what Swift would do with nil (do they
> go first or last?)

Why would nil sort to the end? Empty values typically sort before
non-empty values, for example the empty string sorts before all
other strings.

-Kevin

> If you don't care that much, a simple one-liner without all those
> guards could also be:
>
> users.sorted { ($0.lastName ?? "") < ($1.lastName ?? "") }
> On Sat, Aug 27, 2016 at 6:58 AM Charlie Monroe via swift-evolution  evolut...@swift.org> wrote:
>> I have personally (ab)used this for the following:
>>
>> class User {
>> var email: String
>> var firstName: String?
>> var lastName: String?
>> }
>>
>> You have a list of users based on email, so last name is optional. In
>> Swift 2.x, you can do:
>>
>> users.sort({ $0.lastName < $1.lastName })
>>
>> Now, you need to do:
>>
>> users.sorted({
>>  guard let firstName = $0.0.lastName else {
>>  return true
>>  }
>>
>>  guard let secondName = $0.1.lastName else {
>>  return false
>>  }
>>
>>  return firstName < secondName
>> })
>>
>> Which aside from being a brain teaser how to properly maintain
>> ordering when $0.0's lastName != nil && $0.1's lastName == nil, adds
>> additional few lines.
>>
>> But I agree that it may come as confusing with Ints, etc. - with
>> strings it kind of makes sense since nil is like an empty string
>> which is placed in front of everything.
>>
>>> On Aug 27, 2016, at 1:46 PM, Haravikk via swift-evolution >> evolut...@swift.org> wrote:
>>>
>>>
>>>> On 27 Aug 2016, at 02:01, Kevin Ballard via swift-evolution >>> evolut...@swift.org> wrote:
>>>>
>>>> This change is going to have a HUGE impact for me. I use this sort
>>>> of comparison _all the time_ and find it incredibly useful, and
>>>> have had literally zero bugs caused by this. Surely I can't be the
>>>> only one who uses this. I am not looking forward to copying &
>>>> pasting a reimplementation of the comparison functions into every
>>>> single project I work on.
>>>
>>> Can you give some examples as to how this will have such a huge
>>> impact? Now that we have the ?? operator it seems that this is
>>> fairly easy to replace:
>>>
>>> value < 5 // where value is of type Int?
>>>
>>> With:
>>>
>>> (value ?? 0) < 5
>>>
>>>
>>> The latter is completely clear what the behaviour of nil is.
>>>
>>> Also, you can still re-add the operators where you need them,
>>> ideally with as limited a type as possible so you can make sure that
>>> it's behaviour is well defined.
>>> ___
>>> 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
> --
> Javier Soto
> _
> 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] [Accepted] SE-0121: Remove Optional Comparison Operators

2016-08-27 Thread Kevin Ballard via swift-evolution
I find it useful because Optionals show up all over the place, and it’s very 
convenient to be able to compare Optional values in a straightforward fashion. 
Especially when you have two Optional values to compare (as opposed to 
comparing an Optional with a non-Optional). `nil < .some(x)` evaluating to true 
makes sense because it’s the logical way to define that operator if you’re 
trying to make Optionals comparable (and if we had conditional protocol 
conformances then I’d say Optional should in fact be Comparable), as the 
absence of a value would quite reasonably be considered to be less than the 
presence of a value, assuming that there is an ordered relationship at all. And 
there’s already precedent for “empty” values sorting less than all other values 
(namely, the empty string sorts less than all other strings).

As for optional comparisons making the code cleaner, I end up using them all 
over the place. The case that motivated my email looked something along the 
lines of

  if request?.httpVersion < HTTPVersion(1.0) {
// no keepalive
disconnect()
  }

This particular case could be trivially replaced with

  if request.map({ $0.httpVersion < HTTPVersion(1.0) }) ?? true {

but it’s uglier and harder to read.

It’s easy to come up with contrived examples of comparing two optionals as 
well. A simplistic example is just sorting an array of optionals, or sorting an 
array of structs that contain an optional value.

-Kevin Ballard

> On Aug 26, 2016, at 7:36 PM, Tim Vermeulen  wrote:
> 
> What do you find so useful about them? And in what context does it make sense 
> to you that `nil < .some(x)` always evaluates to true? When I found that out, 
> I was very surprised by that behaviour (just like many others). Do you have 
> examples of then an optional comparison makes the code clearer?
> 
>> Goddammit. I completely missed this thread, because Pipermail regularly 
>> decides not to deliver the swift-evolution-announce version of review 
>> threads (which means they bypass my inbox). Why does it do this? Most of the 
>> emails get delivered, but it just skips some of them, and I keep ending up 
>> missing review threads because of it.
>> 
>> This change is going to have a HUGE impact for me. I use this sort of 
>> comparison _all the time_ and find it incredibly useful, and have had 
>> literally zero bugs caused by this. Surely I can't be the only one who uses 
>> this. I am not looking forward to copying a reimplementation of the 
>> comparison functions into every single project I work on.
>> 
>> I'm also really concerned about how fast such a hugely-impactful change was 
>> proposed, accepted, and implemented. The proposal PR was submitted on July 
>> 12, merged the same day, and a review kicked off again on the same day. And 
>> the first thread the proposal referenced only happened the previous day, on 
>> July 11. And the implementation landed only 12 days later on July 24th. This 
>> was extremely fast and didn't even have time to have the proposal listed on 
>> apple/swift-evolution for people to find before the review kicked off. It 
>> looks like this was done so the change could be made before the end of 
>> source-breaking changes, but the fast-tracking of something like this means 
>> that people like me completely missed it, and now we're stuck with a 
>> highly-impactful change that we don't want. Fast-tracking proposals is 
>> understandable when they're largely additive, or they fix something that is 
>> widely accepted as a problem. But being able to compare optionals is not 
>> universally recognized as a problem, and I know for a fact I've weighed in 
>> on this subject in the past on swift-evolution. I do not think it was 
>> appropriate to fast-track this proposal.
>> 
>> -Kevin Ballard
>> 
>> On Wed, Jul 20, 2016, at 05:38 PM, Chris Lattner via swift-evolution wrote:
>>> Proposal Link: 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0121-remove-optional-comparison-operators.md
>>> 
>>> The review of "SE-0121: Remove Optional Comparison Operators" ran from 
>>> Active review July 12...19. The proposal has been *accepted*.
>>> 
>>> Feedback has been universally positive from both the community and the core 
>>> team, because it eliminates a surprising part of the Swift model at very 
>>> little utility cost.
>>> 
>>> Thank you to Jacob Bandes-Storch for driving this discussion forward.
>>> 
>>> -Chris Lattner
>>> Review Manager
>>> 
>>> 
>>> ___
>>> 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] [Accepted] SE-0121: Remove Optional Comparison Operators

2016-08-26 Thread Kevin Ballard via swift-evolution
Goddammit. I completely missed this thread, because Pipermail regularly decides 
not to deliver the swift-evolution-announce version of review threads (which 
means they bypass my inbox). Why does it do this? Most of the emails get 
delivered, but it just skips some of them, and I keep ending up missing review 
threads because of it.

This change is going to have a HUGE impact for me. I use this sort of 
comparison _all the time_ and find it incredibly useful, and have had literally 
zero bugs caused by this. Surely I can't be the only one who uses this. I am 
not looking forward to copying & pasting a reimplementation of the comparison 
functions into every single project I work on.

I'm also really concerned about how fast such a hugely-impactful change was 
proposed, accepted, and implemented. The proposal PR was submitted on July 12, 
merged the same day, and a review kicked off again on the same day. And the 
first thread the proposal referenced only happened the previous day, on July 
11. And the implementation landed only 12 days later on July 24th. This was 
extremely fast and didn't even have time to have the proposal listed on 
apple/swift-evolution for people to find before the review kicked off. It looks 
like this was done so the change could be made before the end of 
source-breaking changes, but the fast-tracking of something like this means 
that people like me completely missed it, and now we're stuck with a 
highly-impactful change that we don't want. Fast-tracking proposals is 
understandable when they're largely additive, or they fix something that is 
widely accepted as a problem. But being able to compare optionals is not 
universally recognized as a problem, and I know for a fact I've weighed in on 
this subject in the past on swift-evolution. I do not think it was appropriate 
to fast-track this proposal.

-Kevin Ballard

On Wed, Jul 20, 2016, at 05:38 PM, Chris Lattner via swift-evolution wrote:
> Proposal Link: 
> https://github.com/apple/swift-evolution/blob/master/proposals/0121-remove-optional-comparison-operators.md
> 
> The review of "SE-0121: Remove Optional Comparison Operators" ran from Active 
> review July 12...19. The proposal has been *accepted*.
> 
> Feedback has been universally positive from both the community and the core 
> team, because it eliminates a surprising part of the Swift model at very 
> little utility cost.
> 
> Thank you to Jacob Bandes-Storch for driving this discussion forward.
> 
> -Chris Lattner
> Review Manager
> 
> 
> ___
> 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] Passing an optional first argument to sequence(first:next:)

2016-08-19 Thread Kevin Ballard via swift-evolution
AFAIK this issue has never been discussed with sequence(first:next:)
before. It certainly wasn't brought up during review.

As for my opinion, I'm really not sure. I was going to point out that
right now sequence(first:next:) guarantees that the first element of the
resulting sequence is the value provided as "first", but it occurs to me
that if you treat the nil result from next() as an element, then this
still holds true. So I guess my biggest worry is this change will make
it harder to use sequence(first:next:) to produce sequences of optional
values. So I guess I'm ambivalent, and would prefer to defer to the
wisdom of the Swift core team on this matter.

That said, didn't the deadline for source-breaking changes already
come and go?

-Kevin Ballard

On Fri, Aug 19, 2016, at 10:37 AM, Max Moiseev wrote:
> + Erica, Kevin, as the authors of the original proposal.
>
> Do you remember the problem of non-emptiness being discussed before?
> And if not, what’s your opinion on the proposed change?
>
> Thanks,
> Max
>
>> On Aug 19, 2016, at 7:53 AM, Tim Vermeulen  wrote:
>>
>> Hi Max, thanks for having a look.
>>
>> A big part of why I’m not really happy with the current
>> implementation is that the function always produces a nonempty
>> sequence, though the compiler doesn’t know it. `sequence(first:
>> first, next: next).last` returns an optional, even though it can’t
>> possibly be nil. The same goes for something like `sequence(first: 5,
>> next: { $0 * 3 }).first(where: { $0 > 1000 })`, because the sequence
>> is infinite, which means `first(while:)` will either keep running
>> forever, or return a non-optional.
>>
>> Ideally, we’d have three types of sequences, with three corresponding
>> `sequence(first:next:)` functions:
>>
>> func sequence(first: T?, next: (T) -> T?) — returns any sequence
>> func sequence(first: T,  next: (T) -> T?) — returns a nonempty
>> sequence
>> func sequence(first: T,  next: (T) -> T)  — returns an infinite
>> sequence
>>
>> Default implementations for methods on sequences would either return
>> optionals or non-optionals depending on their emptiness/finiteness.
>> We just have the first kind of sequence right now, so in that regard
>> it would make sense to also give `sequence(first:next)` the
>> corresponding signature.  Later, when the language / standard library
>> supports the other two kinds of sequences (if that ever happens), the
>> other versions could be added.
>>
>> Another reason that makes me think that the version that accepts an
>> optional `first` argument is more natural, is the fact that the
>> function body doesn’t need to be changed at all. It supports optional
>> seeds by design; only the signature prevents it.
>>
>> I know these arguments might not be very convincing, but I feel like
>> Swift misses an opportunity if it unnecessarily constrains the
>> `first` parameter to be non-optional. The `.lazy.flatMap({ $0 })`
>> alternative that you pointed out does work, but it makes everything
>> very unreadable: not just the `.lazy.flatMap({ $0 })` part, but also
>> the body of the `next` parameter because you’re now dealing with
>> optionals (i.e. you have to `flatMap` over the closure argument). The
>> best solution I’ve come up with is to copy the `sequence(first:next)`
>> implementation from the source code and change the signature. :-/
>>
>> `sequence(state:next:)` isn’t very appropriate for this task either,
>> because naive usage with an optional seed has the downside of being
>> unnecessarily eager just like a naive `sequence(first:next)`
>> implementation (as described in a comment in the source code).
>>
>>> On 19 Aug 2016, at 00:18, Max Moiseev  wrote:
>>>
>>> Hi Tim,
>>>
>>> Thanks for bringing this up.
>>> Here are my thoughts on the change you’re proposing.
>>>
>>> func sequence(first: T, next: (T) -> T?) ->
>>> UnfoldFirstSequence
>>>
>>> To me the type of the function as it is tells a clear story of
>>> what’s going to happen: take the `first`, make it a head of the
>>> resulting sequence, and then try to produce the tail by a series of
>>> applications of `next`. The only thing that controls when the
>>> sequence generation terminates is the result of `next`.
>>>
>>> If we change the type of `first` to an Optional, it would make
>>> the termination condition non-trivial. After all, the only thing it
>>> would do is try to unwrap the `first`, before doing what it needs
>>> to, but we already have a `map` for that. One should be able to
>>> simply do the `first.map { sequence(first: $0, next: next) } ?? []`
>>> but that won’t work with the types very well, unfortunately.
>>>
>>> As an alternative, `let first: Int? = ...; sequence(first: first,
>>> next: next).flatMap({$0})` (or even `.lazy.flatMap({$0})`) will do
>>> the right thing without making an API more complex.
>>>
>>> I see the point of `sequence(first:next:)` to be precisely the
>>> "generate the non-empty sequence using a seed and a simple
>>> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0137: Avoiding Lock-In to Legacy Protocol Designs

2016-08-12 Thread Kevin Ballard via swift-evolution
On Wed, Aug 10, 2016, at 02:03 PM, John McCall wrote:
>  * What is your evaluation of the proposal?

+1

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

Yes.

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

Yes.

>  * 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?

A quick reading.

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


Re: [swift-evolution] What're the Swift team's thoughts on Go's concurrency?

2016-08-11 Thread Kevin Ballard via swift-evolution
AIUI, fibers are basically coroutines. Even the Naughty Dog presentation
says that fibers are run on threads, and you have to make an explicit
call to switch between fibers. Looking at Ruby's Fiber type, that's also
an explicit coroutine, where you actually yield up a value when you
yield your fiber (which is exactly what coroutines do).

So basically, green threading is preemptive multithreading where the
preempting is done in user-space by the runtime (so it only happens at
specific points where your code calls back into the runtime, but it can
happen at any of those points), and multiple green threads get scheduled
onto the same OS thread, whereas fibers is cooperative multithreading
where your code explicitly yields back to the runtime to switch fibers.

Of course I could be wrong, but that's the impression I got after
reading a few different things about Fibers.

-Kevin

On Thu, Aug 11, 2016, at 10:54 AM, Goffredo Marocchi wrote:
> Hello Kevin,
> I may be wrong in my equating support for fibers to green threads (and
> the runtime cost of supporting them), but I do have seen and linked to
> a presentation of the use and more than trivial benefits to Naughty
> Dog's engine in utilising the 8 Jaguar x86 cores in the PlayStation 4
> CPU. Although like you said, it did not come for free or without
> evident pain points for them.
>
> On Thu, Aug 11, 2016 at 6:50 PM, Kevin Ballard <ke...@sb.org> wrote:
>> __
>> I'm confused by your email. Rust is all about performance, and
>> embedded devices are one of the targets for Rust. And I can't think
>> of any language that uses green threading that is appropriate for
>> constrained devices (e.g. Go definitely isn't appropriate for that).
>> One of the arguments for getting rid of green threading in Rust is
>> that the extra runtime complexity imposed a performance cost.
>>
>>
>> -Kevin
>>
>>
>> On Thu, Aug 11, 2016, at 10:36 AM, Goffredo Marocchi wrote:
>>> Thanks Kevin, I think they have accepted that they do not need to
>>> enter every segment of computing so the extra performance they could
>>> get on some devices is not worth the risk and the complexity it
>>> brings. Not everyone is trying to cram complex 3D experiences at 60-
>>> 90+ FPS on a console like constrained devices and I guess Rust is
>>> not targeting that right now :).
>>>
>>> On Thu, Aug 11, 2016 at 6:12 PM, Kevin Ballard via swift-evolution
>>> <swift-evolution@swift.org> wrote:
>>>> For anyone interested in reading more about Rust's decisions,
>>>> here's two links:
>>>>
>>>> The email about abandoning segmented stacks:
>>>> https://mail.mozilla.org/pipermail/rust-dev/2013-November/006314.html
>>>>
>>>> The RFC to remove green threading, with motivation:
>>>> https://github.com/aturon/rfcs/blob/remove-runtime/active/-remove-runtime.md
>>>>
>>>> -Kevin Ballard
>>>>
>>>>
>>>> On Tue, Aug 9, 2016, at 01:28 PM, Kevin Ballard wrote:
>>>> > The Rust language used to use a green thread model like Go
>>>> > (actually it exposed a configurable threading interface so you
>>>> > could choose green threads or OS threads). It also used segmented
>>>> > stacks like Go did. Over time, Rust ended up dropping the
>>>> > segmented stacks because it significantly complicated FFI without
>>>> > providing much, if any, benefit (and IIRC Go followed suite and
>>>> > dropped segmented stacks somewhere around version 1.5), and then
>>>> > a little while later Rust dropped green threads entirely. If you
>>>> > can find them, there are lots of discussions of the pros and cons
>>>> > that were documented during this process (on mailing lists, in
>>>> > IRC, possibly on Discourse, there's probably at least one post
>>>> > about it in the Rust subreddit, etc). But ultimately, it was
>>>> > determined that keeping this ability significantly complicated
>>>> > the Rust runtime and it provided almost no benefit. The OS is
>>>> > already really good at scheduling threads, and there's no memory
>>>> > savings without segmented stacks (though the OS will map virtual
>>>> > pages for the stack and only allocate the backing physical pages
>>>> > as the memory is touched, so even if you have a 2MB stack, a new
>>>> > thread will only actually allocate something like 8kb). And there
>>>> > are some pretty big downsides to green threads, such as the fact
>>>> > that i

Re: [swift-evolution] What're the Swift team's thoughts on Go's concurrency?

2016-08-11 Thread Kevin Ballard via swift-evolution
I'm confused by your email. Rust is all about performance, and embedded
devices are one of the targets for Rust. And I can't think of any
language that uses green threading that is appropriate for constrained
devices (e.g. Go definitely isn't appropriate for that). One of the
arguments for getting rid of green threading in Rust is that the extra
runtime complexity imposed a performance cost.

-Kevin

On Thu, Aug 11, 2016, at 10:36 AM, Goffredo Marocchi wrote:
> Thanks Kevin, I think they have accepted that they do not need to
> enter every segment of computing so the extra performance they could
> get on some devices is not worth the risk and the complexity it
> brings. Not everyone is trying to cram complex 3D experiences at 60-
> 90+ FPS on a console like constrained devices and I guess Rust is not
> targeting that right now :).
>
> On Thu, Aug 11, 2016 at 6:12 PM, Kevin Ballard via swift-evolution  evolut...@swift.org> wrote:
>> For anyone interested in reading more about Rust's decisions, here's
>> two links:
>>
>>  The email about abandoning segmented stacks:
>>  https://mail.mozilla.org/pipermail/rust-dev/2013-November/006314.html
>>
>>  The RFC to remove green threading, with motivation:
>>  
>> https://github.com/aturon/rfcs/blob/remove-runtime/active/-remove-runtime.md
>>
>>  -Kevin Ballard
>>
>>
>> On Tue, Aug 9, 2016, at 01:28 PM, Kevin Ballard wrote:
>>  > The Rust language used to use a green thread model like Go
>>  > (actually it exposed a configurable threading interface so you
>>  > could choose green threads or OS threads). It also used segmented
>>  > stacks like Go did. Over time, Rust ended up dropping the
>>  > segmented stacks because it significantly complicated FFI without
>>  > providing much, if any, benefit (and IIRC Go followed suite and
>>  > dropped segmented stacks somewhere around version 1.5), and then a
>>  > little while later Rust dropped green threads entirely. If you can
>>  > find them, there are lots of discussions of the pros and cons that
>>  > were documented during this process (on mailing lists, in IRC,
>>  > possibly on Discourse, there's probably at least one post about it
>>  > in the Rust subreddit, etc). But ultimately, it was determined
>>  > that keeping this ability significantly complicated the Rust
>>  > runtime and it provided almost no benefit. The OS is already
>>  > really good at scheduling threads, and there's no memory savings
>>  > without segmented stacks (though the OS will map virtual pages for
>>  > the stack and only allocate the backing physical pages as the
>>  > memory is touched, so even if you have a 2MB stack, a new thread
>>  > will only actually allocate something like 8kb). And there are
>>  > some pretty big downsides to green threads, such as the fact that
>>  > it significantly complicates the runtime since all I/O everywhere
>>  > has to be nonblocking and it has to be transparent to the code,
>>  > and FFI ends up as a major problem (even without segmented
>>  > stacks), because you have no idea if an FFI call will block. Green
>>  > threading libraries end up having to allocate extra OS threads
>>  > just to continue servicing the green threads when the existing
>>  > threads are potentially blocked in FFI.
>>  >
>>  > So ultimately, green threads really only make sense when you
>>  > control the entire ecosystem, so you can ensure the whole stack is
>>  > compatible with green threads and won't ever issue blocking calls,
>>  > and even there there's not much benefit and there's a lot of
>>  > complexity involved.
>>  >
>>  > -Kevin Ballard
>>  >
>>  > On Tue, Aug 9, 2016, at 12:04 PM, Dan Stenmark via swift-evolution
>>  > wrote:
>>  > > I'd like to inquire as to what the Swift team thoughts on Go's
>>  > > concurrency model are?  I'm not referring to convenience of the
>>  > > 'go' keyword and nor am I referring to how the language handles
>>  > > Channels, both of which being what most folks associate with it.
>>  > > Rather, I'd like to ask about the language's use of Green
>>  > > Threads and how the runtime handles the heavy lifting of
>>  > > multiplexing and scheduling them.  What are some of the
>>  > > strengths and weaknesses the Swift team sees to Go's approach?
>>  > >
>>  > > Dan
>>  > >
>>  > > (DISCLAIMER: I'm posting this for academic reasons, not as a
>>  > > pitch.  While the Swift team's responses may 

Re: [swift-evolution] What're the Swift team's thoughts on Go's concurrency?

2016-08-11 Thread Kevin Ballard via swift-evolution
For anyone interested in reading more about Rust's decisions, here's two links:

The email about abandoning segmented stacks: 
https://mail.mozilla.org/pipermail/rust-dev/2013-November/006314.html

The RFC to remove green threading, with motivation: 
https://github.com/aturon/rfcs/blob/remove-runtime/active/-remove-runtime.md

-Kevin Ballard

On Tue, Aug 9, 2016, at 01:28 PM, Kevin Ballard wrote:
> The Rust language used to use a green thread model like Go (actually it 
> exposed a configurable threading interface so you could choose green threads 
> or OS threads). It also used segmented stacks like Go did. Over time, Rust 
> ended up dropping the segmented stacks because it significantly complicated 
> FFI without providing much, if any, benefit (and IIRC Go followed suite and 
> dropped segmented stacks somewhere around version 1.5), and then a little 
> while later Rust dropped green threads entirely. If you can find them, there 
> are lots of discussions of the pros and cons that were documented during this 
> process (on mailing lists, in IRC, possibly on Discourse, there's probably at 
> least one post about it in the Rust subreddit, etc). But ultimately, it was 
> determined that keeping this ability significantly complicated the Rust 
> runtime and it provided almost no benefit. The OS is already really good at 
> scheduling threads, and there's no memory savings without segmented stacks 
> (though the OS will map virtual pages for the stack and only allocate the 
> backing physical pages as the memory is touched, so even if you have a 2MB 
> stack, a new thread will only actually allocate something like 8kb). And 
> there are some pretty big downsides to green threads, such as the fact that 
> it significantly complicates the runtime since all I/O everywhere has to be 
> nonblocking and it has to be transparent to the code, and FFI ends up as a 
> major problem (even without segmented stacks), because you have no idea if an 
> FFI call will block. Green threading libraries end up having to allocate 
> extra OS threads just to continue servicing the green threads when the 
> existing threads are potentially blocked in FFI.
> 
> So ultimately, green threads really only make sense when you control the 
> entire ecosystem, so you can ensure the whole stack is compatible with green 
> threads and won't ever issue blocking calls, and even there there's not much 
> benefit and there's a lot of complexity involved.
> 
> -Kevin Ballard
> 
> On Tue, Aug 9, 2016, at 12:04 PM, Dan Stenmark via swift-evolution wrote:
> > I'd like to inquire as to what the Swift team thoughts on Go's concurrency 
> > model are?  I'm not referring to convenience of the 'go' keyword and nor am 
> > I referring to how the language handles Channels, both of which being what 
> > most folks associate with it.  Rather, I'd like to ask about the language's 
> > use of Green Threads and how the runtime handles the heavy lifting of 
> > multiplexing and scheduling them.  What are some of the strengths and 
> > weaknesses the Swift team sees to Go's approach?
> > 
> > Dan
> > 
> > (DISCLAIMER: I'm posting this for academic reasons, not as a pitch.  While 
> > the Swift team's responses may inform opinions on the matter, I do not want 
> > this to turn into a 'this is how I think Swift should do concurrency' 
> > debate.  That discussion will come when it comes.)
> > ___
> > 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] What're the Swift team's thoughts on Go's concurrency?

2016-08-09 Thread Kevin Ballard via swift-evolution
The Rust language used to use a green thread model like Go (actually it exposed 
a configurable threading interface so you could choose green threads or OS 
threads). It also used segmented stacks like Go did. Over time, Rust ended up 
dropping the segmented stacks because it significantly complicated FFI without 
providing much, if any, benefit (and IIRC Go followed suite and dropped 
segmented stacks somewhere around version 1.5), and then a little while later 
Rust dropped green threads entirely. If you can find them, there are lots of 
discussions of the pros and cons that were documented during this process (on 
mailing lists, in IRC, possibly on Discourse, there's probably at least one 
post about it in the Rust subreddit, etc). But ultimately, it was determined 
that keeping this ability significantly complicated the Rust runtime and it 
provided almost no benefit. The OS is already really good at scheduling 
threads, and there's no memory savings without segmented stacks (though the OS 
will map virtual pages for the stack and only allocate the backing physical 
pages as the memory is touched, so even if you have a 2MB stack, a new thread 
will only actually allocate something like 8kb). And there are some pretty big 
downsides to green threads, such as the fact that it significantly complicates 
the runtime since all I/O everywhere has to be nonblocking and it has to be 
transparent to the code, and FFI ends up as a major problem (even without 
segmented stacks), because you have no idea if an FFI call will block. Green 
threading libraries end up having to allocate extra OS threads just to continue 
servicing the green threads when the existing threads are potentially blocked 
in FFI.

So ultimately, green threads really only make sense when you control the entire 
ecosystem, so you can ensure the whole stack is compatible with green threads 
and won't ever issue blocking calls, and even there there's not much benefit 
and there's a lot of complexity involved.

-Kevin Ballard

On Tue, Aug 9, 2016, at 12:04 PM, Dan Stenmark via swift-evolution wrote:
> I'd like to inquire as to what the Swift team thoughts on Go's concurrency 
> model are?  I'm not referring to convenience of the 'go' keyword and nor am I 
> referring to how the language handles Channels, both of which being what most 
> folks associate with it.  Rather, I'd like to ask about the language's use of 
> Green Threads and how the runtime handles the heavy lifting of multiplexing 
> and scheduling them.  What are some of the strengths and weaknesses the Swift 
> team sees to Go's approach?
> 
> Dan
> 
> (DISCLAIMER: I'm posting this for academic reasons, not as a pitch.  While 
> the Swift team's responses may inform opinions on the matter, I do not want 
> this to turn into a 'this is how I think Swift should do concurrency' debate. 
>  That discussion will come when it comes.)
> ___
> 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] [Review] SE-0136: Memory Layout of Values

2016-08-08 Thread Kevin Ballard via swift-evolution
On Sun, Aug 7, 2016, at 11:18 AM, Dave Abrahams via swift-evolution wrote:
>   * What is your evaluation of the proposal?

+1

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

Yes.

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

Yes.

>   * 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?

A quick reading of the proposal and review thread to date.

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


Re: [swift-evolution] Why does URL.checkResourceIsReachable() return a Bool?

2016-08-08 Thread Kevin Ballard via swift-evolution
The documentation is wrong (for Swift).

For file URLs, this method returns true/false without throwing an error
(at least, if the file doesn't exist there's no error; I don't know if
there are conditions that would cause an error to be returned).

For non-file URLs this method throws an error.

The bit about "For other URL types, false is returned" is written for
Obj-C, where you can completely disregard the error. You can't disregard
the error in Swift, so it doesn't apply (though you can use try? and
treat a nil value the same as false)

-Kevin

On Sun, Aug 7, 2016, at 10:41 AM, Charles Srstka via swift-evolution wrote:
> -[NSURL checkResourceIsReachableAndReturnError:] has taken on several
> forms in Swift during its development, sometimes returning a Boolean
> and an error by reference, sometimes returning Void and using Swift’s
> do/try/catch system. In Swift 3, though, it appears to do both, which
> is weird:
>
> func checkResourceIsReachable() throws -> Bool
>
> All the documentation has to say about this is:
>
> "This method is currently applicable only to URLs for file system
> resources. For other URL types, false is returned.”
>
> It does not, however, say whether non-file URLs are the only thing
> that can cause a return of ‘false’, so I don’t know whether I should
> be checking the return value when checking a file URL or not. This
> results in having to check both the return value *and* the catch block
> each time, which is fairly awkward. I’m also not clear on why checking
> reachability on a non-file URL can’t just return an error like it did
> in the past.
>
> What’s the rationale behind this?
>
> Charles
>
>
>
> _
> 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] Why does URL.checkResourceIsReachable() return a Bool?

2016-08-08 Thread Kevin Ballard via swift-evolution
Well that's curious. I tested in the REPL for URL(fileURLWithPath:
"/foo/bar") and it simply returned false, but running the script does
throw an error. And doubly-weird, if I go back to the REPL and prefix
the call with `try?` the value becomes nil instead of false. So that's
pretty confusing.

It definitely seems like this method should behave differently than it
does today. My suggestion would be to replace it with something like

func checkResourceIsReachable() -> (Bool, Error?)

This best approximates the Obj-C behavior where you can just use the
return value if you don't care about the reason why it's not reachable,
and you can inspect the error if you do care.

-Kevin Ballard

On Mon, Aug 8, 2016, at 03:13 PM, Charles Srstka wrote:
>> On Aug 8, 2016, at 4:32 PM, Kevin Ballard  wrote:
>>
>> The documentation is wrong (for Swift).
>>
>> For file URLs, this method returns true/false without throwing an
>> error (at least, if the file doesn't exist there's no error; I don't
>> know if there are conditions that would cause an error to be
>> returned).
>>
>> For non-file URLs this method throws an error.
>>
>> The bit about "For other URL types, false is returned" is written for
>> Obj-C, where you can completely disregard the error. You can't
>> disregard the error in Swift, so it doesn't apply (though you can use
>> try? and treat a nil value the same as false)
>
> In my testing, this does not appear to be correct; it actually seems
> to throw an error in both cases. For a file URL pointing to a file
> that doesn’t exist, it throws NSFileReadNoSuchFileError, and for an
> HTTP URL, it throws NSFileNoSuchFileError. This further causes me to
> question the purpose of having the method return a boolean.
>
> Here’s the code:
>
> import Foundation
>
> let fileURL = URL(fileURLWithPath: "/asdfasdfasdf")
> let httpURL = URL(string: "http://asdfasdfasdf.com/asdfasdfasdf;)!
>
> do {
>  if try fileURL.checkResourceIsReachable() {
>  print("file URL is reachable")
> } else {
>  print("file URL returned false")
> }
> } catch {
>  print("file URL threw error: \(error)")
> }
>
> do {
>  if try httpURL.checkResourceIsReachable() {
>  print("http URL is reachable")
> } else {
>  print("http URL returned false")
> }
> } catch {
>  print("http URL threw error: \(error)")
> }
>
>
> And the output:
>
> *file URL threw error: Error Domain=NSCocoaErrorDomain Code=260 "The
> file “asdfasdfasdf” couldn’t be opened because there is no such file."
> UserInfo={NSURL=file:///asdfasdfasdf, NSFilePath=/asdfasdfasdf,
> NSUnderlyingError=0x100903eb0 {Error Domain=NSPOSIXErrorDomain Code=2
> "No such file or directory"}}*
> *http URL threw error: Error Domain=NSCocoaErrorDomain Code=4 "The
> file doesn’t exist."*
> *Program ended with exit code: 0*
> **
> Charles
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Accepted] SE-0112: Improved NSError Bridging

2016-08-05 Thread Kevin Ballard via swift-evolution

> On Aug 5, 2016, at 7:36 PM, Erica Sadun <er...@ericasadun.com> wrote:
> 
> On Aug 5, 2016, at 8:10 PM, Kevin Ballard <ke...@sb.org 
> <mailto:ke...@sb.org>> wrote:
>> 
>>> 
>>> On Aug 5, 2016, at 5:16 PM, Erica Sadun <er...@ericasadun.com 
>>> <mailto:er...@ericasadun.com>> wrote:
>>> 
>>> 
>>>> On Aug 5, 2016, at 4:19 PM, Douglas Gregor via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>>> 
>>>>> On Aug 5, 2016, at 12:59 PM, Kevin Ballard via swift-evolution 
>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>>> 
>>>>> If all you want to do is get the localized description, then you can just 
>>>>> say `(error as NSError).localizedDescription`.
>>>> 
>>>> Just ‘error.localizedDescription’ works now. That was part of SE-0112.
>>>> 
>>>>- Doug
>>> 
>>> Would it kill to allow:
>>> 
>>> let err = NSError()
>>> err.localizedDescription = "bad things happen"
>>> throw err
>>> 
>>> or even
>>> 
>>> throw NSError("Bad things happen")
>>> 
>>> for lightweight use? I ended up refactoring entirely to enum : Error 
>>> because Swift yelled at me for using NSError(): "this results in an invalid 
>>> NSError instance. It will raise an exception in a future release. Please 
>>> call errorWithDomain:code:userInfo: or initWithDomain:code:userInfo:. This 
>>> message shown only once."
>>> 
>>> enum Errors: Error {case bad}
>>> Errors.bad._code // 0
>>> Errors.bad._domain // "Errors"
>>> Errors.bad._userInfo // Optional({})
>>> Errors.bad.localizedDescription // "The operation couldn’t be completed. 
>>> (Errors error 0.)"
>>> 
>>> Bleh.
>> 
>> NSErrors need a domain/code. It doesn’t make much sense to throw one without 
>> it. And besides, there’s a fairly trivial solution for doing what you want 
>> to do:
>> 
>> struct GenericError: LocalizedError {
>> let message: String
>> init(_ message: String) {
>> self.message = message
>> }
>> var errorDescription: String? {
>> return message
>> }
>> }
>> 
>> Now you can just say `throw GenericError(“Bad things happen”)`.
>> 
>> -Kevin Ballard
> 
> I know I can build workarounds but if we're going to have the 
> error.localizedDescription, making it an initializable/assignable property 
> just seems like a nice thing™. Why can't we have nice things™?

I don’t actually think it’s a nice thing™ to have it be assignable like you 
ask, because we should be encouraging people to use typed errors. You may as 
well just ask for String to conform to Error (in fact, you could just add that 
conformance yourself and skip the GenericError wrapper entirely).

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


Re: [swift-evolution] [Accepted] SE-0112: Improved NSError Bridging

2016-08-05 Thread Kevin Ballard via swift-evolution

> On Aug 5, 2016, at 5:16 PM, Erica Sadun <er...@ericasadun.com> wrote:
> 
> 
>> On Aug 5, 2016, at 4:19 PM, Douglas Gregor via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>>> 
>>> On Aug 5, 2016, at 12:59 PM, Kevin Ballard via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> If all you want to do is get the localized description, then you can just 
>>> say `(error as NSError).localizedDescription`.
>> 
>> Just ‘error.localizedDescription’ works now. That was part of SE-0112.
>> 
>>  - Doug
> 
> Would it kill to allow:
> 
> let err = NSError()
> err.localizedDescription = "bad things happen"
> throw err
> 
> or even
> 
> throw NSError("Bad things happen")
> 
> for lightweight use? I ended up refactoring entirely to enum : Error because 
> Swift yelled at me for using NSError(): "this results in an invalid NSError 
> instance. It will raise an exception in a future release. Please call 
> errorWithDomain:code:userInfo: or initWithDomain:code:userInfo:. This message 
> shown only once."
> 
> enum Errors: Error {case bad}
> Errors.bad._code // 0
> Errors.bad._domain // "Errors"
> Errors.bad._userInfo // Optional({})
> Errors.bad.localizedDescription // "The operation couldn’t be completed. 
> (Errors error 0.)"
> 
> Bleh.

NSErrors need a domain/code. It doesn’t make much sense to throw one without 
it. And besides, there’s a fairly trivial solution for doing what you want to 
do:

struct GenericError: LocalizedError {
let message: String
init(_ message: String) {
self.message = message
}
var errorDescription: String? {
return message
}
}

Now you can just say `throw GenericError(“Bad things happen”)`.

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


Re: [swift-evolution] [Accepted] SE-0112: Improved NSError Bridging

2016-08-05 Thread Kevin Ballard via swift-evolution
If all you want to do is get the localized description, then you can
just say `(error as NSError).localizedDescription`.

-Kevin

On Fri, Aug 5, 2016, at 02:59 AM, Jean-Daniel Dupas wrote:
>
>> Le 5 août 2016 à 05:12, Kevin Ballard via swift-evolution > evolut...@swift.org> a écrit :
>>
>> With NSError, you *must* check the domain before trying to interpret
>> the code, or else your code is buggy and will behave incorrectly when
>> receiving an unexpected error.
>
> You must check before interpreting the code, but you don’t have to
> interpret the code to do something useful with an NSError.
>
> I think what Jon is looking for is ‘LocalizedError’ and
> ‘CustomNSError’.
> Is there any guarantee that casting an NSError into a CustomNSError or
> LocalizedError will always succeed ?
>
>> With SE-0112, instead of checking the domain, you check if the Error
>> can be casted to the particular error type that represents the
>> domain. There is a one-to-one correspondence between domains and the
>> new error types. For example, NSCocoaErrorDomain is represented by
>> CocoaError, NSURLErrorDomain is URLError, etc.
>>
>> So previously you might have code that looks like
>>
>> func handleError(error: NSError) {
>> switch error.domain {
>> case NSCocoaErrorDomain where error.code ==
>> NSFileNoSuchFileError:
>> let path = error.userInfo[NSFilePathErrorKey] as? String
>> // handle error for path
>> case NSURLErrorDomain where error.code == NSURLErrorTimedOut:
>> let url = error.userInfo[NSURLErrorKey] as? NSURL
>> // handle error for url
>> default:
>> // generic handling of other errors
>> }
>> }
>>
>> And now you'd write that like
>>
>> func handleError(error: Error) {
>> switch error {
>> case let error as CocoaError where error.code ==
>> .fileNoSuchFileError:
>> let path = error.filePath
>> // handle error for path
>> case let error as URLError where error.code == .timedOut:
>> let url = error.failingURL
>> // handle error for url
>> default:
>> // generic handling of other errors
>> }
>> }
>>
>> It's the same basic structure, except now you get strong typing, you
>> can't possibly forget to check the domain (which is a surprisingly
>> common bug I see in a lot of code), and you get convenient accessors
>> for the values stored in the user info.
>>
>> And if you don't actually care about any of the user info properties,
>> then the new version is much simpler than the old:
>>
>> func handleError(error: Error) {
>> switch error {
>> case CocoaError.fileNoSuchFileError:
>> // handle error
>> case URLError.timedOut:
>> // handle error
>> default:
>> // generic handling of other errors
>> }
>> }
>>
>> It's similar to checking the code without the domain in the old
>> style, except now it checks the domain automatically, so you *still*
>> can't accidentally interpret an error's code in the wrong domain.
>>
>> -Kevin Ballard
>>
>> On Thu, Aug 4, 2016, at 11:00 AM, Jon Shier via swift-
>> evolution wrote:
>>> Doug:
>>> Thanks for indulging me so far, I think I’ve almost got it. Prior to
>>> this, using NSError, I could just look at the relevant properties of
>>> the error if I needed to see what type it was. Network errors had
>>> different codes from CloudKit errors, POSIX errors were underlying
>>> FileManager errors. A bit complex due to the undocumented nature of
>>> so many of these errors, but I could ignore any aspect of the error
>>> I didn’t care about. Now, however, it seems I must always care about
>>> what types of errors come out of various methods, as I’ll need to
>>> cast to the appropriate types to get useful information. For
>>> example, how would you handle the CloudKit errors I mentioned
>>> before? It seems to me like I would need to, at the point where I
>>> need to extract useful information, do a switch on various casts.
>>> First, try casting to CKError, then to CocoaError (?), and then
>>> likely produce a fatalError if there’s an unexpected type. Or is
>>> Error guaranteed to always cast to something useful? I’ve read the
>>> proposal a few times now and it looks like a lot of casting is going
>>> to be required, I’m mostly curious about the recommended patterns,
>>> especially for asynchronous calls that d

Re: [swift-evolution] [Accepted] SE-0112: Improved NSError Bridging

2016-08-04 Thread Kevin Ballard via swift-evolution
With NSError, you *must* check the domain before trying to interpret the
code, or else your code is buggy and will behave incorrectly when
receiving an unexpected error. With SE-0112, instead of checking the
domain, you check if the Error can be casted to the particular error
type that represents the domain. There is a one-to-one correspondence
between domains and the new error types. For example, NSCocoaErrorDomain
is represented by CocoaError, NSURLErrorDomain is URLError, etc.

So previously you might have code that looks like

func handleError(error: NSError) {
switch error.domain {
case NSCocoaErrorDomain where error.code == NSFileNoSuchFileError:
let path = error.userInfo[NSFilePathErrorKey] as? String
// handle error for path
case NSURLErrorDomain where error.code == NSURLErrorTimedOut:
let url = error.userInfo[NSURLErrorKey] as? NSURL
// handle error for url
default:
// generic handling of other errors
}
}

And now you'd write that like

func handleError(error: Error) {
switch error {
case let error as CocoaError where error.code ==
.fileNoSuchFileError:
let path = error.filePath
// handle error for path
case let error as URLError where error.code == .timedOut:
let url = error.failingURL
// handle error for url
default:
// generic handling of other errors
}
}

It's the same basic structure, except now you get strong typing, you
can't possibly forget to check the domain (which is a surprisingly
common bug I see in a lot of code), and you get convenient accessors for
the values stored in the user info.

And if you don't actually care about any of the user info properties,
then the new version is much simpler than the old:

func handleError(error: Error) {
switch error {
case CocoaError.fileNoSuchFileError:
// handle error
case URLError.timedOut:
// handle error
default:
// generic handling of other errors
}
}

It's similar to checking the code without the domain in the old style,
except now it checks the domain automatically, so you *still* can't
accidentally interpret an error's code in the wrong domain.

-Kevin Ballard

On Thu, Aug 4, 2016, at 11:00 AM, Jon Shier via swift-evolution wrote:
> Doug:
> Thanks for indulging me so far, I think I’ve almost got it. Prior to
> this, using NSError, I could just look at the relevant properties of
> the error if I needed to see what type it was. Network errors had
> different codes from CloudKit errors, POSIX errors were underlying
> FileManager errors. A bit complex due to the undocumented nature of so
> many of these errors, but I could ignore any aspect of the error I
> didn’t care about. Now, however, it seems I must always care about
> what types of errors come out of various methods, as I’ll need to cast
> to the appropriate types to get useful information. For example, how
> would you handle the CloudKit errors I mentioned before? It seems to
> me like I would need to, at the point where I need to extract useful
> information, do a switch on various casts. First, try casting to
> CKError, then to CocoaError (?), and then likely produce a fatalError
> if there’s an unexpected type. Or is Error guaranteed to always cast
> to something useful? I’ve read the proposal a few times now and it
> looks like a lot of casting is going to be required, I’m mostly
> curious about the recommended patterns, especially for asynchronous
> calls that don’t go through throw/catch.
>
>
>
> Jon
>
>
>> On Aug 2, 2016, at 5:36 PM, Douglas Gregor  wrote:
>>
>>
>>> On Aug 2, 2016, at 2:19 PM, Jon Shier  wrote:
>>>
>>> Thanks Doug. I missed the rename, as earlier points still referred
>>> to ErrorProtocol. In regards to the CloudKit errors, I appreciate
>>> the strongly typed CKError, but why not have the methods return that
>>> type directly?
>>
>> Generally speaking, Cocoa only uses NSError—not specific subclasses
>> or NSError or other error types—because errors can occur at many
>> different places in the stack and be propagated up. A CloudKit
>> operation could fail because of some problem detected in a different
>> error domain—say, the general Cocoa error domain or URLError
>> domain—and that non-CloudKit error would get passed through
>> immediately. So, if you were assuming that every error you get here
>> had to be in the CloudKit error domain, I believe your code was
>> already incorrect. It is *possible* that CloudKit translates/wraps
>> all other errors, but that would be odd for a Cocoa framework.
>>
>>> Every usage of these methods is going to require such a cast, so why
>>> require it in the first place? I don’t understand what advantage
>>> erasing the strongly type error that was just created has when the
>>> developer will just have to bring it right back. Or is this just a
>>> first implementation?
>>
>> There was never a strongly-typed error, and in most 

Re: [swift-evolution] [Swift4] Mailing list vs. Forum

2016-08-03 Thread Kevin Ballard via swift-evolution
On Wed, Aug 3, 2016, at 11:06 AM, Felipe Cypriano via swift-evolution wrote:
> On Wed, Aug 3, 2016, at 03:01, Brent Royal-Gordon via swift-
> evolution wrote:
 3. Native on every platform.
>>> Browsers too.
>>
>> Safari is native, but Discourse in Safari is not by any means
>> native. Any
>> attempt to define things otherwise would produce a vacuous
>> definition of
>> the term "native".
>
> The same can be said about an email client and what it renders.

No it can't. An email client renders text (possibly with HTML styling
applied, but most mailing list traffic is just text). The issue of it
being native or not pertains to everything *except for* the text. All of
the chrome, all of the controls for manipulating the client, navigating
between messages, writing replies, etc. All of that stuff is native in
an email client, and non-native in forums software like Discourse.

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


Re: [swift-evolution] [Accepted] SE-0112: Improved NSError Bridging

2016-08-02 Thread Kevin Ballard via swift-evolution
You're assuming that every error passed to that method is a CKError. The
documentation does not claim that to be true, so it's quite plausible
that you might get other errors that are simply passed through.

-Kevin

On Tue, Aug 2, 2016, at 02:19 PM, Jon Shier via swift-evolution wrote:
> Thanks Doug. I missed the rename, as earlier points still referred to
> ErrorProtocol. In regards to the CloudKit errors, I appreciate the
> strongly typed CKError, but why not have the methods return that type
> directly? Every usage of these methods is going to require such a
> cast, so why require it in the first place? I don’t understand what
> advantage erasing the strongly type error that was just created has
> when the developer will just have to bring it right back. Or is this
> just a first implementation?
>
>
> Jon
>
>> On Aug 2, 2016, at 4:20 PM, Douglas Gregor  wrote:
>>
>>>
>>> On Aug 2, 2016, at 10:30 AM, Jon Shier via swift-evolution >> evolut...@swift.org> wrote:
>>>
>>> I’m not sure where to put such feedback, but the ErrorProtocol to
>>> Error rename that accompanied the implementation of this proposal is
>>> very, very painful. It completely eliminates the very useful ability
>>> to embed an associated Error type inside other types, as those types
>>> now conflict with the protocol. Also, was this rename accompanied by
>>> an evolution proposal? It seems like the change was just made when
>>> this proposal was implemented.
>>
>> The rename was part of the proposal, in bullet #5 of the proposed
>> solution (which, amusing, pastes as bullet #1 below):
>>
>>  1. Rename ErrorProtocol to Error: once we've completed the bridging
>> story, Error becomes the primary way to work with error types in
>> Swift, and the value type to which NSError is bridged:


>> func handleError(_ error: Error, userInteractionPermitted: Bool)
>>
>>
>>> Also, the adoption of this proposal by the Cocoa(Touch) frameworks
>>> as seen in Xcode 8 beta 4 has made asynchronous error handling quite
>>> a bit more arduous. For example, the CKDatabase method
>>> fetch(withRecordID recordID: CKRecordID, completionHandler:
>>> (CKRecord?, Error?) -> Void) returns an `Error` now, meaning I have
>>> to cast to the specific `CKError` type to get useful information out
>>> of it. Is this just an unfortunate first effort that will be fixed,
>>> or is this the expected form of these sorts of APIs after this
>>> proposal?
>>
>> Prior to this proposal, you would have had to check the domain
>> against CKErrorDomain anyway to determine whether you’re looking at a
>> CloudKit error (vs. some other error that is passing through
>> CloudKit), so error bridging shouldn’t actually be adding any work
>> here—although it might be making explicit work that was already done
>> or should have been done. Once you have casted to CKError, you now
>> have typed accessors for information in the error:
>>
>> extension CKError {
>>   /// Retrieve partial error results associated by item ID.
>>   public var partialErrorsByItemID: [NSObject : Error]? {
>> return userInfo[CKPartialErrorsByItemIDKey] as? [NSObject :
>> Error]
>>   }
>>
>>   /// The original CKRecord object that you used as the basis for
>>   /// making your changes.
>>   public var ancestorRecord: CKRecord? {
>> return userInfo[CKRecordChangedErrorAncestorRecordKey] as?
>> CKRecord
>>   }
>>
>>   /// The CKRecord object that was found on the server. Use this
>>   /// record as the basis for merging your changes.
>>   public var serverRecord: CKRecord? {
>> return userInfo[CKRecordChangedErrorServerRecordKey] as? CKRecord
>>   }
>>
>>   /// The CKRecord object that you tried to save. This record is
>>   based
>>   /// on the record in the CKRecordChangedErrorAncestorRecordKey key
>>   /// but contains the additional changes you made.
>>   public var clientRecord: CKRecord? {
>> return userInfo[CKRecordChangedErrorClientRecordKey] as? CKRecord
>>   }
>>
>>   /// The number of seconds after which you may retry a request. This
>>   /// key may be included in an error of type
>>   /// `CKErrorServiceUnavailable` or `CKErrorRequestRateLimited`.
>>   public var retryAfterSeconds: Double? {
>> return userInfo[CKErrorRetryAfterKey] as? Double
>>   }
>> }
>> - Doug
>>
>>>
>>>
>>>
>>> Jon Shier
>>>
>>>
 On Jul 12, 2016, at 8:44 AM, Shawn Erickson via swift-evolution >>> evolut...@swift.org> wrote:

 Thanks for the effort on the proposal and discussion and thanks to
 those working in the implementation.

 -Shawn
 On Tue, Jul 12, 2016 at 12:25 AM Charles Srstka via swift-evolution
  wrote:
> Wow, thanks! I’m delighted that Apple found this improvement to be
> worth inclusion in Swift 3. This will truly make the language much
> nicer to use with the Cocoa frameworks.
>
> Thanks!
>
> Charles
>
> > On Jul 11, 2016, at 11:19 PM, Chris Lattner via swift-evolution
> > 

Re: [swift-evolution] [Accepted] SE-0112: Improved NSError Bridging

2016-08-02 Thread Kevin Ballard via swift-evolution
It did not eliminate that ability at all. You just need to say
`Swift.Error` instead of `Error` when referring to the protocol if a
nested `Error` type is in scope. For example:

class MyClass {
enum Error: Swift.Error {
case somethingWentWrong
}
}

-Kevin Ballard

On Tue, Aug 2, 2016, at 10:30 AM, Jon Shier via swift-evolution wrote:
> I’m not sure where to put such feedback, but the ErrorProtocol to
> Error rename that accompanied the implementation of this proposal is
> very, very painful. It completely eliminates the very useful ability
> to embed an associated Error type inside other types, as those types
> now conflict with the protocol. Also, was this rename accompanied by
> an evolution proposal? It seems like the change was just made when
> this proposal was implemented.
> Also, the adoption of this proposal by the Cocoa(Touch) frameworks as
> seen in Xcode 8 beta 4 has made asynchronous error handling quite a
> bit more arduous. For example, the CKDatabase method
> fetch(withRecordID recordID: CKRecordID, completionHandler:
> (CKRecord?, Error?) -> Void) returns an `Error` now, meaning I have to
> cast to the specific `CKError` type to get useful information out of
> it. Is this just an unfortunate first effort that will be fixed, or is
> this the expected form of these sorts of APIs after this proposal?
>
>
>
> Jon Shier
>
>
>> On Jul 12, 2016, at 8:44 AM, Shawn Erickson via swift-evolution > evolut...@swift.org> wrote:
>>
>> Thanks for the effort on the proposal and discussion and thanks to
>> those working in the implementation.
>>
>> -Shawn
>> On Tue, Jul 12, 2016 at 12:25 AM Charles Srstka via swift-evolution
>>  wrote:
>>> Wow, thanks! I’m delighted that Apple found this improvement to be
>>> worth inclusion in Swift 3. This will truly make the language much
>>> nicer to use with the Cocoa frameworks.
>>>
>>>  Thanks!
>>>
>>>  Charles
>>>
>>>  > On Jul 11, 2016, at 11:19 PM, Chris Lattner via swift-evolution
>>>  >  wrote:
>>>  >
>>>  > Proposal Link:
>>>  > 
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0112-nserror-bridging.md
>>>  >
>>>  > The review of "SE-0112: Improved NSError Bridging" ran from June
>>>  > 30 ... July 4, 2016. The proposal has been *accepted*:
>>>  >
>>>  > The community and core team agree that this proposal is a huge
>>>  > step forward that enriches the experience working with and
>>>  > extending the Cocoa NSError model in Swift.  The core team
>>>  > requests one minor renaming of
>>>  > "attemptRecovery(optionIndex:andThen:)" to
>>>  > "attemptRecovery(optionIndex:resultHandler:)”.  It also discussed
>>>  > renaming CustomNSError and RecoverableError, but decided to stay
>>>  > with those names.
>>>  >
>>>  > Thank you to Doug Gregor and Charles Srstka for driving this
>>>  > discussion forward, and for Doug Gregor taking the charge on the
>>>  > implementation effort to make this happen for Swift 3!
>>>  >
>>>  > -Chris Lattner
>>>  > Review Manager
>>>  >
>>>  > ___
>>>  > 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [META] Gmane and Swift Evolution

2016-07-31 Thread Kevin Ballard via swift-evolution
On Sun, Jul 31, 2016, at 03:42 PM, Chris Lattner via swift-evolution wrote:
>
>> On Jul 31, 2016, at 3:40 PM, Erica Sadun via swift-evolution > evolut...@swift.org> wrote:
>>
>> Gmane.org[1] is shutting down.
>> http://ostatic.com/blog/mint-18-xfce-imminent-gmane-org-shutting-down
>> writes:
>>
>>
>>> "*Long time mailing* list archive site Gmane.org[2] is shutting
>>> down. Gmane has been the home for technical mailing list references
>>> since 2002. But it's no longer fun for founder and only maintainer
>>> Lars Ingebrigtsen. He's been sued in India and threatened with legal
>>> action in at least France, among other annoyances. The straw that
>>> broke Ingebrigtsen's back was a sustained denial of service[3]
>>> attack throughout the month of July. He's been wondering a lot
>>> lately if it's all worth it. So, he's decided[4] to move the mail
>>> and news servers to new hosting. However, Ingebrigtsen is indeed
>>> discontinuing the web-based archive. He said he's just "fed up."
>>> He's willing to send a disk with the web server archives to anyone
>>> who wants to take it over. But with the Gmane.org[5] web presence
>>> gone, it feels like the end of an era. There is much wailing and
>>> gnashing of teeth throughout the community with some even trying to
>>> get a petition started."
>>
>> Because of this shutdown, numerous documents in the Swift Evolution
>> github archive no longer point to valid web links. I have pasted a
>> list of gmane links at the end of this message. As gmane's
>> "robots.txt" disallowed crawling, Google has not preserved the titles
>> or text of the links, which makes finding some of these a little
>> tricky.
>>
>> Here are the remaining links that are not yet converted. Please
>> consider adopting a proposal, tracking down its links, and mailing
>> this thread with the proposal number, gmane links and pipermail
>> equivalents. Pipermail is located at
>> https://lists.swift.org/pipermail/swift-evolution/. Some of these may
>> refer to  build dev discussions instead of evolution ones. If you
>> can, please track down to the exact message for rationale, and the
>> thread for discussion and review links.
>
> Completely agreed.  All of these should point to
> https://lists.swift.org (and always should have, exactly for reasons
> like this).  I’d appreciate any PRs to help clean up the evolution
> repo to point to https://lists.swift.org instead.

FWIW, Gmane.org has been around for something like 14 years, and it
provided a vastly better experience for actually reading the thread
than pipermail, so I don't think using Gmane links was a bad decision
at the time.

Also, if it helps, the guy who runs Gmane offered to send a thumbdrive
with all the archives to anyone who wants to take over in providing a
web interface, and there were a few people expressing interest in that,
so with luck the website will come back in some form at some point.

-Kevin

Links:

  1. http://gmane.org/
  2. http://gmane.org/
  3. https://lars.ingebrigtsen.no/2016/07/28/the-end-of-gmane/
  4. 
https://lars.ingebrigtsen.no/2016/07/28/the-end-of-gmane/comment-page-1/#comment-13502
  5. http://gmane.org/
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0117: Default classes to be non-subclassable publicly

2016-07-09 Thread Kevin Ballard via swift-evolution
On Tue, Jul 5, 2016, at 04:11 PM, Chris Lattner wrote:
>   * What is your evaluation of the proposal?

Mixed bag.

I'm a big fan of sealed-by-default for classes. But I want a keyword (e.g. 
`sealed`) for this so I can be explicit about it too. Just as I sometimes mark 
methods as `internal` to make it clear to the reader that I didn't simply 
forget the access modifier, I would want to mark certain classes as `sealed` to 
make it obvious that I made a deliberate choice.

On the flip side, I'm very against sealed-by-default for functions. My general 
feeling is that, if my class is subclassable, marking certain public methods as 
non-overridable is the exception rather than the norm. Anecdotally, in the 
Postmates app, most of our Swift classes are explicitly marked as `final` 
(which supports sealed-by-default for classes), but for the subclassable 
classes, I'm pretty sure that _none_ of our methods are marked `final`.

Also, I think the keyword `subclassable` is kind of cumbersome. I'm much more 
in favor of `open`, or possibly `public(open)` since this keyword only applies 
to public classes (or public methods, if I'm overriding a sealed method from my 
parent).

And finally, I think we need to make the Swift migrator automatically mark 
public non-final declarations as `open`, otherwise we have a *huge* backwards 
compatibility hazard for all third-party Swift frameworks.

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

Yes.

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

Yes. It's making things safer by default, and matches the default internal 
access level.

>   * 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?

A quick reading of the proposal, then reading part of this massive review 
thread and skimming the rest.

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0118: Closure Parameter Names and Labels

2016-07-09 Thread Kevin Ballard via swift-evolution
On Tue, Jul 5, 2016, at 04:10 PM, Chris Lattner wrote:
>   * What is your evaluation of the proposal?

Strong +1. Overall I like all of the changes listed in this proposal, with some 
commentary below.

> lines.split(whereSeparator: isAllWhitespace)

I think this is ok, but I'd also be fine with split(where:).

> if roots.contains(where: isPrime) {

I strongly prefer this to the alternatives suggested in this thread. Not only 
is Erica right about "anywhere" being visible in containsAny(where:) or 
contains(anyWhere:), but those names also just feel unnecessarily cumbersome. 
Not only that, but using contains(where:) would be more consistent with 
first(where:) (which is a strongly related function; contains(where:) returns 
true iff first(where:) returns non-nil).

> let sum = measurements.reduce(0, +)

I'm very happy to see the closure name being removed here. I never thought the 
name was pulling any weight, since this function is already a term of art 
rather than being an english sentence.

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

Yes.

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

Yes.

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

Other languages don't typically have external parameter names.

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

A quick reading of the proposal and of the thread to date.

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


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0105: Removing Where Clauses from For-In Loops

2016-06-23 Thread Kevin Ballard via swift-evolution
>   * What is your evaluation of the proposal?
 
-1. I don't think this is really a big deal, but I find where clauses on
for loops to be very elegant, and I'm not convinced by any of the
arguments for why they should go away.
 
I'm especially not convinced by the argument over the behavior itself
being confusing, e.g. the fact that it's equivalent to a continue rather
than a break. You know what else is equivalent to a continue that this
proposal isn't modifying? `for case pattern in`. If the refutable
pattern does not match, the element is skipped and the for loop
continues to the next. This is precisely how the `where` clause works
(and it's no surprise that the two were introduced at the same time). So
the argument that says we should remove `where` in favor of explicit guard-
continues also implies that we should remove `for case pattern in`,
which I would strongly disagree with.
 
>   * Is the problem being addressed significant enough to warrant a
> change to Swift?
 
I don't think so. As the proposal argues, this feature is not very widely-
used, at least within open-source code (though as others have pointed
out, there's no data on how much it's used in closed-source code, and
it's plausible that there is far more closed-source Swift code than open-
source). Since it's not widely-used in public, the arguments for
removing it aren't very significant. And the people who do use it tend
to like the feature. And I agree with the people who have pointed out
that it's not the Swift compiler's job to enforce a single coding style.
 
> * How much effort did you put into your review? A glance, a quick
>   reading, or an in-depth study?
 
Reading the proposal and this review thread.
 
On Thu, Jun 23, 2016, at 10:25 AM, Erica Sadun via swift-evolution wrote:
>
>> On Jun 23, 2016, at 7:42 AM, Ryan Lovelett via swift-evolution > evolut...@swift.org> wrote:
>>> Is the problem being addressed significant enough to warrant a
>>> change to Swift?
>>
>> No. In fact, I think that even the proposal itself says as much. The
>> proposal indicates it means to deprecate an available coding
>> style. It
>> seems to me, as much as is practicable, style changes should be
>> enforced
>> by something other than the Swift compiler.
>>
>
> I in no way intended the proposal to "say as much".
>
> As syntactic sugar, the filtering syntax is
>  * rarely used in published deployed code,
 
With no info on how often it's used in closed-source code. Just
looking at a single closed-source project (the Postmates app), we use
the where clause on for loops 7 times, which is more than your
proposal says the stdlib and a random sampling of open source projects
uses combined. And this is just one project, so who knows how much
it's used in other projects.
 
>  * hard to discover (although I like others have taught it to promote
>its visibility),
 
If there's an educational issue here, that should be addressed in the
documentation (i.e. the book), rather than by removing the feature.
 
>  * elevates one style (continue if false) above others (continue if
>false, break if true, break if false), which are not expressible
>using similar shorthand,
 
I completely disagree. Removing this feature is elevating one style (guard-
continue) over another. Keeping the feature is not making any judgement
call about style whatsoever. And as I said above, `for case pattern in`
already has the continue-if-unmatched behavior, so removing this feature
does not mean the for loop no longer has a way to assume continue.
 
>  * introduces a fluent style that discourages design comments at the
>point of use,
 
You can comment where clauses. Just put it on a new line.
 
>  * can be difficult to breakpoint during debugging.
 
This can be said about a lot of things. If I want to breakpoint my where
clause, I can convert it to a guard-continue. Although first I'd try
putting the clause on its own line and seeing if lldb is smart enough to
then break just on the where clause.
 
> I think these are significant issues.
>
> The recommended alternative (using a separate guard) addresses all
> these points: better commenting, better breakpointing and debugging,
> and fully covers the domain of filtering and early exiting. If
> chaining is desired, using filter and prefix(while:) address all
> conditions, allow better commenting, etc, and are more self-
> documenting.
 
You can already use a separate guard. The existence of the where clause
on a for loop does not in any way detract from the ability to use a
separate guard.
 
>> On Jun 23, 2016, at 9:07 AM, Tony Allevato via swift-evolution > evolut...@swift.org> wrote:
>> The fact that some users may be confused by this terminology is not a
>> reason to remove it from the language. Some users will be confused by
>> many concepts in programming languages. If that means this is
>> considered an "advanced" feature, so be it. We should be able to have
>> a language that has both basic features and 

Re: [swift-evolution] [Review #2] SE-0089: Renaming String.init(_: T)

2016-06-06 Thread Kevin Ballard via swift-evolution
On Sat, Jun 4, 2016, at 11:24 AM, Chris Lattner via swift-evolution wrote:
>   * What is your evaluation of the proposal?

+1 in general, but I still think String.init(describing:) is annoyingly long 
and would prefer String.init(from:).

Also, I'm a little concerned by this bit:

> As a performance optimization, the implementation of the string literal 
> interpolation syntax will be changed to prefer the unlabeled initializer when 
> interpolating a type that is LosslessStringConvertible or that otherwise has 
> an unlabeled String initializer, but use the String.init(describing: T) 
> initializer if not.

Right now string interpolation is done via the StringInterpolationConvertible 
protocol, and in particular the implementation for String contains

  public init(stringInterpolationSegment expr: T) {
self = String(expr)
  }

This implementation could be changed to test for LosslessStringConvertible, but 
there's no way to test for "Does String have an unlabelled initializer that 
accepts type T?", so the only way to implement this proposed optimization is by 
adding extra compiler magic.

I'm also not convinced that this is a performance optimization at all. It seems 
reasonable to expect that the unlabeled initializer would basically be sugar 
for calling the labeled initializer (or accessing the description property 
directly), which means there's no performance benefit to calling the unlabeled 
initializer. I can't think of any good reason for a type to implement an 
unlabeled String initializer that's more efficient than its implementation of 
CustomStringConvertible or Streamable.

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

Yes.

>   * 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?

A quick reading of the current proposal, and I participated in the original 
review.

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


Re: [swift-evolution] [swift-evolution-announce] [Accepted with Revision] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-25 Thread Kevin Ballard via swift-evolution
That being said, since we now have generic typealiases, I could presumably just 
have something like

public typealias UnfoldFirstSequence = UnfoldSequence<T, (T?, Bool)>

-Kevin Ballard

On Wed, May 25, 2016, at 09:01 PM, Kevin Ballard wrote:
> We could, but my plan was to implement sequence(first:next:) as a call to 
> sequence(state:next:). I could of course implement it twice, but that would 
> presumably result in slightly larger code size and a larger API surface 
> (because there's a whole extra type there). I think this sort of thing can be 
> hashed out in patch review if anyone feels strongly about it.
> 
> -Kevin Ballard
> 
> On Wed, May 25, 2016, at 08:56 PM, Patrick Smith wrote:
> > Just a dumb question, can you have two different types? UnfoldSequence and 
> > UnfoldStateSequence? Then they can have more focused generic parameters.
> > 
> > 
> > > On 26 May 2016, at 1:51 PM, Kevin Ballard via swift-evolution 
> > > <swift-evolution@swift.org> wrote:
> > > 
> > > On Wed, May 25, 2016, at 08:49 PM, Chris Lattner wrote:
> > >> 
> > >>> On May 25, 2016, at 8:39 PM, Kevin Ballard via swift-evolution 
> > >>> <swift-evolution@swift.org> wrote:
> > >>> 
> > >>> On Thu, May 19, 2016, at 05:52 PM, Kevin Ballard wrote (on a different 
> > >>> thread):
> > >>>> After having given this some thought, it seems apparent that 
> > >>>> `sequence(state:next:)` is equivalent to `AnyIterator({ ... })` where 
> > >>>> the closure captures a single mutable variable. The microbenchmark 
> > >>>> performance may differ slightly, as the AnyIterator version will 
> > >>>> allocate a box on the heap to hold the captured variable (assuming it 
> > >>>> can't get inlined entirely), whereas UnfoldSequence won't. But the 
> > >>>> functionality is the same. 
> > >>> 
> > >>> For the record, I just realized that the type signature of 
> > >>> UnfoldSequence actually requires that we do heap allocation as well, 
> > >>> because this type can only be used for the stateful version if we erase 
> > >>> the state type by capturing it in a closure.
> > >>> 
> > >>> As part of implementing this, I'm going to go ahead and modify the type 
> > >>> signature to UnfoldSequence<T, State>, with `state(first:next:)` 
> > >>> returning the type UnfoldSequence<T, T?>. I think it's better to 
> > >>> diverge slightly from the proposal than it is to introduce unnecessary 
> > >>> (albeit small) performance cost. I hope there are no objections.
> > > 
> > > And of course I spoke too soon, because T? isn't the right state to 
> > > handle this. It looks like I'll end up going with UnfoldSequence<T, (T?, 
> > > Bool)>. Slightly ugly, but most people won't be typing it that often, and 
> > > we've had worse (such as 
> > > LazyMapSequence<LazyFilterSequence<LazyMapSequence<Self.Elements, 
> > > ElementOfResult?>>, ElementOfResult>, which is quite a mouthful).
> > > 
> > >> That makes sense to me - the core team review discussion did not 
> > >> specifically discuss the return type in question, nor its naming.  In my 
> > >> opinion, these implementation concerns can be handled by patch review 
> > >> process.
> > > 
> > > Glad to hear it.
> > > 
> > > -Kevin Ballard
> > > ___
> > > 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] [swift-evolution-announce] [Accepted with Revision] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-25 Thread Kevin Ballard via swift-evolution
We could, but my plan was to implement sequence(first:next:) as a call to 
sequence(state:next:). I could of course implement it twice, but that would 
presumably result in slightly larger code size and a larger API surface 
(because there's a whole extra type there). I think this sort of thing can be 
hashed out in patch review if anyone feels strongly about it.

-Kevin Ballard

On Wed, May 25, 2016, at 08:56 PM, Patrick Smith wrote:
> Just a dumb question, can you have two different types? UnfoldSequence and 
> UnfoldStateSequence? Then they can have more focused generic parameters.
> 
> 
> > On 26 May 2016, at 1:51 PM, Kevin Ballard via swift-evolution 
> > <swift-evolution@swift.org> wrote:
> > 
> > On Wed, May 25, 2016, at 08:49 PM, Chris Lattner wrote:
> >> 
> >>> On May 25, 2016, at 8:39 PM, Kevin Ballard via swift-evolution 
> >>> <swift-evolution@swift.org> wrote:
> >>> 
> >>> On Thu, May 19, 2016, at 05:52 PM, Kevin Ballard wrote (on a different 
> >>> thread):
> >>>> After having given this some thought, it seems apparent that 
> >>>> `sequence(state:next:)` is equivalent to `AnyIterator({ ... })` where 
> >>>> the closure captures a single mutable variable. The microbenchmark 
> >>>> performance may differ slightly, as the AnyIterator version will 
> >>>> allocate a box on the heap to hold the captured variable (assuming it 
> >>>> can't get inlined entirely), whereas UnfoldSequence won't. But the 
> >>>> functionality is the same. 
> >>> 
> >>> For the record, I just realized that the type signature of 
> >>> UnfoldSequence actually requires that we do heap allocation as well, 
> >>> because this type can only be used for the stateful version if we erase 
> >>> the state type by capturing it in a closure.
> >>> 
> >>> As part of implementing this, I'm going to go ahead and modify the type 
> >>> signature to UnfoldSequence<T, State>, with `state(first:next:)` 
> >>> returning the type UnfoldSequence<T, T?>. I think it's better to diverge 
> >>> slightly from the proposal than it is to introduce unnecessary (albeit 
> >>> small) performance cost. I hope there are no objections.
> > 
> > And of course I spoke too soon, because T? isn't the right state to handle 
> > this. It looks like I'll end up going with UnfoldSequence<T, (T?, Bool)>. 
> > Slightly ugly, but most people won't be typing it that often, and we've had 
> > worse (such as 
> > LazyMapSequence<LazyFilterSequence<LazyMapSequence<Self.Elements, 
> > ElementOfResult?>>, ElementOfResult>, which is quite a mouthful).
> > 
> >> That makes sense to me - the core team review discussion did not 
> >> specifically discuss the return type in question, nor its naming.  In my 
> >> opinion, these implementation concerns can be handled by patch review 
> >> process.
> > 
> > Glad to hear it.
> > 
> > -Kevin Ballard
> > ___
> > 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] [swift-evolution-announce] [Accepted with Revision] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-25 Thread Kevin Ballard via swift-evolution
On Wed, May 25, 2016, at 08:49 PM, Chris Lattner wrote:
> 
> > On May 25, 2016, at 8:39 PM, Kevin Ballard via swift-evolution 
> > <swift-evolution@swift.org> wrote:
> > 
> > On Thu, May 19, 2016, at 05:52 PM, Kevin Ballard wrote (on a different 
> > thread):
> >> After having given this some thought, it seems apparent that 
> >> `sequence(state:next:)` is equivalent to `AnyIterator({ ... })` where the 
> >> closure captures a single mutable variable. The microbenchmark performance 
> >> may differ slightly, as the AnyIterator version will allocate a box on the 
> >> heap to hold the captured variable (assuming it can't get inlined 
> >> entirely), whereas UnfoldSequence won't. But the functionality is the 
> >> same. 
> >  
> > For the record, I just realized that the type signature of 
> > UnfoldSequence actually requires that we do heap allocation as well, 
> > because this type can only be used for the stateful version if we erase the 
> > state type by capturing it in a closure.
> >  
> > As part of implementing this, I'm going to go ahead and modify the type 
> > signature to UnfoldSequence<T, State>, with `state(first:next:)` returning 
> > the type UnfoldSequence<T, T?>. I think it's better to diverge slightly 
> > from the proposal than it is to introduce unnecessary (albeit small) 
> > performance cost. I hope there are no objections.

And of course I spoke too soon, because T? isn't the right state to handle 
this. It looks like I'll end up going with UnfoldSequence<T, (T?, Bool)>. 
Slightly ugly, but most people won't be typing it that often, and we've had 
worse (such as 
LazyMapSequence<LazyFilterSequence<LazyMapSequence<Self.Elements, 
ElementOfResult?>>, ElementOfResult>, which is quite a mouthful).

> That makes sense to me - the core team review discussion did not specifically 
> discuss the return type in question, nor its naming.  In my opinion, these 
> implementation concerns can be handled by patch review process.

Glad to hear it.

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


Re: [swift-evolution] [swift-evolution-announce] [Accepted with Revision] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-25 Thread Kevin Ballard via swift-evolution
On Thu, May 19, 2016, at 05:52 PM, Kevin Ballard wrote (on a
different thread):
> After having given this some thought, it seems apparent that
> `sequence(state:next:)` is  equivalent to `AnyIterator({ ... })` where
> the closure captures a single mutable variable. The microbenchmark
> performance may differ slightly, as the AnyIterator version will
> allocate a box on the heap to hold the captured variable (assuming it
> can't get inlined entirely), whereas UnfoldSequence won't. But the
> functionality is the same.
 
For the record, I just realized that the type signature of
UnfoldSequence actually requires that we do heap allocation as well,
because this type can only be used for the stateful version if we erase
the state type by capturing it in a closure.
 
As part of implementing this, I'm going to go ahead and modify the type
signature to UnfoldSequence, with `state(first:next:)`
returning the type UnfoldSequence. I think it's better to diverge
slightly from the proposal than it is to introduce unnecessary (albeit
small) performance cost. I hope there are no objections.
 
-Kevin Ballard
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Accepted with Revision] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-25 Thread Kevin Ballard via swift-evolution
And I've just grabbed that bug, and will whip up an initial
implementation shortly :D
 
I'm also going to update the proposal with the name change in a minute.
 
-Kevin Ballard
 
On Wed, May 25, 2016, at 07:54 PM, Jacob Bandes-Storch via swift-evolution 
wrote:
> Great news!
>
> I've filed a bug for this in JIRA:
> https://bugs.swift.org/browse/SR-1622
>
>
> On Wed, May 25, 2016 at 7:44 PM, Chris Lattner via swift-evolution  evolut...@swift.org> wrote:
>> Proposal Link:
>> https://github.com/apple/swift-evolution/blob/master/proposals/0094-sequence-function.md
>>
>>  The review of "SE-0094: Add sequence(initial:next:) and
>>  sequence(state:next:) to the stdlib" ran from May 19…23, 2016. The
>>  proposal has been *accepted* with one minor naming-related change:
>>
>>  - Feedback from the community & core team is positive.
>>  - Core team discussed whether it made sense to add just the first
>>form, or whether it made sense to add both.  They agree that
>>although the form using an explicit state is much more
>>infrequently used, when it is necessary, it is extremely helpful
>>to have.  It is also useful to consider both as a pair.
>>  - On naming, the core team agrees with the community that
>>“sequence(first:next:)” is a better name than
>>"sequence(initial:next:)”.  "sequence(state:next:)” is approved
>>as-is.
>>
>>  Thank you to Kevin Ballard and Erica Sadun for proposing this both
>>  in SE-0045 and in SE-0094, an implementation of these functions
>>  would be welcome!
>>
>>  -Chris Lattner
>>  Review Manager
>>
>>
>> ___
>>  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] [Review] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-25 Thread Kevin Ballard via swift-evolution
On Wed, May 25, 2016, at 01:08 PM, Dave Abrahams wrote:
> 
> 
> 
> On behalf of Dmitri Gribenko, Max Moiseev, and myself:
> 
> on Thu May 19 2016, Kevin Ballard 
>  wrote:
> 
> > After having given this some thought, it seems apparent that `sequence
> > (state:next:)` is equivalent to `AnyIterator({ ... })` where the closure
> > captures a single mutable variable. 
> 
> Yes.  
> 
> > The microbenchmark performance may differ slightly, as the AnyIterator
> > version will allocate a box on the heap to hold the captured variable
> > (assuming it can't get inlined entirely), whereas UnfoldSequence
> > won't. But the functionality is the same.  Thus the question: do we
> > want to keep `sequence(state:next:)` or is it too close to AnyIterator
> > in functionality? 
> 
> We think the need to do a capture is icky, so the sequence form is
> almost always better.

I agree that the need for a capture is ugly.

> > Arguments in favor of `sequence(state:next:)`: *
> > It's equivalent to unfold and the dual of reduce, so people who've
> > used functional programming languages may expect it to exist.  * It
> > allows you to create ad-hoc stateful sequences without polluting the
> > current scope with a variable that exists solely to be captured.  * If
> > the cost of a small heap allocation is significant for your code, it
> > may be more performant than AnyIterator.  Personally, the most
> > important reason here for me is not having to pollute the current
> > closure with a variable. And this could actually be solved another
> > way, by allowing the use of `var` in a capture list, which would let
> > you say something like `AnyGenerator({ [var state=foo] in ... })`.
> > Given all this, at this point I'm actually leaning towards
> > saying`sequence (state:next:)` doesn't pull its own weight and we
> > should just go with `sequence (initial:next:)`.  -Kevin Ballard
> 
> We forgot to mention this earlier: we prefer “first” over “initial” as the
> label on the latter.

I agree. I almost suggested this a few days ago, but I didn't want to end up 
bikeshedding the parameter names. I'm inclined to say that the Swift core team 
should decide whether to change it to "first" instead of debating it, and if 
so, make that modification when accepting (assuming of course that it does get 
accepted).

> The design of AnySequence and AnyIterator dates from a time when the
> compiler was very immature and many design avenues we might have taken
> were not available.  I find the `sequence` forms to be superior in
> general, and IMO at some point we should re-evaluate the interfaces to
> AnySequence and AnyIterator.

That sounds like a reasonable justification for keeping sequence(state:next:).

-Kevin Ballard

> Cheers,
> Dave
> 
> > On Thu, May 19, 2016, at 05:37 PM, Trent Nadeau via swift-evolution wrote:
> >
> > Ah, yes. I apologize. The fact that state is inout, and the same 
> > instance is
> > always passed in confused me. Thanks for the correction.
> >
> > On Thu, May 19, 2016 at 7:46 PM, Brent Royal-Gordon
> >  wrote:
> >
> > > Also note that there's a typo in the second example:
> > >
> > > for view in sequence(initial: someView, next: { $0.
> > > superview }) {
> > >
> > > // someView, someView.superview, someView.superview.superview, ...
> > >
> > > }
> > >
> > >
> > > should be:
> > >
> > > for view in sequence(state: someView, next: { $0.
> > > superview }) {
> > >
> > > // someView, someView.superview, someView.superview.superview, ...
> > >
> > > }
> >
> > I don't think these are mistakes—in each iteration of the loop, $0 
> > is
> > supposed to be the view from the previous iteration.
> >
> > If you wanted an example using `state`, here's one which is roughly
> > equivalent to `stride(from: 1.0, to: 2.0, by: 0.1)`, using a
> > non-error-accumulating algorithm:
> >
> > let start = 1.0
> >
> > let end = 2.0
> >
> > let distance = 0.1
> >
> > for color in sequence(state: -1.0, next: { $0 += 1; let next = 
> > start +
> > $0 * distance; return next < end ? next : nil }) {
> >
> > …
> >
> > }
> >
> > --
> > Brent Royal-Gordon
> > Architechies
> >
> > -- 
> >
> > Trent Nadeau
> >
> > ___
> >
> > swift-evolution mailing list
> >
> > swift-evolution-m3fhrko0vlzytjvyw6y...@public.gmane.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
> 
> -- 
> Dave
> 

Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

2016-05-24 Thread Kevin Ballard via swift-evolution
On Tue, May 24, 2016, at 11:06 AM, Chris Lattner wrote:
>   * What is your evaluation of the proposal?

+1. protocol<...> feels like a weird corner of the language that not a lot of 
people know about. Also, changing to Any<...> opens the door to allowing 
classes in the list instead of just protocols (protocol doesn't make much sense, but Any is fine).

I prefer to spell it as Any instead of any. I think the biggest reason is 
because Any, without brackets, is used as an existential type, and it would be 
weird to have a lowercase identifier used as a type. Arguably we could 
introduce any<...> and make Any just a typealias for any<>, but that seems 
potentially confusing, so I'd rather just have Any and Any<...>.

Joe Groff's infix notation proposal has some merit, and I'd like to mention one 
other point in favor: Any and Any are equivalent types, but it's not 
immediately obvious that they should be, since all other uses of type 
parameters care about type ordering. Infix notation gets rid of the assumption 
of ordering (since infix operators like + are usually commutative). But it is a 
more dramatic change, and we can always consider switching to that later if we 
want (I imagine that usage of protocol<...> is fairly rare so not many people 
will be impacted by this change), and it does have the drawbacks that Joe 
mentioned which are non-trivial.

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

Probably, yeah. It removes a rarely-used construct in favor of one that people 
are probably more familiar with, and as I mentioned before it opens the door to 
allowing Any (which is an Obj-C feature that Swift 
currently has no equivalent for).

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

Yes.

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

The only language that comes to mind where I'm familiar with the equivalent 
functionality is Rust, and as Joe Groff already said, Rust uses an infix 
operator for this.

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

A quick reading of the proposal and reading the review thread to date.

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


Re: [swift-evolution] [Review] SE-0093: Adding a public base property to slices

2016-05-23 Thread Kevin Ballard via swift-evolution
On Mon, May 23, 2016, at 03:15 PM, Max Moiseev wrote:
> Hi Kevin,
> 
> Thanks for reviewing this proposal.
> 
> It is my poor choice of words to be blamed for the confusion. There is 
> definitely no reason for the new property to only be available for the 
> MutableRandomAccessSlice type. Moreover, since all the slice types are 
> generated with GYB now, it would be more code ;-)
> 
> The intention is to add the new property to ALL the slice types.

Ah hah, you're right, I missed the following line when reading:

> The same change is applicable to both mutable and immutable slice types.

So +1, though I'm still in favor of renaming `_base` to `base` and then adding 
a computed `_base` property back if the stdlib breakage is too high.

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


Re: [swift-evolution] [Review] SE-0093: Adding a public base property to slices

2016-05-23 Thread Kevin Ballard via swift-evolution
On Thu, May 19, 2016, at 04:43 PM, Dave Abrahams via swift-evolution wrote:
>   * What is your evaluation of the proposal?

The motivation sounds reasonable, as does the solution. But it seems odd to 
expose a property `base` on MutableRandomAccessSlice without exposing it on any 
other slice type. I'd much rather expose it everywhere, ideally by renaming the 
`_base` property as suggested in the alternatives section. Stdlib breakage can 
be handled on a temporary basis by providing the `_base` accessor as a computed 
property that returns `base`, though of course the goal should be to remove 
this entirely (or hopefully not have it at all if there's not too much stdlib 
breakage). And such a change should still be purely additive from the 
perspective of third-party code.

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

Yes. This is a relatively minor change but it allows for better performance.

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

Yes.

>   * 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 any languages with this offhand.

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

A quick reading.

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


Re: [swift-evolution] [Review] SE-0089: Renaming String.init(_: T)

2016-05-20 Thread Kevin Ballard via swift-evolution
On Fri, May 20, 2016, at 05:14 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Fri May 20 2016, Kevin Ballard  wrote:
> 
> > On Tue, May 17, 2016, at 08:32 PM, Chris Lattner via swift-evolution wrote:
> >>* What is your evaluation of the proposal?
> >
> > I'm a little nervous about this change, because converting things to
> > strings is a fairly basic operation and it should be immediately
> > obvious how to do that. That said, the described issues are pretty
> > bad, and I know I've had to carefully triple-check sometimes to make
> > sure I was calling the right initializer. So I'm +1 on the idea.
> >
> > That said, I don't like the name String(printing:). As others have
> > pointed out, it sounds like this is related to print(), but this
> > initializer does not actually print anything, it just converts any
> > value into a string. I also don't like String(describing:) because
> > it's too long. This initializer should be easier to call than
> > String(reflecting:). Also, in my experience this initializer is
> > particularly useful with code of the form `someOpt.map(String.init)`,
> > and saying `someOpt.map(String.init(describing:))` is annoyingly long.
> >
> > Given this, I'd like to suggest the simpler `String(from:)`. It's
> > short and generic, and it makes sense as it creates a String from any
> > value.
> 
> Not too bad.  I could live with it.



> > I'm also not a fan of Dave's suggestion of removing this initializer
> > entirely in favor of "\(foo)".  This feels weird, and it also can't be
> > turned into a first-class function value.
> 
>   { "\($0)" }
> 
> ?

Good point. I think what I intended to express was you cannot refer to this 
operation by name anymore. Maybe not a big deal, but it feels weird.

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


Re: [swift-evolution] [Review] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-19 Thread Kevin Ballard via swift-evolution
On Thu, May 19, 2016, at 05:59 PM, Patrick Smith wrote:
> This sounds fair to me. I imagine a functional version would return
> two item tuple instead of mutating, so would it be that similar to
> what people expect?
 
A functional version of `sequence(state:next:)` would indeed use the
type signature of `next` as `State -> (T, State)?`. This is precisely
how Haskell's `unfoldr` works. But doing that with Swift where the state
contains Copy-on-Write data structures will end up with unnecessary
copies if the COW data structure is mutated.
 
-Kevin
 
>> On 20 May 2016, at 10:52 AM, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:
>>
>> After having given this some thought, it seems apparent that
>> `sequence(state:next:)` is  equivalent to `AnyIterator({ ... })`
>> where the closure captures a single mutable variable. The
>> microbenchmark performance may differ slightly, as the AnyIterator
>> version will allocate a box on the heap to hold the captured variable
>> (assuming it can't get inlined entirely), whereas UnfoldSequence
>> won't. But the functionality is the same.
>>
>> Thus the question: do we want to keep `sequence(state:next:)` or is
>> it too close to AnyIterator in functionality? Arguments in favor of
>> `sequence(state:next:)`:
>>
>> * It's equivalent to unfold and the dual of reduce, so people who've
>>   used functional programming languages may expect it to exist.
>> * It allows you to create ad-hoc stateful sequences without polluting
>>   the current scope with a variable that exists solely to be
>>   captured.
>> * If the cost of a small heap allocation is significant for your
>>   code, it may be more performant than AnyIterator.
>>
>> Personally, the most important reason here for me is not having to
>> pollute the current closure with a variable. And this could actually
>> be solved another way, by allowing the use of `var` in a capture
>> list, which would let you say something like `AnyGenerator({ [var
>> state=foo] in ... })`.
>>
>> Given all this, at this point I'm actually leaning towards
>> saying`sequence(state:next:)` doesn't pull its own weight and we
>> should just go with `sequence(initial:next:)`.
>>
>> -Kevin Ballard
>>
>> On Thu, May 19, 2016, at 05:37 PM, Trent Nadeau via swift-
>> evolution wrote:
>>> Ah, yes. I apologize. The fact that state is inout, and the same
>>> instance is always passed in confused me. Thanks for the correction.
>>>
>>> On Thu, May 19, 2016 at 7:46 PM, Brent Royal-Gordon
>>> <br...@architechies.com> wrote:
>>>> > Also note that there's a typo in the second example:
>>>>  >
>>>>  > for view in sequence(initial: someView, next: { $0. superview
>>>>  > }) {
>>>>  >
>>>>  > // someView, someView.superview, someView.superview.superview,
>>>>  > ...
>>>>  >
>>>>  > }
>>>>  >
>>>>  >
>>>>  > should be:
>>>>  >
>>>>  > for view in sequence(state: someView, next: { $0. superview }) {
>>>>  >
>>>>  > // someView, someView.superview, someView.superview.superview,
>>>>  > ...
>>>>  >
>>>>  > }
>>>>
>>>> I don't think these are mistakes—in each iteration of the loop, $0
>>>> is supposed to be the view from the previous iteration.
>>>>
>>>> If you wanted an example using `state`, here's one which is roughly
>>>> equivalent to `stride(from: 1.0, to: 2.0, by: 0.1)`, using a non-error-
>>>> accumulating algorithm:
>>>>
>>>> let start = 1.0
>>>> let end = 2.0
>>>> let distance = 0.1
>>>>
>>>> for color in sequence(state: -1.0, next: { $0 += 1; let next =
>>>> start + $0 * distance; return next < end ? next : nil }) {
>>>> …
>>>> }
>>>>
>>>> --
>>>>  Brent Royal-Gordon Architechies
>>>
>>>
>>>
>>> --
>>> Trent Nadeau
>>> _
>>> 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] [Review] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-19 Thread Kevin Ballard via swift-evolution
After having given this some thought, it seems apparent that
`sequence(state:next:)` is  equivalent to `AnyIterator({ ... })` where
the closure captures a single mutable variable. The microbenchmark
performance may differ slightly, as the AnyIterator version will
allocate a box on the heap to hold the captured variable (assuming it
can't get inlined entirely), whereas UnfoldSequence won't. But the
functionality is the same.
 
Thus the question: do we want to keep `sequence(state:next:)` or is it
too close to AnyIterator in functionality? Arguments in favor of
`sequence(state:next:)`:
 
* It's equivalent to unfold and the dual of reduce, so people who've
  used functional programming languages may expect it to exist.
* It allows you to create ad-hoc stateful sequences without polluting
  the current scope with a variable that exists solely to be captured.
* If the cost of a small heap allocation is significant for your code,
  it may be more performant than AnyIterator.
 
Personally, the most important reason here for me is not having to
pollute the current closure with a variable. And this could actually be
solved another way, by allowing the use of `var` in a capture list,
which would let you say something like `AnyGenerator({ [var state=foo]
in ... })`.
 
Given all this, at this point I'm actually leaning towards
saying`sequence(state:next:)` doesn't pull its own weight and we should
just go with `sequence(initial:next:)`.
 
-Kevin Ballard
 
On Thu, May 19, 2016, at 05:37 PM, Trent Nadeau via swift-evolution wrote:
> Ah, yes. I apologize. The fact that state is inout, and the same
> instance is always passed in confused me. Thanks for the correction.
>
> On Thu, May 19, 2016 at 7:46 PM, Brent Royal-Gordon
>  wrote:
>> > Also note that there's a typo in the second example:
>>  >
>>  > for view in sequence(initial: someView, next: { $0. superview }) {
>>  >
>>  > // someView, someView.superview, someView.superview.superview, ...
>>  >
>>  > }
>>  >
>>  >
>>  > should be:
>>  >
>>  > for view in sequence(state: someView, next: { $0. superview }) {
>>  >
>>  > // someView, someView.superview, someView.superview.superview, ...
>>  >
>>  > }
>>
>> I don't think these are mistakes—in each iteration of the loop, $0 is
>> supposed to be the view from the previous iteration.
>>
>>  If you wanted an example using `state`, here's one which is roughly
>>  equivalent to `stride(from: 1.0, to: 2.0, by: 0.1)`, using a non-error-
>>  accumulating algorithm:
>>
>>  let start = 1.0
>>  let end = 2.0
>>  let distance = 0.1
>>
>>  for color in sequence(state: -1.0, next: { $0 += 1; let next = start
>>  + $0 * distance; return next < end ? next : nil }) {
>>  …
>>  }
>>
>>  --
>>  Brent Royal-Gordon Architechies
>
>
>
> --
> Trent Nadeau
> _
> 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] [Review] SE-0094: Add sequence(initial:next:) and sequence(state:next:) to the stdlib

2016-05-19 Thread Kevin Ballard via swift-evolution
On Thu, May 19, 2016, at 04:20 PM, Trent Nadeau via swift-evolution wrote:
> Also note that there's a typo in the second example:
>
> for view in sequence(initial: someView, next: { $.superview }) {  //
> someView, someView.superview, someView.superview.superview, ... }
>
> should be:
>
> for view in sequence(state: someView, next: { $.superview }) {  //
> someView, someView.superview, someView.superview.superview, ... }
 
The code as written is correct. The rewritten version would actually
just emit [someView.superview, someView.superview, someView.superview,
...] forever. I imagine the confusion stems from the fact that there's 2
examples but they both demonstrate just the first function, and there's
no examples of the second function, which is something I'll try to
address soon.
 
-Kevin Ballard
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0045: Add scan, prefix(while:), drop(while:), and iterate to the stdlib

2016-05-14 Thread Kevin Ballard via swift-evolution
AnySequence is specifically used to erase the type of an underlying
sequence, and I'm guessing that using it here will make it harder to
optimize loops that use this.
 
-Kevin Ballard
 
On Fri, May 13, 2016, at 10:20 PM, Patrick Smith wrote:
> Would there be any issue with the return type being AnySequence? It’s
> used in other areas:
>
> LazySequence & FlattenSequence’s
> dropFirst(n: Int) -> AnySequence
> dropLast(n: Int) -> AnySequence
>
> No need to introduce another type, and it’s straight forward to
> implement with AnySequence.
>
>
>> On 14 May 2016, at 5:07 AM, Kevin Ballard via swift-evolution > evolut...@swift.org> wrote:
>>
>> On Fri, May 13, 2016, at 11:08 AM, Erica Sadun wrote:
>>> On May 1, 2016, at 5:13 AM, Brent Royal-Gordon via swift-evolution
>>> <swift-evolution@swift.org> wrote:
>>>>
>>>>> The proposal has been updated as per feedback from the core team
>>>>> (https://github.com/apple/swift-evolution/pull/275). This includes
>>>>> removing some last vestiges of Swift 2 naming as well as replacing
>>>>> `iterate(_:apply:)` with an overloaded function
>>>>> `unfold(_:applying:)`.
>>>>
>>>> The proposal says this:
>>>>
>>>> public func unfold<T, State>(_ initialState: State, applying: State
>>>> -> (T, State)?) -> UnfoldSequence
>>>> public func unfold(_ initialElement: T, apply: T -> T) ->
>>>> UnfoldSequence
>>>>
>>>> However, the comment implies that the second one should instead be
>>>> this:
>>>>
>>>> public func unfold(_ initialElement: T, applying: T -> T?) ->
>>>> UnfoldSequence
>>>>
>>>> I'm not sure I like having these be overloaded on only the return
>>>> type of the closure. Maybe we could do something like this?
>>>>
>>>> public func unfold<T, State>(fromState initialState: State,
>>>> applying: State -> (T, State)?) -> UnfoldSequence
>>>> public func unfold(fromFirst initialElement: T, apply: T -> T)
>>>> -> UnfoldSequence
>>>>
>>>> That way you're calling either `unfold(fromState:applying:)` or
>>>> `unfold(fromFirst:applying:)`. (Some further bikeshedding might be
>>>> needed here—it's late and I'm tired.)
>>>
>>> I really don't want to see this discussion die as I have a vested
>>> interest in getting this functionality into
>>> Swift 3. So let me suggest that
>>>
>>> `sequence(_:, next:) -> AdHocSequence`
>>>
>>> might be a Swift acceptable solution.  We're not going to see
>>> fold/unfold pair happen. It's a given that
>>> `reduce` is a fixed point in Swift space and `sequence` well
>>> describes what this should be doing.
>>>
>>> So is it possible to push forward with `sequence`, whose only
>>> negative seems to be that it's not as well
>>> loved as `unfold`?
>>
>> I do like `sequence`, though I'm not sold on the name AdHocSequence
>> (just from that name it's hard to figure out what it does). An
>> alternative is `expand`, which is nice because it pairs with
>> `reduce`, but it's less obvious that it produces a sequence and the
>> name isn't as good with the stateful version.
>>
>> As for return type name, we could go ahead and use UnfoldSequence
>> anyway even though the function isn't named `unfold`, because this
>> name will make sense to people who do know what unfold is, and I'm
>> not convinced we can have a meaningful name for people who don't
>> (since SequenceSequence is too silly).
>>
>> So given that, I'll suggest the following:
>>
>> func sequence(initial: T, next: T -> T?) -> UnfoldSequence
>> func sequence<T, State>(state: State, next: (inout State) -> T?) ->
>> UnfoldSequence
>>
>> I'm suggesting `sequence(initial:next:)` instead of the previously-
>> suggested `sequence(from:applying:)` because the term "from" could
>> equally well mean the first element or the state, whereas "initial"
>> should make it more obvious that this value is the first element of
>> the resulting sequence. And I'm using "next" as suggested by Erica
>> because the function does return the next element, and it's similar
>> to the IteratorProtocol method. I've also chosen to change the
>> stateful version to use an inout parameter, as previously suggested,
>> because it's equivalent to the State -> (T, State)? in functionality
>> but is less likely to produce unwanted COW copies.
>>
>> -Kevin Ballard
>> ___
>> 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] [Review] SE-0045: Add scan, prefix(while:), drop(while:), and iterate to the stdlib

2016-05-13 Thread Kevin Ballard via swift-evolution
On Fri, May 13, 2016, at 11:08 AM, Erica Sadun wrote:
> On May 1, 2016, at 5:13 AM, Brent Royal-Gordon via swift-evolution  evolut...@swift.org> wrote:
>>
>>> The proposal has been updated as per feedback from the core team
>>> (https://github.com/apple/swift-evolution/pull/275). This includes
>>> removing some last vestiges of Swift 2 naming as well as replacing
>>> `iterate(_:apply:)` with an overloaded function
>>> `unfold(_:applying:)`.
>>
>> The proposal says this:
>>
>>  public func unfold(_ initialState: State, applying: State
>>  -> (T, State)?) -> UnfoldSequence
>>  public func unfold(_ initialElement: T, apply: T -> T) ->
>>  UnfoldSequence
>>
>> However, the comment implies that the second one should instead
>> be this:
>>
>>  public func unfold(_ initialElement: T, applying: T -> T?) ->
>>  UnfoldSequence
>>
>> I'm not sure I like having these be overloaded on only the return
>> type of the closure. Maybe we could do something like this?
>>
>>  public func unfold(fromState initialState: State,
>>  applying: State -> (T, State)?) -> UnfoldSequence
>>  public func unfold(fromFirst initialElement: T, apply: T -> T) ->
>>  UnfoldSequence
>>
>> That way you're calling either `unfold(fromState:applying:)` or
>> `unfold(fromFirst:applying:)`. (Some further bikeshedding might be
>> needed here—it's late and I'm tired.)
>
> I really don't want to see this discussion die as I have a vested
> interest in getting this functionality into
> Swift 3. So let me suggest that
>
> `sequence(_:, next:) -> AdHocSequence`
>
> might be a Swift acceptable solution.  We're not going to see
> fold/unfold pair happen. It's a given that
> `reduce` is a fixed point in Swift space and `sequence` well describes
> what this should be doing.
>
> So is it possible to push forward with `sequence`, whose only negative
> seems to be that it's not as well
> loved as `unfold`?
 
I do like `sequence`, though I'm not sold on the name AdHocSequence
(just from that name it's hard to figure out what it does). An
alternative is `expand`, which is nice because it pairs with `reduce`,
but it's less obvious that it produces a sequence and the name isn't as
good with the stateful version.
 
As for return type name, we could go ahead and use UnfoldSequence
anyway even though the function isn't named `unfold`, because this name
will make sense to people who do know what unfold is, and I'm not
convinced we can have a meaningful name for people who don't (since
SequenceSequence is too silly).
 
So given that, I'll suggest the following:
 
func sequence(initial: T, next: T -> T?) -> UnfoldSequence
func sequence(state: State, next: (inout State) -> T?) ->
UnfoldSequence
 
I'm suggesting `sequence(initial:next:)` instead of the previously-
suggested `sequence(from:applying:)` because the term "from" could
equally well mean the first element or the state, whereas "initial"
should make it more obvious that this value is the first element of the
resulting sequence. And I'm using "next" as suggested by Erica because
the function does return the next element, and it's similar to the
IteratorProtocol method. I've also chosen to change the stateful version
to use an inout parameter, as previously suggested, because it's
equivalent to the State -> (T, State)? in functionality but is less
likely to produce unwanted COW copies.
 
-Kevin Ballard
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Review] SE-0086: Drop NS Prefix in Swift Foundation

2016-05-12 Thread Kevin Ballard via swift-evolution
On Mon, May 9, 2016, at 03:20 PM, Douglas Gregor via swift-evolution wrote:
>  * What is your evaluation of the proposal?
 
+1 to enum renaming / hoisting, including turning NSStringEncoding into
an enum, but -1 on dropping the NS prefix. I agree with a lot of what
the other -1 people have said, but the 2 biggest reasons for me are:
 
1. The NS prefix is a signal that the type is probably an Objective-C
   class, and with the enum renaming/hoisting this signal will become
   even stronger. The fact that it's an Objective-C class means that
   it's not Swift-like, it's a reference type, it doesn't participate in
   copy-on-write mutation, etc.
 
2. Dropping the NS prefix means that a *lot* of pretty generic names are
   now owned by Foundation, which makes it difficult to implement the
   same concept in the Swift standard library. A lot of these names
   aren't likely to end up in the Swift stdlib, but I'd rather be
   cautious about this and not take any of these names.
 
By keeping the NS prefixes, we can then "swiftify" these APIs on an
ongoing basis and drop the prefix once a type has been "swiftified"
(which includes turning things into value types when applicable, not
merely renaming methods). And if done right, the swiftified types can
operate without Foundation at all, the same way
String/Array/Dictionary/Set are independent implementations that bridge
to/from Obj-C.
 
As a side note, regardless of everything else, we really should not
rename NSJSONSerialization to JSONSerialization. This class is a
specific implementation of a JSON encoder/decoder that operates on
Foundation types. The name JSONSerialization should be reserved for the
potential use of a Swift-native JSON encoder/decoder.

>  * Is the problem being addressed significant enough to warrant a
>change to Swift?
 
I don't think so. I'm not sure what the benefit of dropping the "NS"
prefix is supposed to be at all, besides saving 2 keystrokes. The
proposal says this is to "establish these libraries as fundamental and
native Swift libraries" by "making their naming style match the
convention established by the standard library", but I don't think this
is actually the right way to do this. Renaming these classes doesn't
make the API feel like native Swift (biggest example is value vs
reference types). What would make them feel like native Swift is writing
a native Swift type with a native Swift API and native Swift conventions
that bridges to/from the obj-c class (e.g. how Swift 3 is gaining the
URL value type).

>  * How much effort did you put into your review? A glance, a quick
>reading, or an in-depth study?
 
A quick reading of the proposal, as well as reading previous discussions
about this topic.
 
-Kevin Ballard
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Accepted with modifications] SE-0045: Add scan, prefix(while:), drop(while:), and unfold to the stdlib

2016-05-06 Thread Kevin Ballard via swift-evolution
On Fri, May 6, 2016, at 07:33 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Fri May 06 2016, Kevin Ballard  wrote:
> 
> > On Fri, May 6, 2016, at 06:05 PM, Dave Abrahams via swift-evolution wrote:
> >> 
> >> on Fri May 06 2016, Kevin Ballard  wrote:
> >> 
> >> > On Fri, May 6, 2016, at 05:31 PM, Kevin Ballard wrote:
> >> >> On Fri, May 6, 2016, at 05:19 PM, Dave Abrahams via swift-evolution 
> >> >> wrote:
> >
> >> >> > 
> >> >> > on Wed May 04 2016, Chris Lattner  wrote:
> >> >> > 
> >> >> > > Proposal link: 
> >> >> > > https://github.com/apple/swift-evolution/blob/master/proposals/0045-scan-takewhile-dropwhile.md
> >> >
> >> >> > >
> >> >> > > Hello Swift Community,
> >> >> > >
> >> >> > > The review of SE-0045: "Add scan, prefix(while:), drop(while:), and
> >> >> > > unfold to the stdlib" ran from April 28...May 3, 2016. A subset of 
> >> >> > > the
> >> >> > > proposal is *accepted, with modifications* for Swift 3.  This 
> >> >> > > proposal
> >> >> > > included four new additions to the standard library:
> >> >> > >
> >> >> > > Sequence.prefix(while:) & Sequence.drop(while:) - These are 
> >> >> > > *accepted* as specified in revision 3 of the proposal.
> >> >> > 
> >> >> > I know the review is over and all, but…
> >> >> > 
> >> >> > Chris brought to my attention an idea that I liked, and asked me to 
> >> >> > post
> >> >> > here about it.  Specifically, the argument label “where:” would 
> >> >> > probably
> >> >> > be better than “while:”.  “While” makes it sound to me like it's going
> >> >> > to take a nullary predicate and be much more active.  But it's hard to
> >> >> > love
> >> >> > 
> >> >> >  s.drop(where: { $0 > 1 })
> >> >> >  s.drop { $0 > 1 }
> >> >> > 
> >> >> > because it makes it sound like a general filtering operation.
> >> >> > 
> >> >> > Therefore, I'd much rather see
> >> >> > 
> >> >> >s.droppingPrefix(where: {$0 > 1})
> >> >> 
> >> >> Using "where:" has a very high potential for confusion, because
> >> >> "where" makes it sound like it runs the predicate against every
> >> >> single element, whereas "while" makes it clear that it stops
> >> >> evaluating elements once the predicate returns false. Or in other
> >> >> words, `drop(where: predicate)` looks like it should be equivalent
> >> >> to `filter({ !predicate($0) })`.
> >> >
> >> > Oops, I read your message too fast and missed the fact that you
> >> > changed the function name too in the very last line.
> >> 
> >> And made the exact point that you made :-)
> >
> > Indeed. My apologies, I was trying to get through my email too fast and 
> > ended up skimming too much.
> >
> >> > If we switched to `droppingPrefix(where:)` then we'd need to change 
> >> > `dropFirst(_:)` as well.
> >> 
> >> Yes, as I noted in my response to Erica, I would like to see some more 
> >> design
> >> coherence in this whole area.  I think
> >> 
> >>   xs.dropFirst()  =>  xs.droppingFirst()
> >>   xs.dropFirst(3) => xs.droppingPrefix(ofMaxLength: 3)
> >> 
> >> I'm not wedded to “dropping,” especially because it has other
> >> connotations.  Dmitri, Max, and I kicked around a bunch of other
> >> possibilities, e.g.
> >> 
> >>   sansPrefix
> >>   withoutPrefix
> >
> > If we do rename this, I'm partial to basing it off of the word "skip",
> > e.g. skippingPrefix(), since that's similar to "drop" but doesn't have
> > the connotation of possibly mutating the receiver. That said, having a
> > first argument label "ofMaxLength:" seems overly verbose. Don't forget
> > that not everybody has the benefit of Xcode code completion when
> > writing Swift code.
> 
> Me, for example.  It needs to be at least “maxLength,” IMO, for
> clarity.  “of” clarifies that you're not talking about the maximum
> length of the result... though I suppose it could be argued that that
> misinterpretation wouldn't make any sense.

How about "count"? `skippingFirst(count:)` is not too long and it's reasonably 
descriptive.

> >> Anyway, we can't do all of that by the seat of our pants.  I personally
> >> wouldn't want to go any further than s.dropPrefix(where: ...)  without a
> >> new proposal/review.
> >
> > Agreed, anything beyond that needs a full review. So back to the
> > suggestion at hand.
> >
> > I wrote up a whole long explanation for why I still think "while" is
> > the better choice, and then I thought about how this impacts
> > `prefix(...:)` instead of `drop(...:)`, and in this context "where:"
> > makes more sense. `prefix(while:)` turns "prefix" from a noun into a
> > verb, 
> 
> Sorta, yeah.
> 
> > and the verb meaning of "prefix" is not at all what we're doing with
> > this operation. But `prefix(where:)` is still a noun and makes
> > sense. And of course if we have `prefix(where:)` then it's a bit odd
> > to have `drop(while:)`, so we'd have to go with `drop(where:)` or
> > `dropPrefix(where:)`. So I guess I've now convinced 

Re: [swift-evolution] [Accepted with modifications] SE-0045: Add scan, prefix(while:), drop(while:), and unfold to the stdlib

2016-05-06 Thread Kevin Ballard via swift-evolution
On Fri, May 6, 2016, at 06:15 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Fri May 06 2016, Matthew Johnson  wrote:
> 
> >> On May 6, 2016, at 7:30 PM, Dave Abrahams via swift-evolution 
> >>  wrote:
> >> 
> >> 
> >> on Fri May 06 2016, Cole Campbell  wrote:
> >> 
> >>> I don't know if it's considered too late at this point to rename 
> >>> 'reduce', but
> >>> I'll add an enthusiastic +1 to renaming it to 'fold' and adding 'unfold'. 
> >>> 'Fold'
> >>> is just as obvious a name as 'reduce', IMO (actually I even prefer
> >>> it). 
> >> 
> >> It's not, IMO.  “Reduce” was chosen deliberately over “fold” because we
> >> think it is more in “common currency” among programmers, in no small
> >> part to the notice that MapReduce has gotten.
> >
> > I was guessing this was the rationale.  But if it’s not too late and
> > “fold” solves the “unfold” naming problem maybe we that balances out
> > the equation.
> 
> Personally, I'm not confident “unfold” would be considered to meet the
> utility bar, even if we changed the name of “reduce,” FWIW.

As I said to Chris in an off-list email, unfold() was actually the function 
that I was the most excited about in the proposal, because it allows for a very 
elegant solution to a variety of looping needs, especially now that we've 
gotten rid of the C-style for loops. One example of its use is something like

  // Iterate over self.view and all its ancestor views.
  for view in unfold(self.view, applying: { $0.superview }) {
  // ...
  }

In fact, just today I hit this exact issue and wished I had unfold(). This same 
pattern works for any case where an object has a property of the same type and 
you want to walk the entire chain, such as 
UIViewController.presentingViewController, or 
NSError.userInfo[NSUnderlyingErrorKey].

It also integrates very nicely with the other sequence methods, including 
drop(while:) and prefix(while:). For example:

  // Iterate over someView and all its ancestors, stopping at self.view
  for view in unfold(someView, applying: { $0.superview }).prefix(while: { $0 
!== self.view }) {
  // ...
  }

Incidentally, I tried writing up an example of using the stateful version to 
reimplement zip(), but it ended up being a good argument in favor of the 
suggestion someone (maybe you?) had for turning the state into an inout 
parameter.

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


Re: [swift-evolution] [Accepted with modifications] SE-0045: Add scan, prefix(while:), drop(while:), and unfold to the stdlib

2016-05-06 Thread Kevin Ballard via swift-evolution
On Fri, May 6, 2016, at 06:05 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Fri May 06 2016, Kevin Ballard  wrote:
> 
> > On Fri, May 6, 2016, at 05:31 PM, Kevin Ballard wrote:
> >> On Fri, May 6, 2016, at 05:19 PM, Dave Abrahams via swift-evolution wrote:
> >> > 
> >> > on Wed May 04 2016, Chris Lattner  wrote:
> >> > 
> >> > > Proposal link: 
> >> > > https://github.com/apple/swift-evolution/blob/master/proposals/0045-scan-takewhile-dropwhile.md
> >
> >> > >
> >> > > Hello Swift Community,
> >> > >
> >> > > The review of SE-0045: "Add scan, prefix(while:), drop(while:), and
> >> > > unfold to the stdlib" ran from April 28...May 3, 2016. A subset of the
> >> > > proposal is *accepted, with modifications* for Swift 3.  This proposal
> >> > > included four new additions to the standard library:
> >> > >
> >> > > Sequence.prefix(while:) & Sequence.drop(while:) - These are *accepted* 
> >> > > as specified in revision 3 of the proposal.
> >> > 
> >> > I know the review is over and all, but…
> >> > 
> >> > Chris brought to my attention an idea that I liked, and asked me to post
> >> > here about it.  Specifically, the argument label “where:” would probably
> >> > be better than “while:”.  “While” makes it sound to me like it's going
> >> > to take a nullary predicate and be much more active.  But it's hard to
> >> > love
> >> > 
> >> >  s.drop(where: { $0 > 1 })
> >> >  s.drop { $0 > 1 }
> >> > 
> >> > because it makes it sound like a general filtering operation.
> >> > 
> >> > Therefore, I'd much rather see
> >> > 
> >> >s.droppingPrefix(where: {$0 > 1})
> >> 
> >> Using "where:" has a very high potential for confusion, because
> >> "where" makes it sound like it runs the predicate against every
> >> single element, whereas "while" makes it clear that it stops
> >> evaluating elements once the predicate returns false. Or in other
> >> words, `drop(where: predicate)` looks like it should be equivalent
> >> to `filter({ !predicate($0) })`.
> >
> > Oops, I read your message too fast and missed the fact that you
> > changed the function name too in the very last line.
> 
> And made the exact point that you made :-)

Indeed. My apologies, I was trying to get through my email too fast and ended 
up skimming too much.

> > If we switched to `droppingPrefix(where:)` then we'd need to change 
> > `dropFirst(_:)` as well.
> 
> Yes, as I noted in my response to Erica, I would like to see some more design
> coherence in this whole area.  I think
> 
>   xs.dropFirst()  =>  xs.droppingFirst()
>   xs.dropFirst(3) => xs.droppingPrefix(ofMaxLength: 3)
> 
> I'm not wedded to “dropping,” especially because it has other
> connotations.  Dmitri, Max, and I kicked around a bunch of other
> possibilities, e.g.
> 
>   sansPrefix
>   withoutPrefix

If we do rename this, I'm partial to basing it off of the word "skip", e.g. 
skippingPrefix(), since that's similar to "drop" but doesn't have the 
connotation of possibly mutating the receiver. That said, having a first 
argument label "ofMaxLength:" seems overly verbose. Don't forget that not 
everybody has the benefit of Xcode code completion when writing Swift code.

> Anyway, we can't do all of that by the seat of our pants.  I personally
> wouldn't want to go any further than s.dropPrefix(where: ...)  without a
> new proposal/review.

Agreed, anything beyond that needs a full review. So back to the suggestion at 
hand.

I wrote up a whole long explanation for why I still think "while" is the better 
choice, and then I thought about how this impacts `prefix(...:)` instead of 
`drop(...:)`, and in this context "where:" makes more sense. `prefix(while:)` 
turns "prefix" from a noun into a verb, and the verb meaning of "prefix" is not 
at all what we're doing with this operation. But `prefix(where:)` is still a 
noun and makes sense. And of course if we have `prefix(where:)` then it's a bit 
odd to have `drop(while:)`, so we'd have to go with `drop(where:)` or 
`dropPrefix(where:)`. So I guess I've now convinced myself while writing this 
email that "where:" is the right choice :D

That said, given that we already have `dropFirst(_:)`, maybe we should go with 
`dropFirst(where:)` instead of `dropPrefix(where:)`? Otherwise it's a bit odd 
to have both "dropFirst" and "dropPrefix" as names. Admittedly, this same 
argument applies to the existing `drop(while:)` name too, and I don't have a 
great explanation for that beyond the fact that I had a vague idea that 
dropFirst(_:) might be renamed to drop(first:), though that can't actually 
happen because having both dropFirst() and drop(first:) is hugely confusing, 
and it doesn't make sense to rename dropFirst() to drop().

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


Re: [swift-evolution] [Accepted with modifications] SE-0045: Add scan, prefix(while:), drop(while:), and unfold to the stdlib

2016-05-06 Thread Kevin Ballard via swift-evolution
On Fri, May 6, 2016, at 05:31 PM, Kevin Ballard wrote:
> On Fri, May 6, 2016, at 05:19 PM, Dave Abrahams via swift-evolution wrote:
> > 
> > on Wed May 04 2016, Chris Lattner  wrote:
> > 
> > > Proposal link: 
> > > https://github.com/apple/swift-evolution/blob/master/proposals/0045-scan-takewhile-dropwhile.md
> > >
> > > Hello Swift Community,
> > >
> > > The review of SE-0045: "Add scan, prefix(while:), drop(while:), and
> > > unfold to the stdlib" ran from April 28...May 3, 2016. A subset of the
> > > proposal is *accepted, with modifications* for Swift 3.  This proposal
> > > included four new additions to the standard library:
> > >
> > > Sequence.prefix(while:) & Sequence.drop(while:) - These are *accepted* as 
> > > specified in revision 3 of the proposal.
> > 
> > I know the review is over and all, but…
> > 
> > Chris brought to my attention an idea that I liked, and asked me to post
> > here about it.  Specifically, the argument label “where:” would probably
> > be better than “while:”.  “While” makes it sound to me like it's going
> > to take a nullary predicate and be much more active.  But it's hard to
> > love
> > 
> >  s.drop(where: { $0 > 1 })
> >  s.drop { $0 > 1 }
> > 
> > because it makes it sound like a general filtering operation.
> > 
> > Therefore, I'd much rather see
> > 
> >s.droppingPrefix(where: {$0 > 1})
> 
> Using "where:" has a very high potential for confusion, because "where" makes 
> it sound like it runs the predicate against every single element, whereas 
> "while" makes it clear that it stops evaluating elements once the predicate 
> returns false. Or in other words, `drop(where: predicate)` looks like it 
> should be equivalent to `filter({ !predicate($0) })`.

Oops, I read your message too fast and missed the fact that you changed the 
function name too in the very last line.

If we switched to `droppingPrefix(where:)` then we'd need to change 
`dropFirst(_:)` as well.

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


Re: [swift-evolution] [Accepted with modifications] SE-0045: Add scan, prefix(while:), drop(while:), and unfold to the stdlib

2016-05-06 Thread Kevin Ballard via swift-evolution
On Fri, May 6, 2016, at 05:19 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Wed May 04 2016, Chris Lattner  wrote:
> 
> > Proposal link: 
> > https://github.com/apple/swift-evolution/blob/master/proposals/0045-scan-takewhile-dropwhile.md
> >
> > Hello Swift Community,
> >
> > The review of SE-0045: "Add scan, prefix(while:), drop(while:), and
> > unfold to the stdlib" ran from April 28...May 3, 2016. A subset of the
> > proposal is *accepted, with modifications* for Swift 3.  This proposal
> > included four new additions to the standard library:
> >
> > Sequence.prefix(while:) & Sequence.drop(while:) - These are *accepted* as 
> > specified in revision 3 of the proposal.
> 
> I know the review is over and all, but…
> 
> Chris brought to my attention an idea that I liked, and asked me to post
> here about it.  Specifically, the argument label “where:” would probably
> be better than “while:”.  “While” makes it sound to me like it's going
> to take a nullary predicate and be much more active.  But it's hard to
> love
> 
>  s.drop(where: { $0 > 1 })
>  s.drop { $0 > 1 }
> 
> because it makes it sound like a general filtering operation.
> 
> Therefore, I'd much rather see
> 
>s.droppingPrefix(where: {$0 > 1})

Using "where:" has a very high potential for confusion, because "where" makes 
it sound like it runs the predicate against every single element, whereas 
"while" makes it clear that it stops evaluating elements once the predicate 
returns false. Or in other words, `drop(where: predicate)` looks like it should 
be equivalent to `filter({ !predicate($0) })`.

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


Re: [swift-evolution] [Accepted with modifications] SE-0045: Add scan, prefix(while:), drop(while:), and unfold to the stdlib

2016-05-06 Thread Kevin Ballard via swift-evolution
On Fri, May 6, 2016, at 02:23 PM, Dave Abrahams via swift-evolution wrote:
> 
> on Fri May 06 2016, Kevin Ballard  wrote:
> 
> > One idea that came out of the core team discussion was something like:
> >
> > sequence(from: 0) { $0 += 42 }
> >
> > Since it returns a sequence.
> >
> > It just occurred to me that, if we follow existing naming conventions, this
> > function would end up returning a value of type SequenceSequence .
> 
> Why do you think so?

A random sampling of functions that generate non-Array sequences and their 
corresponding sequence type:

* Sequence.flatten() -> FlattenSequence
* Sequence.joined() -> JoinedSequence
* LazySequenceProtocol.map() -> LazyMapSequence
* LazySequenceProtocol.filter() -> LazyFilterSequence

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


Re: [swift-evolution] [Accepted with modifications] SE-0045: Add scan, prefix(while:), drop(while:), and unfold to the stdlib

2016-05-06 Thread Kevin Ballard via swift-evolution
On Thu, May 5, 2016, at 01:39 PM, Chris Lattner via swift-evolution wrote:
>
>> On May 5, 2016, at 1:03 PM, Erica Sadun  wrote:
>>
>> On May 4, 2016, at 5:50 PM, Chris Lattner via swift-evolution > evolut...@swift.org> wrote:
>>>
>>> Proposal link:
>>> https://github.com/apple/swift-evolution/blob/master/proposals/0045-scan-takewhile-dropwhile.md
>>>
>>> Sequence.prefix(while:) & Sequence.drop(while:) - These are
>>> *accepted* as specified in revision 3 of the proposal.
>>
>> I'm still a little sad we didn't go for `prefix`/`suffix` or
>> `take`/`drop` pairs that linguistically matched.Nonetheless I'm
>> gratified these are hopping into the language. That said, I'm going
>> to put on my painters cap to consider selecting some exterior latex
>> for the feature I was most looking forward to in this proposal:
>>
>> Core team writes:
>>> unfold(_:applying:) - This addition is *rejected* by the core team
>>> as written, but deserves more discussion in the community, and
>>> potentially could be the subject of a future proposal.  The core
>>> team felt that the utility of this operation is high enough to be
>>> worth including in the standard library, but could not find an
>>> acceptable name for it.  “unfold” is problematic, despite its
>>> precedence in other language, because Swift calls the corresponding
>>> operation “reduce” and not “fold”.  No one could get excited about
>>> “unreduce”.   “iterate” was also considered, but a noun is more
>>> appropriate than an verb in this case.  Given the lack of a good
>>> name, the core team preferred to reject *_to let the community
>>> discuss it more_*.
>>
>> A few thoughts:
>>
>> * I'm not sure why a noun is more appropriate than a verb. Reduce
>>   isn't a noun, prefix isn't a noun, drop isn't a noun.
>
> I’m not a naming guru, but my understanding is that ‘reduce’ was
> picked because it was term of art (like map), which is what allowed
> the misuse of a verb.
>
> One idea that came out of the core team discussion was something like:
>
> sequence(from: 0) { $0 += 42 }
>
> Since it returns a sequence.
 
It just occurred to me that, if we follow existing naming conventions,
this function would end up returning a value of type SequenceSequence .
 
-Kevin
 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-evolution-announce] [Review] SE-0017: Change Unmanaged to use UnsafePointer

2016-05-03 Thread Kevin Ballard via swift-evolution
On Thu, Apr 28, 2016, at 11:10 AM, Chris Lattner wrote:
> Hello Swift community,
> 
> The review of "SE-0017: Change Unmanaged to use UnsafePointer" begins now and 
> runs through May 3. The proposal is available here:
> 
>   
> https://github.com/apple/swift-evolution/blob/master/proposals/0017-convert-unmanaged-to-use-unsafepointer.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?

+1

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

Yes. Going through COpaquePointer is quite annoying when dealing with Unmanaged 
and C context pointers.

>   * 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?

A quick reading, and I've hit this pain point in my own code before.

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


Re: [swift-evolution] [Review] SE-0052: Change IteratorType post-nil guarantee

2016-05-03 Thread Kevin Ballard via swift-evolution
On Thu, Apr 28, 2016, at 11:12 AM, Chris Lattner via swift-evolution wrote:
> Hello Swift community,
> 
> The review of "SE-0052: Change IteratorType post-nil guarantee" begins now 
> and runs through May 3. The proposal is available here:
> 
>   
> https://github.com/apple/swift-evolution/blob/master/proposals/0052-iterator-post-nil-guarantee.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?

I was originally strongly -1 on this (as can be seen from my previous messages 
on this ML about this topic), both for the reasons that Gwendal Roué wrote as 
well as my belief that the vast majority of users never even write code that 
hits this case at all and my own experience in that it's actually more common 
for me as an author of a custom Iterator to have to worry about meeting this 
guarantee than it is for anyone using my Iterator to rely on the behavior.

However, if there really is a 25% speedup on UTF-8 decoding for ASCII input, 
that's a pretty significant point in favor of the change. I saw the gist that 
was used to come up with this 25% number. But I do have to ask, does the 25% 
increase still hold when talking about String.UTF8View, or is that significant 
speedup only shown when using the UTF8 type to transcode? And similarly, what's 
the effect on performance for non-ASCII input?

Similarly, do we have any numbers for the effect on performance for a custom 
Iterator that now has to track state which it otherwise wouldn't? 
TakeWhileIterator would be a good candidate for testing, except it hasn't been 
implemented yet (though it shouldn't be hard to whip up a sample implementation 
for that).

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

Yes. The current defined behavior is pretty much the worst of all options since 
it encourages library authors to deliberately crash, and yet no stdlib type 
actually does crash, so it makes it easy to write code that works for stdlib 
iterators but will fail when given a third-party iterator.

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

Yes.

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

Rust's equivalent Iterator type is defined such that after a previous call to 
next() has returned None, Iterators are allowed to return either None or 
Some(Item) from subsequent calls to next() (but shouldn't crash). And Rust has 
a FuseIterator (and a corresponding .fuse() method). This matches the first 
alternative in the proposal. And with this approach, it's true that it's 
extremely rare for people to call .fuse() (but this just demonstrates that very 
few people write code where post-nil behavior matters), but it does simplify 
many Iterator implementations, and AFAIK nobody's complained about this 
behavior.

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

An in-depth study.

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


Re: [swift-evolution] [Review] SE-0045: Add scan, prefix(while:), drop(while:), and iterate to the stdlib

2016-05-01 Thread Kevin Ballard via swift-evolution
On Sun, May 1, 2016, at 04:13 AM, Brent Royal-Gordon wrote:
> > The proposal has been updated as per feedback from the core team 
> > (https://github.com/apple/swift-evolution/pull/275). This includes removing 
> > some last vestiges of Swift 2 naming as well as replacing 
> > `iterate(_:apply:)` with an overloaded function `unfold(_:applying:)`.
> 
> The proposal says this:
> 
>   public func unfold(_ initialState: State, applying: State -> 
> (T, State)?) -> UnfoldSequence
>   public func unfold(_ initialElement: T, apply: T -> T) -> 
> UnfoldSequence
> 
> However, the comment implies that the second one should instead be this:
> 
>   public func unfold(_ initialElement: T, applying: T -> T?) -> 
> UnfoldSequence

Oops, you're right, that was a mistake.

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


  1   2   >