Re: [swift-evolution] [Proposal] Type Narrowing

2016-11-06 Thread Jean-Daniel via swift-evolution

> Le 7 nov. 2016 à 04:52, Chris Lattner via swift-evolution 
>  a écrit :
> 
> 
>> On Nov 3, 2016, at 10:04 AM, Haravikk via swift-evolution 
>>  wrote:
>> 
>> To avoid hijacking the guard let x = x thread entirely I've decided to try 
>> to write up a proposal on type narrowing in Swift.
>> Please give your feedback on the functionality proposed, as well as the 
>> clarity of the proposal/examples themselves; I've tried to keep it 
>> straightforward, but I do tend towards being overly verbose, I've always 
>> tried to have the examples build upon one another to show how it all stacks 
>> up.
> 
> FWIW, we have specifically considered something like this proposal in the 
> past.  You didn’t mention it, but the ?: operator is a specific example that 
> frequently comes up.  People often expect to be able to do something like:
> 
>   … = foo is B ? foo.bMethod() : …
> 

For the case of the ?: operator, I think it can be replaced by a ?? operator 
for most cases:

… = (foo as B)?.bMethod() ?? …


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


Re: [swift-evolution] Contiguous Memory and the Effect of Borrowing on Safety

2016-11-06 Thread Hooman Mehr via swift-evolution

> On Nov 6, 2016, at 8:03 PM, Dave Abrahams via swift-evolution 
>  wrote:
>> I had a brush with Julia > as 
>> well. Have you
>> looked at their work 
> 
> It's been a while, to be honest.
> 
>> and the recent reworking of their similar data structures?
> 
> Links would be appreciated.

Start with this blog post, if you haven’t already seen it: 
http://julialang.org/blog/2016/03/arrays-iteration

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


Re: [swift-evolution] Contiguous Memory and the Effect of Borrowing on Safety

2016-11-06 Thread Dave Abrahams via swift-evolution

on Sun Nov 06 2016, Hooman Mehr  wrote:

> Yes, this is a very important issue to consider before we freeze them.
>
> As part of my Swift hobby, I have worked a bit on a Swifty wrapper for
> linear algebra packages 

That domain makes an excellent test case.

> and also toyed a bit with the merits of a Swift implementation of some
> of the related algorithms and data structures (such as banded or
> sparse matrices)
>
> It is really difficult to come up with efficient and generic solutions
> in these spaces.

I'm not surprised.  The generics system in Swift has a lot of growing up
to do, and until it does that, it's hard to even contemplate the library
abstractions that will be needed.

> I had a brush with Julia  as well. Have you
> looked at their work 

It's been a while, to be honest.

> and the recent reworking of their similar data structures?

Links would be appreciated.

>> On Nov 6, 2016, at 1:20 PM, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> 
>> Given that we're headed for ABI (and thus stdlib API) stability, I've
>> been giving lots of thought to the bottom layer of our collection
>> abstraction and how it may limit our potential for efficiency.  In
>> particular, I want to keep the door open for optimizations that work on
>> contiguous memory regions.  Every cache-friendly data structure, even if
>> it is not an array, contains contiguous memory regions over which
>> operations can often be vectorized, that should define boundaries for
>> parallelism, etc.  Throughout Cocoa you can find patterns designed to
>> exploit this fact when possible (NSFastEnumeration).  Posix I/O bottoms
>> out in readv/writev, and MPI datatypes essentially boil down to
>> identifying the contiguous parts of data structures.  My point is that
>> this is an important class of optimization, with numerous real-world
>> examples.
>> 
>> If you think about what it means to build APIs for contiguous memory
>> into abstractions like Sequence or Collection, at least without
>> penalizing the lowest-level code, it means exposing UnsafeBufferPointers
>> as a first-class part of the protocols, which is really
>> unappealing... unless you consider that *borrowed* UnsafeBufferPointers
>> can be made safe.  
>> 
>> [Well, it's slightly more complicated than that because
>> UnsafeBufferPointer is designed to bypass bounds checking in release
>> builds, and to ensure safety you'd need a BoundsCheckedBuffer—or
>> something—that checks bounds unconditionally... but] the point remains
>> that
>> 
>>  A thing that is unsafe when it's arbitrarily copied can become safe if
>>  you ensure that it's only borrowed (in accordance with well-understood
>>  lifetime rules).
>> 
>> And this leads me to wonder about our practice of embedding the word
>> "unsafe" in names.  A construct that is only conditionally unsafe
>> shouldn't be spelled "unsafe" when used in a safe way, right?  So this
>> *seems* to argue for an "unsafe" keyword that can be used to label
>> the constructs that actually add unsafety (as has been previously
>> suggested on this list).  Other ideas are of course most welcome.
>> 
>> -- 
>> -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
>

-- 
-Dave

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


Re: [swift-evolution] [Proposal] Type Narrowing

2016-11-06 Thread Chris Lattner via swift-evolution

> On Nov 3, 2016, at 10:04 AM, Haravikk via swift-evolution 
>  wrote:
> 
> To avoid hijacking the guard let x = x thread entirely I've decided to try to 
> write up a proposal on type narrowing in Swift.
> Please give your feedback on the functionality proposed, as well as the 
> clarity of the proposal/examples themselves; I've tried to keep it 
> straightforward, but I do tend towards being overly verbose, I've always 
> tried to have the examples build upon one another to show how it all stacks 
> up.

FWIW, we have specifically considered something like this proposal in the past. 
 You didn’t mention it, but the ?: operator is a specific example that 
frequently comes up.  People often expect to be able to do something like:

… = foo is B ? foo.bMethod() : …

which is the same sort of flow sensitive type refinement as you’re proposing 
here.  This topic also came up in the design discussion around #available 
(which shipped in Swift 2, but was discussed much earlier), because unavailable 
decls could be available as optionals when not specifically checked for.

This is just MHO, but while I have been in favor of this in the (distant) past, 
I became convinced that this would be a bad idea when it comes to code 
maintenance over the long term.  With our current (intentional shadowing based) 
design, you can always jump to the definition of a value to see where it was 
defined, and definitions always specify a type.  Introducing flow senstitive 
type refinement breaks this model because the type of a decl depends not just 
on its declaration, but on a potentially arbitrary number of imperative checks 
that occur between the declaration and the use.  This can make it much more 
difficult to understand code.

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


Re: [swift-evolution] Contiguous Memory and the Effect of Borrowing on Safety

2016-11-06 Thread Hooman Mehr via swift-evolution
Yes, this is a very important issue to consider before we freeze them.

As part of my Swift hobby, I have worked a bit on a Swifty wrapper for linear 
algebra packages and also toyed a bit with the merits of a Swift implementation 
of some of the related algorithms and data structures (such as banded or sparse 
matrices)

It is really difficult to come up with efficient and generic solutions in these 
spaces. I had a brush with Julia  as well. Have you 
looked at their work and the recent reworking of their similar data structures?

> On Nov 6, 2016, at 1:20 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> 
> Given that we're headed for ABI (and thus stdlib API) stability, I've
> been giving lots of thought to the bottom layer of our collection
> abstraction and how it may limit our potential for efficiency.  In
> particular, I want to keep the door open for optimizations that work on
> contiguous memory regions.  Every cache-friendly data structure, even if
> it is not an array, contains contiguous memory regions over which
> operations can often be vectorized, that should define boundaries for
> parallelism, etc.  Throughout Cocoa you can find patterns designed to
> exploit this fact when possible (NSFastEnumeration).  Posix I/O bottoms
> out in readv/writev, and MPI datatypes essentially boil down to
> identifying the contiguous parts of data structures.  My point is that
> this is an important class of optimization, with numerous real-world
> examples.
> 
> If you think about what it means to build APIs for contiguous memory
> into abstractions like Sequence or Collection, at least without
> penalizing the lowest-level code, it means exposing UnsafeBufferPointers
> as a first-class part of the protocols, which is really
> unappealing... unless you consider that *borrowed* UnsafeBufferPointers
> can be made safe.  
> 
> [Well, it's slightly more complicated than that because
> UnsafeBufferPointer is designed to bypass bounds checking in release
> builds, and to ensure safety you'd need a BoundsCheckedBuffer—or
> something—that checks bounds unconditionally... but] the point remains
> that
> 
>  A thing that is unsafe when it's arbitrarily copied can become safe if
>  you ensure that it's only borrowed (in accordance with well-understood
>  lifetime rules).
> 
> And this leads me to wonder about our practice of embedding the word
> "unsafe" in names.  A construct that is only conditionally unsafe
> shouldn't be spelled "unsafe" when used in a safe way, right?  So this
> *seems* to argue for an "unsafe" keyword that can be used to label
> the constructs that actually add unsafety (as has been previously
> suggested on this list).  Other ideas are of course most welcome.
> 
> -- 
> -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] Contiguous Memory and the Effect of Borrowing on Safety

2016-11-06 Thread Dave Abrahams via swift-evolution

on Sun Nov 06 2016, Daniel Duan  wrote:

>> On Nov 6, 2016, at 1:20 PM, Dave Abrahams via swift-evolution
>>  wrote:
>> 
>> A construct that is only conditionally unsafe
>> shouldn't be spelled "unsafe" when used in a safe way, right?  So this
>> *seems* to argue for an "unsafe" keyword that can be used to label
>> the constructs that actually add unsafety (as has been previously
>> suggested on this list).  Other ideas are of course most welcome.
>> 
>
> How would “unsafe” coexist with memory ownership model? It seems to me
> that there’s some overlapping concepts here (borrowed/moved). 

Yes, the ownership model covers borrowing.

> I haven’t formulated any complete thoughts on this topic. Just had a
> feeling that we should take the ownership model in mind as we tackle
> this.

That was a main point of my posting.  Apologies if that wasn't made
clear.

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


Re: [swift-evolution] Contiguous Memory and the Effect of Borrowing on Safety

2016-11-06 Thread Daniel Duan via swift-evolution

> On Nov 6, 2016, at 1:20 PM, Dave Abrahams via swift-evolution 
>  wrote:
> 
> A construct that is only conditionally unsafe
> shouldn't be spelled "unsafe" when used in a safe way, right?  So this
> *seems* to argue for an "unsafe" keyword that can be used to label
> the constructs that actually add unsafety (as has been previously
> suggested on this list).  Other ideas are of course most welcome.
> 

How would “unsafe” coexist with memory ownership model? It seems to me that 
there’s some overlapping concepts here (borrowed/moved). I haven’t formulated 
any complete thoughts on this topic. Just had a feeling that we should take the 
ownership model in mind as we tackle this.

> -- 
> -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] [Proposal] Type Narrowing

2016-11-06 Thread Haravikk via swift-evolution

> On 3 Nov 2016, at 22:56, Nevin Brackett-Rozinsky 
>  wrote:
> 
> Okay, I think I found an actual shortcoming that type narrowing might 
> address, namely mutating a property in place if it is a subtype. Here is a 
> small example setup:
> 
> protocol A { var x: Int {get} }
> struct B: A { var x: Int }
> struct C { var a: A }
> var c = C(a: B(x: 4))
> 
> Note that “A” does not promise the “x” property will be mutable, while B 
> does. I use “x: Int” as a minimal example, but any solution should also work 
> for more complex scenarios.
> 
> Now suppose we wish to test whether “c.a” is of type B, and if so change its 
> “x” value. We could, of course, make a local copy, mutate it, and reassign to 
> “c.a”. But if those operations are expensive we would rather avoid doing so. 
> And if B uses copy-on-write, we would want to remove the value from “c” 
> entirely so that we hopefully have a unique reference. This is hard to get 
> right.
> 
> We would prefer to write something like the following:
> 
> (c.a as? B)?.x = 12
> 
> But that does not currently work, resulting in the error “Cannot assign to 
> immutable expression of type 'Int'”.
> 
> Will the proposed type-narrowing feature provide a simple way to mutate “c.a” 
> in place, contingent upon its being of type B?
> How does it compare to an alternative such as inout return values, which 
> could preserve mutability in the above?

That's a good example, and yes it should be possible for type-narrowing to 
simplify stuff like this, I'll add a section on that I should probably go into 
more detail on how I intend working with narrowed mutable values to work, as 
for the advantage vs inout it's really just a matter of simplicity I think; 
using type narrowing should allow it to just work without having to pass to 
methods or design the API specifically for that kind of thing.



> If we are going to have any sort of type narrowing, I would strongly prefer 
> that it be explicit. For example we could use a keyword such as “rebind” to 
> narrow the type of an existing symbol in a scope:
> 
> if rebind c.a as B {
> c.a.x = 12
> }

I don't see what's really gained by making it explicit vs implicit; if the 
condition was c.a is B then I'm not sure how that's any less clear?

> Furthermore, I think the proposal to treat enum cases as types is a major 
> change to Swift’s type system, and probably introduces many unforeseen 
> headaches. It also smells somewhat of a backdoor way for union types to sneak 
> into the language.

I'd say that in a sense enums are types, after all they can have unique 
associated value types of their own. Really though my intent is primarily to 
support optionals, but I figure it makes sense to try and do it from the 
perspective of general purpose enums since that's all optionals really are 
anyway.


Also, I've been thinking about thread safety and it occurs to me that type 
narrowing could actually be of significant benefit to it, rather than a 
detriment.

Consider:

struct Foo { var value:Int }
struct Bar { var foo?:Foo }

var a = Foo(value: 5)
var b = Bar(foo: a)

b.foo.value = 10

Now, in this case we're only dealing with structs, and we know that b.foo has a 
value, thus b.foo.value is nice and safe; in fact no force unwrapping needs to 
occur behind the scenes, it can optimise away completely.

Instead, let's assume Bar is a class we're handling in a potentially shared way:

class Bar { var foo?:Foo }

func myMethod(bar:Bar) {
b.foo = new Foo(5) // We now know that b.foo shouldn't be nil
b.foo!.value = 10
}

In this case, since Bar is a class we don't have total control over, we can't 
be certain that b.foo is non-nil when we try to modify it a second time; as a 
result, type-narrowing won't occur (because it's a class from another scope), 
however, because the type-checker knows that bar.foo should have a value, we 
can actually issue a more informative error message if force unwrapping fails, 
e.g- concurrent modification error.

In other words, we can potentially use it to help detect concurrency issues. 
It's another thing that's going to require a section on the proposal though, I 
have a feeling it's going to get pretty big!___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution