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

2016-12-08 Thread Alexis Beingessner via swift-evolution


> On Dec 8, 2016, at 3:50 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> on Thu Dec 08 2016, Ben Cohen  wrote:
> 
>>> On Dec 2, 2016, at 8:27 PM, Nate Cook  wrote:
>>> 
 On Dec 2, 2016, at 2:12 PM, Ben Cohen via swift-evolution
 >
 wrote:
>> 
 
> On Dec 1, 2016, at 11:33 PM, Nate Cook via swift-evolution
> >
> wrote:
> 
> 3) Make all buffer pointers their own slices but use a different
> index type. If the indices were just wrapped pointers, that would
> handle the index sharing without needing an additional property on
> the buffer. We could also maintain integer-based stridable
> conformance (which greatly simplifies index arithmetic), since the
> indices would just offset by a byte for raw buffers or a stride
> for typed buffers.
> 
 
 Unfortunately, switching to non-integer indices would change this
 from being mildly source-breaking to being extremely
 source-breaking, as there’s lots of code out there using buffers
 today indexing them with integers (including integer literals).
 
 The big win with UnsafeBufferPointer having an integer index is
 it’s a drop-in replacement for arrays, so when you hit a
 performance problem using an array you can quickly switch to using
 a buffer under most circumstances instead without having to change
 much of your code – including code that uses for i in
 0..>> 
>>> It is definitely very source-breaking, though with relatively simple fixits:
>>> 
>>>buf[0] ---> buf[buf.startIndex]
>>>buf[3] ---> buf[buf.startIndex + 3]
>>>buf[i] ---> buf[buf.startIndex + i]
>>> 
>>> Any integer arithmetic happening outside the subscript could be left
>>> unchanged. If that cost isn't worth the benefit, then making
>>> UnsafeRawBufferPointer use Slice as its slice type is probably the
>>> best way to resolve that issue.
>>> 
>>> Nate
>> 
>> The fixits aren’t quite that simple for slices, though:
>> 
>>let slice = buf[3..<6]
>>slice[3] —> slice[slice.startIndex + 0] // fixit would somehow need to 
>> know this is 0 not 3
>>slice[i] —> slice[slice.startIndex + ??] // or even need to
>> know this is, erm, I haven’t had enough coffee this morning
>> 
>> The other downside is it would thwart speculatively switching an Array
>> to an UnsafeBuffer to see if that was a bottleneck, then switching
>> back.
>> 
>>> On Dec 1, 2016, at 11:33 PM, Nate Cook via swift-evolution 
>>>  wrote:
>>> 
>>> 1) Switch to using Slice as a wrapper for UnsafeRawBufferPointer.
>>> 
>> 
>> Based on the above, it seems like this is the least bad option, and we
>> need to do this ASAP as currently UnsafeRawBufferPointer is
>> non-compliant with the requirements of slicing and needs changing
>> before it’s more widely adopted.
> 
> Or we could say that UnsafeRawBufferPointer isn't a Collection.  Making
> it a Collection in the first place has always seemed suspect to me.
> 

If this is considered a viable option, it's the one I want. Passing types 
without bounds checks into generic "safe" code shouldn't be this easy. You 
should need to explicitly wrap it up in something safe. And I really don't want 
the known-to-be-error-prone indexing model in concrete unsafe code.

> -- 
> -Dave
> ___
> 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 about renaming Optional.map to Optional.mapMe ?

2016-12-05 Thread Alexis Beingessner via swift-evolution
This same issue applies to an Array of Arrays, wherein there is no renaming 
solution. That is, you've built a Collection of Collection, and have mixed up 
the inner and outer collections. I expect in most cases you'll run into a type 
error when you try to use the result.

This is an unfortunate bug to have, but I don't think a change to a core type 
is worth making over it. The name has been discussed in the past, and it was 
deemed sufficiently desirable as to defy standard naming conventions (it should 
be called mapped by standard conventions).

> On Dec 5, 2016, at 11:48 PM, David Sweeris via swift-evolution 
>  wrote:
> 
> 
>> On Dec 5, 2016, at 7:46 PM, Jay Zhao via swift-evolution 
>>  wrote:
>> 
>> Hi there,
>> 
>> Code explains everything:
>> 
>>  
>> 
>> /// Maybe a bad API naming in Swift? See below:
>> 
>> /// array1 can be array of any object that have a `count` method
>> let array1 = [[String]]()
>> let array2 :[String]? = nil
>> 
>> 
>> // I believe the confusion between `array.map` and 
>> `optionalArray.map` is really bad.
>> // Because when you read code like this, you can not tell which is 
>> which:
>> _ = array1.map({$0.count})
>> _ = array2.map({$0.count})
>> 
>> // It can be clearer:
>> // 1, we pass `self.element` into the closure
>> _ = array1.map({$0.count})
>> // 2, we pass self directly into the closure
>> _ = array2.mapMe({$0.count})
>> 
>> 
>> The mapFlat method is also problematic.
> 
> It might be possible to convince me to support renaming map for optionals, 
> but not to mapMe. As it is, you’ll have the same problem with anything having 
> a map function where the element(s) also have a map function. Sets of arrays, 
> arrays of dictionaries, etc. 
> 
> - Dave Sweeris
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [swift-build-dev] Proposal: Package Manager Version Pinning

2016-10-14 Thread Alexis Beingessner via swift-evolution


> On Oct 14, 2016, at 8:00 PM, Paul Cantrell  wrote:
> 
> 
>>> On Oct 14, 2016, at 6:42 PM, Daniel Dunbar  wrote:
>>> 
>>> On Oct 14, 2016, at 4:02 PM, Paul Cantrell  wrote:
>>> 
>>> I’m puzzled. If a package’s pinning does not affect any other package that 
>>> uses it, why should the defaults be different? A library will still suffer 
>>> from all the “works for me” problems an app might.
>>> 
>>> Is the rationale that not pinning libraries encourages accidental testing 
>>> of new versions of a library’s dependencies as they arrive? Or is there 
>>> another rationale for having different defaults?
>> 
>> I'll defer to this comment (linked from someone else earlier in the thread), 
>> which happens to match up with my perspective:
>> https://github.com/yarnpkg/yarn/issues/838#issuecomment-253362537
> 
> I took that comment to be an explanation of why a library's lockfile/pinfile 
> should not propagate to other packages that use it. That is clearly the case; 
> such pin propagation would be nonsensical.
> 
> My question was not about that, but about why libraries shouldn’t use a 
> pinfile at all, even for their own _internal_ development. All the same “last 
> know good build” concerns apply.
> 
> The difference is that testing against that single last known good version 
> set is sufficient for a top-level package, whereas a library should (1) 
> ideally test against multiple valid dependency versions and (2) test often 
> against new versions of its dependencies. I don’t see, however, that this 
> implies that libraries should not have pinfiles at all — just that their 
> release / CI process should not be limited to what’s pinned.

A few comments down, Yehuda even provides an example of him doing just that 
with Bundler:

https://github.com/yarnpkg/yarn/issues/838#issuecomment-253366352

But in this case you actually want to maintain *many* lock files, and so it 
seems fine to require a bit of extra work (passing some flags) to do this. 
Drifting tests are the better default here. It makes library CI into an 
alpha-tester, empowering binaries to be more confident in upgrading frequently.

> 
> Cheers, P
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] PITCH: New :== operator for generic constraints

2016-08-18 Thread Alexis Beingessner via swift-evolution

Slava and Joe's suggestion of self conformance and the constraints involved are 
something that's been explored in other languages with similar systems. There's 
a great series of posts discussing some of the issues at hand:

These describe the constraints of interest (“object safety”):
http://huonw.github.io/blog/2015/01/object-safety/
http://huonw.github.io/blog/2015/05/where-self-meets-sized-revisiting-object-safety/

These are in the context of the Rust language, whose traits are similar in many 
ways to Swift protocols. These posts should give enough background to those 
familiar with protocols but not traits:
http://huonw.github.io/blog/2015/01/peeking-inside-trait-objects/
http://huonw.github.io/blog/2015/01/the-sized-trait/

One idea presented here that's applicable to Swift is the ability to 
distinguish between “static type” and “dynamic type” via the Sized trait (Sized 
referring to "statically sized"). By default most locations that work with 
generics implicitly assume Sized, which leads to more efficient code, and 
allows things like:

let x = T.staticMethod()

to make sense. However, if a piece of code isn’t interested in these 
capabilities, it can add ?Sized to the type constraint to “remove” the 
assumption, constraining the body of the method. Let’s call `?Sized` in Swift 
`MaybeExistential` (because that’s what it would mean). So you would write 
something like:

func foo(input: T) { … }

and the effect would be that MyProto existentials could be passed to this 
function in the knowledge that the function would be forbidden from calling 
static initializers and any other problematic methods. This isn’t a totally 
unprecedented strategy in Swift either: this is the same kind of idea behind 
`@noescape`; constraining the user of the generic type to empower the provider.

> On Aug 17, 2016, at 12:42 AM, Slava Pestov via swift-evolution 
>  wrote:
> 
> 
>>> On Aug 16, 2016, at 8:52 PM, Charles Srstka  
>>> wrote:
>>> 
>>> On Aug 16, 2016, at 8:51 PM, Slava Pestov  wrote:
>>> 
>>> Here is why we must have that requirement. Consider the following code:
>>> 
>>> protocol P {
>>>   init()
>>> }
>>> 
>>> struct A : P {
>>>   init() {}
>>> }
>>> 
>>> struct B : P {
>>>   init() {}
>>> }
>>> 
>>> func makeIt() -> T {
>>>   return T()
>>> }
>>> 
>>> I can use this function as follows:
>>> 
>>> let a: A = makeIt() // Creates a new ‘A'
>>> let a: B = makeIt() // Creates a new ‘B’
>>> 
>>> Now suppose we allow P to self-conform. Then the following becomes valid:
>>> 
>>> let p: P = makeIt()
>>> 
>>> What exactly would makeIt() do in this case? There’s no concrete type 
>>> passed in, or any way of getting one, so there’s nothing to construct. The 
>>> same issue would come up with static methods here.
>> 
>> Argh, that’s particularly frustrating since in something like ‘func foo> P>(t: T)’ or ‘func foo(s: S) where S.IteratorElement: P’, 
>> you’re only ever getting instances anyway since the parameter is in the 
>> input, so calling initializers or static functions isn’t something you can 
>> even do (unless you call .dynamicType, at which point you *do* have a 
>> concrete type at runtime thanks to the dynamic check).
> 
> Well, if you have ‘func foo(t: T)’, then you can write 
> T.someStaticMember() to call static members — it’s true you also have an 
> instance ’t’, but you can also work directly with the type. But I suspect 
> this is not what you meant, because:
> 
>> 
>> I wish there were a way to have partial conformance in cases like these. 
>> Like how this causes what’s probably Swift’s most confusing compiler error 
>> (certainly one of its most asked about):
>> 
>> protocol P: Equatable {
>> static func ==(l: Self, r: Self) -> Bool
>> 
>> func foo()
>> }
>> 
>> struct S: P {
>> static func ==(l: S, r: S) -> Bool {
>> return true
>> }
>> 
>> func foo() {
>> print("foo")
>> }
>> }
>> 
>> let s = S()
>> let p = s as P // error: Protocol ‘P’ can only be used as a generic 
>> constraint because it has Self or associated type requirements
> 
> Yep :) So the property of ‘can be used as an existential type’ is actually a 
> bit different from ‘protocol conforms to itself’. The rules here are:
> 
> - Self must not appear in contravariant position
> - Protocol has no associated types
> 
> Note that static members and initializers are OK, and you can call them via 
> ‘p.dynamicType.foo()’ where p : P.
> 
>> 
>> It would make using protocols so much less teeth-grinding if the compiler 
>> *did* allow you to type the variable as P, but then would just throw an 
>> error if you tried to call one of the “problem” methods (in this case, using 
>> the ‘==' operator would be an error, but calling ‘foo’ would be fine). If 
>> this were possible, the conformance for a variable typed P would just not 
>> pick up “illegal” things like initializers, and would also leave out 
>> conformance