Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-10 Thread David Hart via swift-evolution


> On 9 Jun 2017, at 19:06, Max Moiseev via swift-evolution 
>  wrote:
> 
> Sorry. I might be missing something. Why is this better than:
> 
> let allEmployees = Set(managers.flatMap { $0.directReports }
> 
> ?

For the same reasons

managers.flatMap(calculateReports(_:))

Is better than:

managers.flatMap { calculateReports($0) }

Quite a few people enjoy this tearse, functional style.

>> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
>>  wrote:
>> 
>> The new smart key path feature is really lovely, and feels like a great 
>> addition to Swift.
>> 
>> It seems like it might be straightforward to add overloads of `map` and 
>> `flatMap` to the standard library to make use of the new functionality:
>> 
>>let managers = flatOrganisation.managers
>>let allEmployees = Set(managers.flatMap(\.directReports))
>>let employeeNames = Set(allEmployees.map(\.name))
>> 
>> This feels like a really natural way of working with key paths in a 
>> functional style. It makes a lot of sense for collections, and possibly for 
>> Optional too (although as far as I can see optional chaining is more or less 
>> equivalent, and with more compact syntax).
>> 
>> I’m hoping that this might be low-hanging fruit that could be considered for 
>> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
>> there’s interest!
>> 
>> –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] Pitch: Support for map and flatMap with smart key paths

2017-06-09 Thread Dave Abrahams via swift-evolution

on Fri Jun 09 2017, Saagar Jha  wrote:

> It reads better and feels more natural. In my mind, it’s similar to the 
> difference between 
>
> ["1", "2", "3"].flatMap { Double($0) }
>
> and
>
> ["1", "2", "3"].flatMap(Double.init)
>
> Saagar Jha

I am not convinced this syntactic sugar is worth complicating the
language or library for, but if it is, IMO the right thing is to make a
keypath be-a subtype of the appropriate function type, rather than to
start down the path of creating a keypath overload for every method that
takes a closure argument.

>
>> On Jun 9, 2017, at 16:06, Max Moiseev via swift-evolution 
>>  wrote:
>> 
>> Sorry. I might be missing something. Why is this better than:
>> 
>> let allEmployees = Set(managers.flatMap { $0.directReports }
>> 
>> ?
>> 
>>> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution
>>>  wrote:
>>> 
>>> The new smart key path feature is really lovely, and feels like a great 
>>> addition to Swift.
>>> 
>>> It seems like it might be straightforward to add overloads of `map`
>>> and `flatMap` to the standard library to make use of the new
>>> functionality:
>>> 
>>> let managers = flatOrganisation.managers
>>> let allEmployees = Set(managers.flatMap(\.directReports))
>>> let employeeNames = Set(allEmployees.map(\.name))
>>> 
>>> This feels like a really natural way of working with key paths in a
>>> functional style. It makes a lot of sense for collections, and
>>> possibly for Optional too (although as far as I can see optional
>>> chaining is more or less equivalent, and with more compact syntax).
>>> 
>>> I’m hoping that this might be low-hanging fruit that could be
>>> considered for the Swift 4 release. I’d be happy to have a go at
>>> writing a proposal if there’s interest!
>>> 
>>> –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
>

-- 
-Dave

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


Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-09 Thread Saagar Jha via swift-evolution
It reads better and feels more natural. In my mind, it’s similar to the 
difference between 

["1", "2", "3"].flatMap { Double($0) }

and

["1", "2", "3"].flatMap(Double.init)

Saagar Jha

> On Jun 9, 2017, at 16:06, Max Moiseev via swift-evolution 
>  wrote:
> 
> Sorry. I might be missing something. Why is this better than:
> 
> let allEmployees = Set(managers.flatMap { $0.directReports }
> 
> ?
> 
>> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
>>  wrote:
>> 
>> The new smart key path feature is really lovely, and feels like a great 
>> addition to Swift.
>> 
>> It seems like it might be straightforward to add overloads of `map` and 
>> `flatMap` to the standard library to make use of the new functionality:
>> 
>>  let managers = flatOrganisation.managers
>>  let allEmployees = Set(managers.flatMap(\.directReports))
>>  let employeeNames = Set(allEmployees.map(\.name))
>> 
>> This feels like a really natural way of working with key paths in a 
>> functional style. It makes a lot of sense for collections, and possibly for 
>> Optional too (although as far as I can see optional chaining is more or less 
>> equivalent, and with more compact syntax).
>> 
>> I’m hoping that this might be low-hanging fruit that could be considered for 
>> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
>> there’s interest!
>> 
>> –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] Pitch: Support for map and flatMap with smart key paths

2017-06-09 Thread Karl Wagner via swift-evolution

> On 7. Jun 2017, at 19:35, Adam Sharp via swift-evolution 
>  wrote:
> 
> The new smart key path feature is really lovely, and feels like a great 
> addition to Swift.
> 
> It seems like it might be straightforward to add overloads of `map` and 
> `flatMap` to the standard library to make use of the new functionality:
> 
>   let managers = flatOrganisation.managers
>   let allEmployees = Set(managers.flatMap(\.directReports))
>   let employeeNames = Set(allEmployees.map(\.name))
> 
> This feels like a really natural way of working with key paths in a 
> functional style. It makes a lot of sense for collections, and possibly for 
> Optional too (although as far as I can see optional chaining is more or less 
> equivalent, and with more compact syntax).
> 
> I’m hoping that this might be low-hanging fruit that could be considered for 
> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
> there’s interest!
> 
> –Adam
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

Working demo:

struct VirtualKeyPath {
let block: (Root) -> Value
func evaluate(on: Root) -> Value { return block(on) }
}

// If we could extend 'Any', this would be possible...
//extension Any {
//subscript(keyPath: VirtualKeyPath) -> Value {
//return keyPath.evaluate(on: self)
//}
//}

extension KeyPath where Value: Collection {

func map(_ descendent: KeyPath) -> 
VirtualKeyPath {
return VirtualKeyPath { (obj: Root) -> [T] in
return obj[keyPath: self].map { $0[keyPath: descendent] }
}
}
}

extension VirtualKeyPath where Value: Collection {

func map(_ descendent: KeyPath) -> 
VirtualKeyPath {
return VirtualKeyPath { (obj: Root) -> [T] in
return self.evaluate(on: obj).map { $0[keyPath: descendent] }
}
}
}

struct Person {
let name: String
}
struct Department {
let people: [Person]
}

let nameLengths = (\Department.people).map(\.name).map(\.characters.count)

let testObj = Department(people: [Person(name: "Alice"),
  Person(name: "Bob"),
  Person(name: "Claire"),
  Person(name: "David")])

kp.evaluate(on: testObj) // returns [5, 3, 6, 5]
As far as making this kind of thing easier in the language is concerned, one 
thing I can think of is allowing another \ to end the key-path expression, 
rather than enclosing it with brackets. So:

let nameLengths = (\Department.people).map(\.name).map(\.characters.count)

Becomes:

let nameLengths = \Department.people\.map(\.name).map(\.characters.count)

And that’s it, I think. It’s quite nice as-is.

- Karl

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


Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-09 Thread Karl Wagner via swift-evolution

> On 10. Jun 2017, at 01:42, Karl Wagner  wrote:
> 
>> 
>> On 8. Jun 2017, at 04:58, Tony Allevato via swift-evolution 
>> > wrote:
>> 
>> +1, I really like this. It would also align nicely with the method type 
>> flattening in SE-0042 
>> 
>>  (once it gets implemented), because passing keypaths (i.e., unbound 
>> property references) and unbound parameterless method references to 
>> map/flatMap would look nearly the same:
>> 
>> ```
>> struct Person {
>>   let firstName: String
>>   let lastName: String
>>   func fullName() -> String { return "\(firstName) \(lastName)" }
>> }
>> 
>> let people: [Person]
>> let firstNames = people.map(\.firstName)
>> let fullNames = people.map(Person.fullName)  // because after SE-0042, this 
>> will be (Person) -> String, not (Person) -> () -> String
>> ```
>> 
>> Especially if there's a move in the future to also use \. to denote unbound 
>> methods references, which was discussed during the keypath reviews. (Even 
>> with that, I believe it would be more work though to get rid of the explicit 
>> type name in the function case.)
>> 
>> 
> 
> When it comes to unbound method references, personally, I would love to see 
> us ditch currying in some future version of Swift and move to full-blown 
> partial application instead. We would need variadic generics if we wanted to 
> expose them as nicely-typed objects as we do with KeyPaths.
> 
> Anyway, I think what you want is something like this (where VirtualKeyPath is 
> a custom subclass of KeyPath which is lazily-evaluated using a closure).
> 
> extension KeyPath where Value: Collection {
> func map(_ descendent: KeyPath) -> VirtualKeyPath 
> {
> return VirtualKeyPath { 
> (obj: Root) -> [T] in obj[keypath: self].map { $0[keypath: 
> descendent] } 
> }
> }
> }
> 
> \Department.people.map(\.fullName).characters.count  // type: 
> VirtualKeyPath
> 
> 
> Custom subclasses of KeyPath are not allowed, so you can’t actually do this. 
> I don’t know, maybe it wouldn’t be much overhead to add the one, 
> closure-based VirtualKeyPath — clearly the architecture is meant to be 
> flexible. Maybe it’s better to wait until Swift 5 for that, though.
> 
> - Karl

Two corrections to myself:

1) It’s KeyPath

2) You could implement VirtualKeyPath today, but you wouldn’t get the chaining 
syntax. You’d have to just keep map-ping it every time:

\Department.people.map(\.fullName).map(\.characters.count)  // type: 
VirtualKeyPath

- Karl

> 
>> On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution 
>> > wrote:
>> +1. Would think that all variants should exist on Optional too unless it 
>> would be harmful.
>> On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution 
>> > wrote:
>> This is a great idea, and ought to be easy enough to bring forward!  +1 from 
>> me!
>> 
>> -Michael
>> 
>> > On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution 
>> > > wrote:
>> >
>> > 
>> >
>> >> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
>> >> > wrote:
>> >>
>> >> The new smart key path feature is really lovely, and feels like a great 
>> >> addition to Swift.
>> >>
>> >> It seems like it might be straightforward to add overloads of `map` and 
>> >> `flatMap` to the standard library to make use of the new functionality:
>> >>
>> >>  let managers = flatOrganisation.managers
>> >>  let allEmployees = Set(managers.flatMap(\.directReports))
>> >>  let employeeNames = Set(allEmployees.map(\.name))
>> >>
>> >> This feels like a really natural way of working with key paths in a 
>> >> functional style. It makes a lot of sense for collections, and possibly 
>> >> for Optional too (although as far as I can see optional chaining is more 
>> >> or less equivalent, and with more compact syntax).
>> >>
>> >> I’m hoping that this might be low-hanging fruit that could be considered 
>> >> for the Swift 4 release. I’d be happy to have a go at writing a proposal 
>> >> if there’s interest!
>> >>
>> >> –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 
>> > 

Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-09 Thread Karl Wagner via swift-evolution

> On 8. Jun 2017, at 04:58, Tony Allevato via swift-evolution 
>  wrote:
> 
> +1, I really like this. It would also align nicely with the method type 
> flattening in SE-0042 
> 
>  (once it gets implemented), because passing keypaths (i.e., unbound property 
> references) and unbound parameterless method references to map/flatMap would 
> look nearly the same:
> 
> ```
> struct Person {
>   let firstName: String
>   let lastName: String
>   func fullName() -> String { return "\(firstName) \(lastName)" }
> }
> 
> let people: [Person]
> let firstNames = people.map(\.firstName)
> let fullNames = people.map(Person.fullName)  // because after SE-0042, this 
> will be (Person) -> String, not (Person) -> () -> String
> ```
> 
> Especially if there's a move in the future to also use \. to denote unbound 
> methods references, which was discussed during the keypath reviews. (Even 
> with that, I believe it would be more work though to get rid of the explicit 
> type name in the function case.)
> 
> 

When it comes to unbound method references, personally, I would love to see us 
ditch currying in some future version of Swift and move to full-blown partial 
application instead. We would need variadic generics if we wanted to expose 
them as nicely-typed objects as we do with KeyPaths.

Anyway, I think what you want is something like this (where VirtualKeyPath is a 
custom subclass of KeyPath which is lazily-evaluated using a closure).

extension KeyPath where Value: Collection {
func map(_ descendent: KeyPath) -> VirtualKeyPath {
return VirtualKeyPath { 
(obj: Root) -> [T] in obj[keypath: self].map { $0[keypath: 
descendent] } 
}
}
}

\Department.people.map(\.fullName).characters.count  // type: 
VirtualKeyPath


Custom subclasses of KeyPath are not allowed, so you can’t actually do this. I 
don’t know, maybe it wouldn’t be much overhead to add the one, closure-based 
VirtualKeyPath — clearly the architecture is meant to be flexible. Maybe it’s 
better to wait until Swift 5 for that, though.

- Karl

> On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution 
> > wrote:
> +1. Would think that all variants should exist on Optional too unless it 
> would be harmful.
> On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution 
> > wrote:
> This is a great idea, and ought to be easy enough to bring forward!  +1 from 
> me!
> 
> -Michael
> 
> > On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution 
> > > wrote:
> >
> > 
> >
> >> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
> >> > wrote:
> >>
> >> The new smart key path feature is really lovely, and feels like a great 
> >> addition to Swift.
> >>
> >> It seems like it might be straightforward to add overloads of `map` and 
> >> `flatMap` to the standard library to make use of the new functionality:
> >>
> >>  let managers = flatOrganisation.managers
> >>  let allEmployees = Set(managers.flatMap(\.directReports))
> >>  let employeeNames = Set(allEmployees.map(\.name))
> >>
> >> This feels like a really natural way of working with key paths in a 
> >> functional style. It makes a lot of sense for collections, and possibly 
> >> for Optional too (although as far as I can see optional chaining is more 
> >> or less equivalent, and with more compact syntax).
> >>
> >> I’m hoping that this might be low-hanging fruit that could be considered 
> >> for the Swift 4 release. I’d be happy to have a go at writing a proposal 
> >> if there’s interest!
> >>
> >> –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 
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 

Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-09 Thread Max Moiseev via swift-evolution
Sorry. I might be missing something. Why is this better than:

let allEmployees = Set(managers.flatMap { $0.directReports }

?

> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
>  wrote:
> 
> The new smart key path feature is really lovely, and feels like a great 
> addition to Swift.
> 
> It seems like it might be straightforward to add overloads of `map` and 
> `flatMap` to the standard library to make use of the new functionality:
> 
>   let managers = flatOrganisation.managers
>   let allEmployees = Set(managers.flatMap(\.directReports))
>   let employeeNames = Set(allEmployees.map(\.name))
> 
> This feels like a really natural way of working with key paths in a 
> functional style. It makes a lot of sense for collections, and possibly for 
> Optional too (although as far as I can see optional chaining is more or less 
> equivalent, and with more compact syntax).
> 
> I’m hoping that this might be low-hanging fruit that could be considered for 
> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
> there’s interest!
> 
> –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] Pitch: Support for map and flatMap with smart key paths

2017-06-08 Thread Matt Diephouse via swift-evolution


> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
>  wrote:
> 
> The new smart key path feature is really lovely, and feels like a great 
> addition to Swift.
> 
> It seems like it might be straightforward to add overloads of `map` and 
> `flatMap` to the standard library to make use of the new functionality:
> 
>   let managers = flatOrganisation.managers
>   let allEmployees = Set(managers.flatMap(\.directReports))
>   let employeeNames = Set(allEmployees.map(\.name))
> 
> This feels like a really natural way of working with key paths in a 
> functional style. It makes a lot of sense for collections, and possibly for 
> Optional too (although as far as I can see optional chaining is more or less 
> equivalent, and with more compact syntax).
> 
> I’m hoping that this might be low-hanging fruit that could be considered for 
> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
> there’s interest!
> 
> –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] Pitch: Support for map and flatMap with smart key paths

2017-06-08 Thread tobias--- via swift-evolution
I had the need for the same thing today and made it as an extension on Sequence.

extension Sequence {
func map(_ keyPath: KeyPath) -> [T] {
return self.map {
$0[keyPath: keyPath]
}
}

func flatMap(_ keyPath: KeyPath) -> [T] {
return self.flatMap {
$0[keyPath: keyPath]
}
}
}


> The new smart key path feature is really lovely, and feels like a great 
> addition to Swift.
> 
> It seems like it might be straightforward to add overloads of `map` and 
> `flatMap` to the standard library to make use of the new functionality:
> 
> let managers = flatOrganisation.managers
> let allEmployees = Set(managers.flatMap(\.directReports))
> let employeeNames = Set(allEmployees.map(\.name))
> 
> This feels like a really natural way of working with key paths in a 
> functional style. It makes a lot of sense for collections, and possibly for 
> Optional too (although as far as I can see optional chaining is more or less 
> equivalent, and with more compact syntax).
> 
> I’m hoping that this might be low-hanging fruit that could be considered for 
> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
> there’s interest!
> 
> –Adam
> 
> 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-08 Thread Paul Cantrell via swift-evolution
Ah, quite ingenious, Susan!

And you made me realize that the only reason my no-operator-needed code didn’t 
compile is that I had keypath instead of keyPath. So it was indeed “Paul needs 
to go to sleep now” option, which I will now do. 

P


> On Jun 7, 2017, at 11:34 PM, Susan Cheng  wrote:
> 
> this work,
> 
> prefix operator *
> 
> prefix func *(keyPath: KeyPath) -> (Root) -> Value {
> return { $0[keyPath: keyPath] }
> }
> 
> ["Hello, World"].map(*\String.count)// [12]
> 
> 
> 2017-06-08 12:19 GMT+08:00 Paul Cantrell via swift-evolution 
> >:
> It should be possible to achieve Ruby-like generality in Swift with a 
> protocol for “thing that can converted to a transform function.” That 
> wouldn’t need a special & operator.
> 
> Here’s a sketch. This sketch doesn’t compile — maybe not enough of Swift 4 is 
> there yet for it to work, or maybe I am missing something obvious and need to 
> go to sleep now — but it’s close enough to suggest the approach:
> 
> public protocol TransformConvertible {  // or whatever you want to call it
>   associatedtype From
>   associatedtype To
>   
>   var transform: (From) -> To { get }
> }
> 
> extension KeyPath: TransformConvertible {
>   public typealias From = Root
>   public typealias To = Value
>   
>   public var transform: (Root) -> Value {
> return { $0[keypath: self] }
>   }
> }
> 
> extension Sequence {
>   public func map(_ transformSource: U) -> [T]
>where U: TransformConvertible,
>  U.From == Element,
>  U.To == T {
> return map(transformSource.transform)
>   }
> }
> 
> This seems a bit more ambitious, perhaps not suitable for this round of Swift 
> evolution work. But I throw it out there at least to show that supporting 
> people.map(\.firstName) today would not preclude a generic keypath → function 
> mechanism in the future:
> 
> A flavor of map that accepts a keypath today could be generalized to accept 
> TransformConvertible in the future without breaking existing code.
> When calling a function that doesn’t know how to work with 
> TransformConvertible, you could use (Foo.bar).transform, no special operator 
> needed.
> 
> Cheers,
> 
> Paul
> 
> P.S. Largely irrelevant Ruby aside: Ruby’s & is not a free-floating operator, 
> but part of the method invocation syntax indicating that the following arg 
> should be treated as a block. Ruby calls a to_proc method on whatever is in 
> that position. Symbol implements to_proc by returning a lambda that calls the 
> method named by the symbol on the lambda’s first arg. Very much the 
> duck-typed version of TransformConvertible above.
> 
> 
>> On Jun 7, 2017, at 10:21 PM, Stephen Celis via swift-evolution 
>> > wrote:
>> 
>> -1
>> 
>> A -1 from me may be surprising. I'm excited about key path composition and 
>> generic solutions, e.g. this experiment with lenses: 
>> https://twitter.com/stephencelis/status/863916921577758721 
>> 
>> 
>> But I'd prefer a reusable solution for converting key paths into functions.
>> 
>> Heaven help me for this Rubyism, but a prefix "&" operator (or, maybe better 
>> yet, some implicit mechanism) could convert a key-path to a function that 
>> passes a root value to a key path...
>> 
>>   people.map(&\.firstName)
>> 
>> This way any function that takes a transformation from "whole" to "part" 
>> could take a key path. Requiring an overload per instance is less flexible.
>> 
>> Stephen
>> 
>>> On Jun 7, 2017, at 10:58 PM, Tony Allevato via swift-evolution 
>>> > wrote:
>>> 
>>> +1, I really like this. It would also align nicely with the method type 
>>> flattening in SE-0042 (once it gets implemented), because passing keypaths 
>>> (i.e., unbound property references) and unbound parameterless method 
>>> references to map/flatMap would look nearly the same:
>>> 
>>> ```
>>> struct Person {
>>>  let firstName: String
>>>  let lastName: String
>>>  func fullName() -> String { return "\(firstName) \(lastName)" }
>>> }
>>> 
>>> let people: [Person]
>>> let firstNames = people.map(\.firstName)
>>> let fullNames = people.map(Person.fullName)  // because after SE-0042, this 
>>> will be (Person) -> String, not (Person) -> () -> String
>>> ```
>>> 
>>> Especially if there's a move in the future to also use \. to denote unbound 
>>> methods references, which was discussed during the keypath reviews. (Even 
>>> with that, I believe it would be more work though to get rid of the 
>>> explicit type name in the function case.)
>>> 
>>> 
>>> On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution 
>>> 

Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Stephen Celis via swift-evolution
:D

Great example for what I was trying to say. We can compose such a thing with 
existing code and not require an overload per.

> On Jun 8, 2017, at 12:34 AM, Susan Cheng  wrote:
> 
> this work,
> 
> prefix operator *
> 
> prefix func *(keyPath: KeyPath) -> (Root) -> Value {
> return { $0[keyPath: keyPath] }
> }
> 
> ["Hello, World"].map(*\String.count)// [12]
> 
> 
> 2017-06-08 12:19 GMT+08:00 Paul Cantrell via swift-evolution 
> :
> It should be possible to achieve Ruby-like generality in Swift with a 
> protocol for “thing that can converted to a transform function.” That 
> wouldn’t need a special & operator.
> 
> Here’s a sketch. This sketch doesn’t compile — maybe not enough of Swift 4 is 
> there yet for it to work, or maybe I am missing something obvious and need to 
> go to sleep now — but it’s close enough to suggest the approach:
> 
> public protocol TransformConvertible {  // or whatever you want to call it
>   associatedtype From
>   associatedtype To
>   
>   var transform: (From) -> To { get }
> }
> 
> extension KeyPath: TransformConvertible {
>   public typealias From = Root
>   public typealias To = Value
>   
>   public var transform: (Root) -> Value {
> return { $0[keypath: self] }
>   }
> }
> 
> extension Sequence {
>   public func map(_ transformSource: U) -> [T]
>where U: TransformConvertible,
>  U.From == Element,
>  U.To == T {
> return map(transformSource.transform)
>   }
> }
> 
> This seems a bit more ambitious, perhaps not suitable for this round of Swift 
> evolution work. But I throw it out there at least to show that supporting 
> people.map(\.firstName) today would not preclude a generic keypath → function 
> mechanism in the future:
> 
>   • A flavor of map that accepts a keypath today could be generalized to 
> accept TransformConvertible in the future without breaking existing code.
>   • When calling a function that doesn’t know how to work with 
> TransformConvertible, you could use (Foo.bar).transform, no special operator 
> needed.
> 
> Cheers,
> 
> Paul
> 
> P.S. Largely irrelevant Ruby aside: Ruby’s & is not a free-floating operator, 
> but part of the method invocation syntax indicating that the following arg 
> should be treated as a block. Ruby calls a to_proc method on whatever is in 
> that position. Symbol implements to_proc by returning a lambda that calls the 
> method named by the symbol on the lambda’s first arg. Very much the 
> duck-typed version of TransformConvertible above.
> 
> 
>> On Jun 7, 2017, at 10:21 PM, Stephen Celis via swift-evolution 
>>  wrote:
>> 
>> -1
>> 
>> A -1 from me may be surprising. I'm excited about key path composition and 
>> generic solutions, e.g. this experiment with lenses: 
>> https://twitter.com/stephencelis/status/863916921577758721
>> 
>> But I'd prefer a reusable solution for converting key paths into functions.
>> 
>> Heaven help me for this Rubyism, but a prefix "&" operator (or, maybe better 
>> yet, some implicit mechanism) could convert a key-path to a function that 
>> passes a root value to a key path...
>> 
>>   people.map(&\.firstName)
>> 
>> This way any function that takes a transformation from "whole" to "part" 
>> could take a key path. Requiring an overload per instance is less flexible.
>> 
>> Stephen
>> 
>>> On Jun 7, 2017, at 10:58 PM, Tony Allevato via swift-evolution 
>>>  wrote:
>>> 
>>> +1, I really like this. It would also align nicely with the method type 
>>> flattening in SE-0042 (once it gets implemented), because passing keypaths 
>>> (i.e., unbound property references) and unbound parameterless method 
>>> references to map/flatMap would look nearly the same:
>>> 
>>> ```
>>> struct Person {
>>>  let firstName: String
>>>  let lastName: String
>>>  func fullName() -> String { return "\(firstName) \(lastName)" }
>>> }
>>> 
>>> let people: [Person]
>>> let firstNames = people.map(\.firstName)
>>> let fullNames = people.map(Person.fullName)  // because after SE-0042, this 
>>> will be (Person) -> String, not (Person) -> () -> String
>>> ```
>>> 
>>> Especially if there's a move in the future to also use \. to denote unbound 
>>> methods references, which was discussed during the keypath reviews. (Even 
>>> with that, I believe it would be more work though to get rid of the 
>>> explicit type name in the function case.)
>>> 
>>> 
>>> On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution 
>>>  wrote:
>>> +1. Would think that all variants should exist on Optional too unless it 
>>> would be harmful.
>>> On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution 
>>>  wrote:
>>> This is a great idea, and ought to be easy enough to bring forward!  +1 

Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Susan Cheng via swift-evolution
this work,


prefix operator *


prefix func *(keyPath: KeyPath) -> (Root) -> Value
{

return { $0[keyPath: keyPath] }

}


["Hello, World"].map(*\String.count)// [12]


2017-06-08 12:19 GMT+08:00 Paul Cantrell via swift-evolution <
swift-evolution@swift.org>:

> It should be possible to achieve Ruby-like generality in Swift with a
> protocol for “thing that can converted to a transform function.” That
> wouldn’t need a special & operator.
>
> Here’s a sketch. This sketch doesn’t compile — maybe not enough of Swift 4
> is there yet for it to work, or maybe I am missing something obvious and
> need to go to sleep now — but it’s close enough to suggest the approach:
>
> public protocol TransformConvertible {  // or whatever you want to
> call it
>   associatedtype From
>   associatedtype To
>
>
>   var transform: (From) -> To { get }
> }
>
> extension KeyPath: TransformConvertible {
>   public typealias From = Root
>   public typealias To = Value
>
>
>   public var transform: (Root) -> Value {
> return { $0[keypath: self] }
>   }
> }
>
> extension Sequence {
>   public func map(_ transformSource: U) -> [T]
>where U: TransformConvertible,
>  U.From == Element,
>  U.To == T {
> return map(transformSource.transform)
>   }
> }
>
> This seems a bit more ambitious, perhaps not suitable for this round of
> Swift evolution work. But I throw it out there at least to show that
> supporting people.map(\.firstName) today *would not preclude* a generic
> keypath → function mechanism in the future:
>
>
>- A flavor of map that accepts a keypath today could be generalized to
>accept TransformConvertible in the future without breaking existing code.
>- When calling a function that doesn’t know how to work
>with TransformConvertible, you could use (Foo.bar).transform, no special
>operator needed.
>
>
> Cheers,
>
> Paul
>
> P.S. Largely irrelevant Ruby aside: Ruby’s & is not a free-floating
> operator, but part of the method invocation syntax indicating that the
> following arg should be treated as a block. Ruby calls a to_proc method on
> whatever is in that position. Symbol implements to_proc by returning a
> lambda that calls the method named by the symbol on the lambda’s first arg.
> Very much the duck-typed version of TransformConvertible above.
>
>
> On Jun 7, 2017, at 10:21 PM, Stephen Celis via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> -1
>
> A -1 from me may be surprising. I'm excited about key path composition and
> generic solutions, e.g. this experiment with lenses: https://twitter.com/
> stephencelis/status/863916921577758721
>
> But I'd prefer a reusable solution for converting key paths into functions.
>
> Heaven help me for this Rubyism, but a prefix "&" operator (or, maybe
> better yet, some implicit mechanism) could convert a key-path to a function
> that passes a root value to a key path...
>
>   people.map(&\.firstName)
>
> This way any function that takes a transformation from "whole" to "part"
> could take a key path. Requiring an overload per instance is less flexible.
>
> Stephen
>
> On Jun 7, 2017, at 10:58 PM, Tony Allevato via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> +1, I really like this. It would also align nicely with the method type
> flattening in SE-0042 (once it gets implemented), because passing keypaths
> (i.e., unbound property references) and unbound parameterless method
> references to map/flatMap would look nearly the same:
>
> ```
> struct Person {
>  let firstName: String
>  let lastName: String
>  func fullName() -> String { return "\(firstName) \(lastName)" }
> }
>
> let people: [Person]
> let firstNames = people.map(\.firstName)
> let fullNames = people.map(Person.fullName)  // because after SE-0042,
> this will be (Person) -> String, not (Person) -> () -> String
> ```
>
> Especially if there's a move in the future to also use \. to denote
> unbound methods references, which was discussed during the keypath reviews.
> (Even with that, I believe it would be more work though to get rid of the
> explicit type name in the function case.)
>
>
> On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution <
> swift-evolution@swift.org> wrote:
> +1. Would think that all variants should exist on Optional too unless it
> would be harmful.
> On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution <
> swift-evolution@swift.org> wrote:
> This is a great idea, and ought to be easy enough to bring forward!  +1
> from me!
>
> -Michael
>
> On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> 
>
> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> The new smart key path feature is really lovely, and feels like a great
> addition to Swift.
>
> It seems like it might be 

Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Paul Cantrell via swift-evolution
It should be possible to achieve Ruby-like generality in Swift with a protocol 
for “thing that can converted to a transform function.” That wouldn’t need a 
special & operator.

Here’s a sketch. This sketch doesn’t compile — maybe not enough of Swift 4 is 
there yet for it to work, or maybe I am missing something obvious and need to 
go to sleep now — but it’s close enough to suggest the approach:

public protocol TransformConvertible {  // or whatever you want to call it
  associatedtype From
  associatedtype To
  
  var transform: (From) -> To { get }
}

extension KeyPath: TransformConvertible {
  public typealias From = Root
  public typealias To = Value
  
  public var transform: (Root) -> Value {
return { $0[keypath: self] }
  }
}

extension Sequence {
  public func map(_ transformSource: U) -> [T]
   where U: TransformConvertible,
 U.From == Element,
 U.To == T {
return map(transformSource.transform)
  }
}

This seems a bit more ambitious, perhaps not suitable for this round of Swift 
evolution work. But I throw it out there at least to show that supporting 
people.map(\.firstName) today would not preclude a generic keypath → function 
mechanism in the future:

A flavor of map that accepts a keypath today could be generalized to accept 
TransformConvertible in the future without breaking existing code.
When calling a function that doesn’t know how to work with 
TransformConvertible, you could use (Foo.bar).transform, no special operator 
needed.

Cheers,

Paul

P.S. Largely irrelevant Ruby aside: Ruby’s & is not a free-floating operator, 
but part of the method invocation syntax indicating that the following arg 
should be treated as a block. Ruby calls a to_proc method on whatever is in 
that position. Symbol implements to_proc by returning a lambda that calls the 
method named by the symbol on the lambda’s first arg. Very much the duck-typed 
version of TransformConvertible above.


> On Jun 7, 2017, at 10:21 PM, Stephen Celis via swift-evolution 
>  wrote:
> 
> -1
> 
> A -1 from me may be surprising. I'm excited about key path composition and 
> generic solutions, e.g. this experiment with lenses: 
> https://twitter.com/stephencelis/status/863916921577758721
> 
> But I'd prefer a reusable solution for converting key paths into functions.
> 
> Heaven help me for this Rubyism, but a prefix "&" operator (or, maybe better 
> yet, some implicit mechanism) could convert a key-path to a function that 
> passes a root value to a key path...
> 
>   people.map(&\.firstName)
> 
> This way any function that takes a transformation from "whole" to "part" 
> could take a key path. Requiring an overload per instance is less flexible.
> 
> Stephen
> 
>> On Jun 7, 2017, at 10:58 PM, Tony Allevato via swift-evolution 
>>  wrote:
>> 
>> +1, I really like this. It would also align nicely with the method type 
>> flattening in SE-0042 (once it gets implemented), because passing keypaths 
>> (i.e., unbound property references) and unbound parameterless method 
>> references to map/flatMap would look nearly the same:
>> 
>> ```
>> struct Person {
>>  let firstName: String
>>  let lastName: String
>>  func fullName() -> String { return "\(firstName) \(lastName)" }
>> }
>> 
>> let people: [Person]
>> let firstNames = people.map(\.firstName)
>> let fullNames = people.map(Person.fullName)  // because after SE-0042, this 
>> will be (Person) -> String, not (Person) -> () -> String
>> ```
>> 
>> Especially if there's a move in the future to also use \. to denote unbound 
>> methods references, which was discussed during the keypath reviews. (Even 
>> with that, I believe it would be more work though to get rid of the explicit 
>> type name in the function case.)
>> 
>> 
>> On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution 
>>  wrote:
>> +1. Would think that all variants should exist on Optional too unless it 
>> would be harmful.
>> On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution 
>>  wrote:
>> This is a great idea, and ought to be easy enough to bring forward!  +1 from 
>> me!
>> 
>> -Michael
>> 
>>> On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> 
 On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
  wrote:
 
 The new smart key path feature is really lovely, and feels like a great 
 addition to Swift.
 
 It seems like it might be straightforward to add overloads of `map` and 
 `flatMap` to the standard library to make use of the new functionality:
 
 let managers = flatOrganisation.managers
 let allEmployees = Set(managers.flatMap(\.directReports))
 let employeeNames = 

Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Stephen Celis via swift-evolution
-1

A -1 from me may be surprising. I'm excited about key path composition and 
generic solutions, e.g. this experiment with lenses: 
https://twitter.com/stephencelis/status/863916921577758721

But I'd prefer a reusable solution for converting key paths into functions.

Heaven help me for this Rubyism, but a prefix "&" operator (or, maybe better 
yet, some implicit mechanism) could convert a key-path to a function that 
passes a root value to a key path...

   people.map(&\.firstName)

This way any function that takes a transformation from "whole" to "part" could 
take a key path. Requiring an overload per instance is less flexible.

Stephen

> On Jun 7, 2017, at 10:58 PM, Tony Allevato via swift-evolution 
>  wrote:
> 
> +1, I really like this. It would also align nicely with the method type 
> flattening in SE-0042 (once it gets implemented), because passing keypaths 
> (i.e., unbound property references) and unbound parameterless method 
> references to map/flatMap would look nearly the same:
> 
> ```
> struct Person {
>   let firstName: String
>   let lastName: String
>   func fullName() -> String { return "\(firstName) \(lastName)" }
> }
> 
> let people: [Person]
> let firstNames = people.map(\.firstName)
> let fullNames = people.map(Person.fullName)  // because after SE-0042, this 
> will be (Person) -> String, not (Person) -> () -> String
> ```
> 
> Especially if there's a move in the future to also use \. to denote unbound 
> methods references, which was discussed during the keypath reviews. (Even 
> with that, I believe it would be more work though to get rid of the explicit 
> type name in the function case.)
> 
> 
> On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution 
>  wrote:
> +1. Would think that all variants should exist on Optional too unless it 
> would be harmful.
> On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution 
>  wrote:
> This is a great idea, and ought to be easy enough to bring forward!  +1 from 
> me!
> 
> -Michael
> 
> > On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution 
> >  wrote:
> >
> > 
> >
> >> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
> >>  wrote:
> >>
> >> The new smart key path feature is really lovely, and feels like a great 
> >> addition to Swift.
> >>
> >> It seems like it might be straightforward to add overloads of `map` and 
> >> `flatMap` to the standard library to make use of the new functionality:
> >>
> >>  let managers = flatOrganisation.managers
> >>  let allEmployees = Set(managers.flatMap(\.directReports))
> >>  let employeeNames = Set(allEmployees.map(\.name))
> >>
> >> This feels like a really natural way of working with key paths in a 
> >> functional style. It makes a lot of sense for collections, and possibly 
> >> for Optional too (although as far as I can see optional chaining is more 
> >> or less equivalent, and with more compact syntax).
> >>
> >> I’m hoping that this might be low-hanging fruit that could be considered 
> >> for the Swift 4 release. I’d be happy to have a go at writing a proposal 
> >> if there’s interest!
> >>
> >> –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
> ___
> 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] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Tony Allevato via swift-evolution
+1, I really like this. It would also align nicely with the method type
flattening in SE-0042

(once it gets implemented), because passing keypaths (i.e., unbound
property references) and unbound parameterless method references to
map/flatMap would look nearly the same:

```
struct Person {
  let firstName: String
  let lastName: String
  func fullName() -> String { return "\(firstName) \(lastName)" }
}

let people: [Person]
let firstNames = people.map(\.firstName)
let fullNames = people.map(Person.fullName)  // because after SE-0042, this
will be (Person) -> String, not (Person) -> () -> String
```

Especially if there's a move in the future to also use \. to denote unbound
methods references, which was discussed during the keypath reviews. (Even
with that, I believe it would be more work though to get rid of the
explicit type name in the function case.)


On Wed, Jun 7, 2017 at 6:11 PM Xiaodi Wu via swift-evolution <
swift-evolution@swift.org> wrote:

> +1. Would think that all variants should exist on Optional too unless it
> would be harmful.
> On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>> This is a great idea, and ought to be easy enough to bring forward!  +1
>> from me!
>>
>> -Michael
>>
>> > On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >
>> > 
>> >
>> >> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution <
>> swift-evolution@swift.org> wrote:
>> >>
>> >> The new smart key path feature is really lovely, and feels like a
>> great addition to Swift.
>> >>
>> >> It seems like it might be straightforward to add overloads of `map`
>> and `flatMap` to the standard library to make use of the new functionality:
>> >>
>> >>  let managers = flatOrganisation.managers
>> >>  let allEmployees = Set(managers.flatMap(\.directReports))
>> >>  let employeeNames = Set(allEmployees.map(\.name))
>> >>
>> >> This feels like a really natural way of working with key paths in a
>> functional style. It makes a lot of sense for collections, and possibly for
>> Optional too (although as far as I can see optional chaining is more or
>> less equivalent, and with more compact syntax).
>> >>
>> >> I’m hoping that this might be low-hanging fruit that could be
>> considered for the Swift 4 release. I’d be happy to have a go at writing a
>> proposal if there’s interest!
>> >>
>> >> –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
>>
> ___
> 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: Support for map and flatMap with smart key paths

2017-06-07 Thread Xiaodi Wu via swift-evolution
+1. Would think that all variants should exist on Optional too unless it
would be harmful.
On Wed, Jun 7, 2017 at 20:13 Michael J LeHew Jr via swift-evolution <
swift-evolution@swift.org> wrote:

> This is a great idea, and ought to be easy enough to bring forward!  +1
> from me!
>
> -Michael
>
> > On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > 
> >
> >> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution <
> swift-evolution@swift.org> wrote:
> >>
> >> The new smart key path feature is really lovely, and feels like a great
> addition to Swift.
> >>
> >> It seems like it might be straightforward to add overloads of `map` and
> `flatMap` to the standard library to make use of the new functionality:
> >>
> >>  let managers = flatOrganisation.managers
> >>  let allEmployees = Set(managers.flatMap(\.directReports))
> >>  let employeeNames = Set(allEmployees.map(\.name))
> >>
> >> This feels like a really natural way of working with key paths in a
> functional style. It makes a lot of sense for collections, and possibly for
> Optional too (although as far as I can see optional chaining is more or
> less equivalent, and with more compact syntax).
> >>
> >> I’m hoping that this might be low-hanging fruit that could be
> considered for the Swift 4 release. I’d be happy to have a go at writing a
> proposal if there’s interest!
> >>
> >> –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
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Michael J LeHew Jr via swift-evolution
This is a great idea, and ought to be easy enough to bring forward!  +1 from me!

-Michael

> On Jun 7, 2017, at 11:18 AM, Matt Diephouse via swift-evolution 
>  wrote:
> 
> 
> 
>> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
>>  wrote:
>> 
>> The new smart key path feature is really lovely, and feels like a great 
>> addition to Swift.
>> 
>> It seems like it might be straightforward to add overloads of `map` and 
>> `flatMap` to the standard library to make use of the new functionality:
>> 
>>  let managers = flatOrganisation.managers
>>  let allEmployees = Set(managers.flatMap(\.directReports))
>>  let employeeNames = Set(allEmployees.map(\.name))
>> 
>> This feels like a really natural way of working with key paths in a 
>> functional style. It makes a lot of sense for collections, and possibly for 
>> Optional too (although as far as I can see optional chaining is more or less 
>> equivalent, and with more compact syntax).
>> 
>> I’m hoping that this might be low-hanging fruit that could be considered for 
>> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
>> there’s interest!
>> 
>> –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] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Matt Diephouse via swift-evolution


> On Jun 7, 2017, at 10:35 AM, Adam Sharp via swift-evolution 
>  wrote:
> 
> The new smart key path feature is really lovely, and feels like a great 
> addition to Swift.
> 
> It seems like it might be straightforward to add overloads of `map` and 
> `flatMap` to the standard library to make use of the new functionality:
> 
>   let managers = flatOrganisation.managers
>   let allEmployees = Set(managers.flatMap(\.directReports))
>   let employeeNames = Set(allEmployees.map(\.name))
> 
> This feels like a really natural way of working with key paths in a 
> functional style. It makes a lot of sense for collections, and possibly for 
> Optional too (although as far as I can see optional chaining is more or less 
> equivalent, and with more compact syntax).
> 
> I’m hoping that this might be low-hanging fruit that could be considered for 
> the Swift 4 release. I’d be happy to have a go at writing a proposal if 
> there’s interest!
> 
> –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] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Víctor Pimentel Rodríguez via swift-evolution
On Wed, Jun 7, 2017 at 7:35 PM, Adam Sharp via swift-evolution <
swift-evolution@swift.org> wrote:

> The new smart key path feature is really lovely, and feels like a great
> addition to Swift.
>
> It seems like it might be straightforward to add overloads of `map` and
> `flatMap` to the standard library to make use of the new functionality:
>
> let managers = flatOrganisation.managers
> let allEmployees = Set(managers.flatMap(\.directReports))
> let employeeNames = Set(allEmployees.map(\.name))
>
> This feels like a really natural way of working with key paths in a
> functional style. It makes a lot of sense for collections, and possibly for
> Optional too (although as far as I can see optional chaining is more or
> less equivalent, and with more compact syntax).
>
> I’m hoping that this might be low-hanging fruit that could be considered
> for the Swift 4 release. I’d be happy to have a go at writing a proposal if
> there’s interest!
>
> –Adam
>

+1, it seems like a wonderful addition that would make a lot of code much
shorter.

-- 
Víctor Pimentel
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


[swift-evolution] Pitch: Support for map and flatMap with smart key paths

2017-06-07 Thread Adam Sharp via swift-evolution
The new smart key path feature is really lovely, and feels like a great 
addition to Swift.

It seems like it might be straightforward to add overloads of `map` and 
`flatMap` to the standard library to make use of the new functionality:

let managers = flatOrganisation.managers
let allEmployees = Set(managers.flatMap(\.directReports))
let employeeNames = Set(allEmployees.map(\.name))

This feels like a really natural way of working with key paths in a functional 
style. It makes a lot of sense for collections, and possibly for Optional too 
(although as far as I can see optional chaining is more or less equivalent, and 
with more compact syntax).

I’m hoping that this might be low-hanging fruit that could be considered for 
the Swift 4 release. I’d be happy to have a go at writing a proposal if there’s 
interest!

–Adam

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-22 Thread David Smith via swift-evolution

> On Feb 20, 2017, at 2:56 PM, David Sweeris via swift-evolution 
>  wrote:
> 
>> 
>> On Feb 20, 2017, at 2:50 PM, Michel Fortin via swift-evolution 
>>  wrote:
>> 
>>> Le 20 févr. 2017 à 14:45, Matthew Johnson  a écrit :
>>> 
 
 On Feb 20, 2017, at 1:42 PM, Michel Fortin  
 wrote:
 
> Le 20 févr. 2017 à 14:23, Charles Srstka  a 
> écrit :
> 
> I’m not sure how I feel about that, since it hamstrings the ability to 
> improve APIs in a lot of ways without breaking backwards compatibility. A 
> quick example off the top of my head would be all the Cocoa APIs that 
> started out having ivars representing paths backed by simple getter 
> methods, and were later refactored to be URL-based, but with the original 
> path properties become computed properties pointing to the URL’s “path” 
> property. With this, properties would not be able to be refactored in 
> this way unless the library developer had previously declared the “path” 
> property as private(set), which is unlikely for a property that was not 
> intended to be changed after the class was initialized.
 
 Version 1:
 
public class A {
public let path: String
}
 
 Version 2:
 
public class A {
public pure var path: String { return url.path }
public let path: URL
}
 
 This is assuming `let` is implicitly pure. It probably should not be. Or 
 at least it should not when crossing module boundaries. Note that internal 
 to the module it wouldn't violate any contract to allow pure code access 
 to `let` variables.
 
 Which makes me think of an idea: internal to the module, `pure` could be 
 inferred for everything. Only the published APIs would require the 
 annotations, and only if you want `pure` to be part of the API contract. 
 Attaching `pure` to an internal function could still be useful for your 
 own reasoning though.
>>> 
>>> That’s a very interesting approach that could lighten the syntactic load.  
>>> We could strategically annotate our code where we want purity verified, but 
>>> otherwise omit the annotation for members that don’t need to be visible 
>>> outside the module.  This approach works especially well for closures.  I 
>>> like it a lot!
>> 
>> There is an important limitation to this though: a class method that mutate 
>> something in the class is never going to be implicitly pure (per the rules 
>> of purity for instance methods). For that the compiler would have to prove 
>> the method is only called from unique references, and that'd be a bit weird 
>> (add a method call somewhere and suddenly the function becomes impure).
>> 
>> There's also an issue with diagnostics: say you have func1 that calls func2 
>> that calls func3. Func1 is `pure`, the other two are pure only implicitly. 
>> Then you change something in func3, and suddenly func1 complains that it 
>> can't call impure func2 and you are left wondering why because you haven't 
>> changed anything in func2. Perhaps the compiler could dig in the call tree 
>> to find the impure operation and tell you, but that's starting to look like 
>> the awful diagnostic messages for C++ templates.
> 
> Could we only infer purity for one “level”? As a technical limitation rather 
> than part of the language spec, to be removed at some later date when we have 
> time to implement the diagnostic logic? So in your example, the purity of 
> func2 or func3 could be inferred, but the other would have to be annotated.
> 
> - Dave Sweeris

It seems like there's a parallel to 'throws' here, where the unknown 
throwy-ness of a function has to be dealt with for closures with 'rethrows'. 
Pie in the sky, perhaps, but it'd be interesting to see what a generalized 
effects system would look like for Swift, ideally subsuming both of those and 
allowing for many others.

David

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-21 Thread Matthew Johnson via swift-evolution

> On Feb 21, 2017, at 9:38 PM, Michel Fortin  wrote:
> 
>> Le 21 févr. 2017 à 22:05, Matthew Johnson  a écrit :
>> 
 Le 20 févr. 2017 à 12:17, Matthew Johnson  a écrit 
 :
 
> e) Generic Containers:
> Generic containers that impose requirements on their elements will pose 
> some additional problems, for instance: `Set.insert` needs to call 
> `hashValue` and `==` on its elements, making the purity of `Set.insert` 
> constrained by the purity of those functions. Without a way to express 
> this kind of conditional purity, `Set` and `Dictionary` cannot be pure.
 
 Could we use a mechanism similar to `rethrows` to address this kind of 
 transitive purity?  We have already discussed something along those lines 
 for handling functions passed as arguments.  Maybe that mechanism could be 
 designed to handle this use case as well.
>>> 
>>> Similar, yes. But more complicated too. In pseudo code, this is what you'd 
>>> have to express for `Set.insert`:
>>> 
>>> pure(where: Element.hashValue is pure, Element.== is pure)
>>> func insert(_ element: Element) { ... }
>>> 
>>> Then the compiler can enforce that `insert` only does things that are 
>>> allowed in a pure function, but can ignore the purity of Element.hashValue 
>>> and Element.== because the caller will check for that that.
>> 
>> Yep, that’s the kind of thing I had in mind.
>> 
>> I can imagine being this explicit could get pretty cumbersome though.  I 
>> wonder if there is a way to streamline this.  For example, in this case if 
>> we could just talk about `Element`’s conformance to `Hashable` and we could 
>> talk about a `pure` conformance (all requirements are met with pure 
>> implementations) then we could just say something like this:
>> 
>> pure(Element.Hashable)
>> func insert(_ element: Element) { ... }
>> 
>> Note: I also removed some redundancies - we could just say that the 
>> parameters are a list of things the purity of which `insert`’s purity 
>> depends.
>> 
>> For function arguments it would look something like this:
>> 
>> pure(transform)
>> func map(transform: Element -> T)
> 
> The approach is interesting and less heavy than my pseudo code example. The 
> syntax with protocols is a bit off though. What does `Element.Hashable` mean 
> in Swift? It refers to a member inside of `Element`, not a conformance of 
> `Element` to the `Hashable` protocol. I don't think there is any syntax to 
> refer to a conformance of a certain type to a protocol in Swift. The closest 
> is a check for the existence of a conformance for generic arguments.

Right, this was pseudo code and I just used the first syntax for referencing a 
conformance that came to mind.  We would obviously need to do a solid round of 
design of the real syntax.  I was mostly trying to show an approach we might be 
able to sue keep the annotations manageable.

> 
> But I'd tend to gravitate towards your last example, which is simpler: just 
> provide a path to the function that must be pure. Ideally you would be able 
> do it like this:
> 
>   pure(Element.hashValue, Element.==)
> 
> Unfortunately, it's hard (impossible?) currently to represent the getter of a 
> property or to get the function associated with an operator like ==, so this 
> is a bit ad-hoc. (Try to assign the function to a variable to see what I 
> mean.) There's still some general language improvements required to make this 
> work.
> 
> If you want another syntax requiring all functions in a protocol conformance 
> to be pure, that's an additive thing. I'm not sure it's worth its weight 
> though.

Yeah, it’s hard to say.  I just feel like referencing individual functions and 
properties is going to be a significant burden in some cases.  I’m trying to 
think of how we might be able to keep it under control.  If we can’t then 
people won’t want to bother with the annotation even when their function should 
be pure.

> 
> I do agree that it's cumbersome to have these complicated annotations. We 
> could imitate D and have generic functions infer their purity automatically, 
> but that wouldn't work well in a language like Swift where generic code can 
> be opaque. Instead, perhaps the compiler could automatically suggest what to 
> add when it detects some requirements are missing in a pure function.

I think it’s worth investing effort into trying to find a way to avoid 
burdensome annotations rather than having the compiler generate the boilerplate 
for us.

> 
> 
> -- 
> Michel Fortin
> https://michelf.ca
> 

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-21 Thread Michel Fortin via swift-evolution
> Le 21 févr. 2017 à 22:05, Matthew Johnson  a écrit :
> 
>>> Le 20 févr. 2017 à 12:17, Matthew Johnson  a écrit :
>>> 
 e) Generic Containers:
 Generic containers that impose requirements on their elements will pose 
 some additional problems, for instance: `Set.insert` needs to call 
 `hashValue` and `==` on its elements, making the purity of `Set.insert` 
 constrained by the purity of those functions. Without a way to express 
 this kind of conditional purity, `Set` and `Dictionary` cannot be pure.
>>> 
>>> Could we use a mechanism similar to `rethrows` to address this kind of 
>>> transitive purity?  We have already discussed something along those lines 
>>> for handling functions passed as arguments.  Maybe that mechanism could be 
>>> designed to handle this use case as well.
>> 
>> Similar, yes. But more complicated too. In pseudo code, this is what you'd 
>> have to express for `Set.insert`:
>> 
>>  pure(where: Element.hashValue is pure, Element.== is pure)
>>  func insert(_ element: Element) { ... }
>> 
>> Then the compiler can enforce that `insert` only does things that are 
>> allowed in a pure function, but can ignore the purity of Element.hashValue 
>> and Element.== because the caller will check for that that.
> 
> Yep, that’s the kind of thing I had in mind.
> 
> I can imagine being this explicit could get pretty cumbersome though.  I 
> wonder if there is a way to streamline this.  For example, in this case if we 
> could just talk about `Element`’s conformance to `Hashable` and we could talk 
> about a `pure` conformance (all requirements are met with pure 
> implementations) then we could just say something like this:
> 
> pure(Element.Hashable)
> func insert(_ element: Element) { ... }
> 
> Note: I also removed some redundancies - we could just say that the 
> parameters are a list of things the purity of which `insert`’s purity depends.
> 
> For function arguments it would look something like this:
> 
> pure(transform)
> func map(transform: Element -> T)

The approach is interesting and less heavy than my pseudo code example. The 
syntax with protocols is a bit off though. What does `Element.Hashable` mean in 
Swift? It refers to a member inside of `Element`, not a conformance of 
`Element` to the `Hashable` protocol. I don't think there is any syntax to 
refer to a conformance of a certain type to a protocol in Swift. The closest is 
a check for the existence of a conformance for generic arguments.

But I'd tend to gravitate towards your last example, which is simpler: just 
provide a path to the function that must be pure. Ideally you would be able do 
it like this:

pure(Element.hashValue, Element.==)

Unfortunately, it's hard (impossible?) currently to represent the getter of a 
property or to get the function associated with an operator like ==, so this is 
a bit ad-hoc. (Try to assign the function to a variable to see what I mean.) 
There's still some general language improvements required to make this work.

If you want another syntax requiring all functions in a protocol conformance to 
be pure, that's an additive thing. I'm not sure it's worth its weight though.

I do agree that it's cumbersome to have these complicated annotations. We could 
imitate D and have generic functions infer their purity automatically, but that 
wouldn't work well in a language like Swift where generic code can be opaque. 
Instead, perhaps the compiler could automatically suggest what to add when it 
detects some requirements are missing in a pure function.


-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-21 Thread Matthew Johnson via swift-evolution

> On Feb 21, 2017, at 8:57 PM, Michel Fortin via swift-evolution 
>  wrote:
> 
> (this was accidentally sent off-list, reposting here a day later)

And this was my reply.

> 
>> Le 20 févr. 2017 à 12:17, Matthew Johnson  a écrit :
>> 
>>> e) Generic Containers:
>>> Generic containers that impose requirements on their elements will pose 
>>> some additional problems, for instance: `Set.insert` needs to call 
>>> `hashValue` and `==` on its elements, making the purity of `Set.insert` 
>>> constrained by the purity of those functions. Without a way to express this 
>>> kind of conditional purity, `Set` and `Dictionary` cannot be pure.
>> 
>> Could we use a mechanism similar to `rethrows` to address this kind of 
>> transitive purity?  We have already discussed something along those lines 
>> for handling functions passed as arguments.  Maybe that mechanism could be 
>> designed to handle this use case as well.
> 
> Similar, yes. But more complicated too. In pseudo code, this is what you'd 
> have to express for `Set.insert`:
> 
>   pure(where: Element.hashValue is pure, Element.== is pure)
>   func insert(_ element: Element) { ... }
> 
> Then the compiler can enforce that `insert` only does things that are allowed 
> in a pure function, but can ignore the purity of Element.hashValue and 
> Element.== because the caller will check for that that.

Yep, that’s the kind of thing I had in mind.

I can imagine being this explicit could get pretty cumbersome though.  I wonder 
if there is a way to streamline this.  For example, in this case if we could 
just talk about `Element`’s conformance to `Hashable` and we could talk about a 
`pure` conformance (all requirements are met with pure implementations) then we 
could just say something like this:

pure(Element.Hashable)
func insert(_ element: Element) { ... }

Note: I also removed some redundancies - we could just say that the parameters 
are a list of things the purity of which `insert`’s purity depends.

For function arguments it would look something like this:

pure(transform)
func map(transform: Element -> T)

> 
> -- 
> Michel Fortin
> https://michelf.ca
> 
> ___
> 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] Support for pure functions. Part n + 1.

2017-02-21 Thread Michel Fortin via swift-evolution
(this was accidentally sent off-list, reposting here a day later)

> Le 20 févr. 2017 à 12:17, Matthew Johnson  a écrit :
> 
>> e) Generic Containers:
>> Generic containers that impose requirements on their elements will pose some 
>> additional problems, for instance: `Set.insert` needs to call `hashValue` 
>> and `==` on its elements, making the purity of `Set.insert` constrained by 
>> the purity of those functions. Without a way to express this kind of 
>> conditional purity, `Set` and `Dictionary` cannot be pure.
> 
> Could we use a mechanism similar to `rethrows` to address this kind of 
> transitive purity?  We have already discussed something along those lines for 
> handling functions passed as arguments.  Maybe that mechanism could be 
> designed to handle this use case as well.

Similar, yes. But more complicated too. In pseudo code, this is what you'd have 
to express for `Set.insert`:

pure(where: Element.hashValue is pure, Element.== is pure)
func insert(_ element: Element) { ... }

Then the compiler can enforce that `insert` only does things that are allowed 
in a pure function, but can ignore the purity of Element.hashValue and 
Element.== because the caller will check for that that.

-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-21 Thread David Sweeris via swift-evolution

> On Feb 16, 2017, at 09:03, T.J. Usiyan via swift-evolution 
>  wrote:
> 
> # Pure Functions
> 
> * Proposal: 
> [SE-](https://github.com/apple/swift-evolution/blob/master/proposals/-name.md)
> * Author(s): [TJ Usiyan](https://github.com/griotspeak)
> * Status: **Awaiting review**
> * Review manager: TBD
> 
> ## Introduction
> 
> Some functions are, essentially, only meant to be transformations of their 
> input and–as such–do not and should not reference any variables other than 
> those passed in. These same functions are not meant to have any effects other 
> than the aforementioned transformation of input. Currently, Swift cannot 
> assist the developer and confirm that any given function is one of these 
> 'pure' functions. To facilitate this, this proposal adds syntax to signal 
> that a function is 'pure'.
> 
> 'pure', in this context, means:
> 1. The function must have a return value
> 1. This function can only call other pure functions
> 1. This function cannot access/modify global or static variables.
> 
> ## Motivation
> 
> Consider the following example where `_computeNullability(of:)` is meant to 
> create its output solely based on the provided recognizer.
> 
> ```
> class Recognizer {
>   var nullabilityMemo: Bool?
>   var isNullable: Bool {
>   func _computeNullability(of recognizer: Recognizer) -> Bool {…}
>   if let back = nullabilityMemo {
>   return back 
>   } else {
>   let back =  _computeNullability(of: self)
>   nullabilityMemo = back
>   return back
>   }
>   }
> }
> ```
> if `_computeNullability(of:)` is recursive at all, there exists a real 
> potential to accidentally reference `self` in its body and the mistake, 
> depending on circumstance, can be terribly subtle. Converting 
> `_computeNullability(of:)` to a `static` function is an option but obfuscates 
> the fact that it is *only* to be called within `isNullable`.
> 
> 
> ## Proposed solution
> 
> Given the ability to indicate that `_computeNullability(of:)` is a 'pure' 
> function, the developer gains assurance from the tooling that it doesn't 
> reference anything or cause any side effects.
> 
> 
> ```
> class Recognizer {
>   var nullabilityMemo: Bool?
>   var isNullable: Bool {
>   pfunc _computeNullability(of recognizer: Recognizer) -> Bool {…}
>   if let back = nullabilityMemo {
>   return back 
>   } else {
>   let back =  _computeNullability(of: self)
>   nullabilityMemo = back
>   return back
>   }
>   }
> }
> ```
> 
> ## Detailed design
> 
> This proposal introduces a new annotation `=>`, which is to be accepted 
> everywhere `->` currently is. Members created using this kewyord must follow 
> the rules listed in the introduction.
> 
> ## Impact on existing code
> 
> This is an additive feature unless alternative 2 is chosen and, as such, 
> should not require an effect on existing code. It could be used to annotate 
> closures accepted by methods in the standard library such as `map`, `filter`, 
> and `reduce`. While this would fit well with their typical use, such a change 
> is not necessarily part of this proposal.
> 
> ## Alternatives considered
> 
> It should be noted that neither of these alternatives can remain consistent 
> for inline closures.
> 1. keyword `pfunc` (pronounciation: pifəŋk) for 'pure' functions. 
> 2. `proc` keyword for 'impure' functions and 'func' for 'pure' functions. 
> This would be a massively source breaking change and, as such, is unlikely to 
> have any feasibility. It is, however, the most clean semantically, in my 
> opinion.

Could we use pure functions as the basis of "type functions"? That is, 
functions that operate on, and return, types rather than variables. For 
example, the "N+P" part of the return type in:
func append  (lhs: Matrix, rhs: Matrix) -> Matrix {...}
(where M,N, and P all conform to "Length" or something, since Int literals 
can't be generic parameters yet.) Because something like that would come in 
real handy for matrix and vector types.

I know this feature would have to be a separate proposal... I was just thinking 
of potential applications of pure functions, since somebody was asking earlier 
in the thread.

- Dave Sweeris


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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Matthew Johnson via swift-evolution

> On Feb 20, 2017, at 6:54 PM, Michel Fortin  wrote:
> 
>> 
>> Le 20 févr. 2017 à 18:02, Matthew Johnson  a écrit :
>> 
>> 
>>> On Feb 20, 2017, at 4:50 PM, Michel Fortin  wrote:
>>> 
 Le 20 févr. 2017 à 14:45, Matthew Johnson  a écrit 
 :
 
> 
> On Feb 20, 2017, at 1:42 PM, Michel Fortin  
> wrote:
> 
>> Le 20 févr. 2017 à 14:23, Charles Srstka  a 
>> écrit :
>> 
>> I’m not sure how I feel about that, since it hamstrings the ability to 
>> improve APIs in a lot of ways without breaking backwards compatibility. 
>> A quick example off the top of my head would be all the Cocoa APIs that 
>> started out having ivars representing paths backed by simple getter 
>> methods, and were later refactored to be URL-based, but with the 
>> original path properties become computed properties pointing to the 
>> URL’s “path” property. With this, properties would not be able to be 
>> refactored in this way unless the library developer had previously 
>> declared the “path” property as private(set), which is unlikely for a 
>> property that was not intended to be changed after the class was 
>> initialized.
> 
> Version 1:
> 
>   public class A {
>   public let path: String
>   }
> 
> Version 2:
> 
>   public class A {
>   public pure var path: String { return url.path }
>   public let path: URL
>   }
> 
> This is assuming `let` is implicitly pure. It probably should not be. Or 
> at least it should not when crossing module boundaries. Note that 
> internal to the module it wouldn't violate any contract to allow pure 
> code access to `let` variables.
> 
> Which makes me think of an idea: internal to the module, `pure` could be 
> inferred for everything. Only the published APIs would require the 
> annotations, and only if you want `pure` to be part of the API contract. 
> Attaching `pure` to an internal function could still be useful for your 
> own reasoning though.
 
 That’s a very interesting approach that could lighten the syntactic load.  
 We could strategically annotate our code where we want purity verified, 
 but otherwise omit the annotation for members that don’t need to be 
 visible outside the module.  This approach works especially well for 
 closures.  I like it a lot!
>>> 
>>> There is an important limitation to this though: a class method that mutate 
>>> something in the class is never going to be implicitly pure (per the rules 
>>> of purity for instance methods). For that the compiler would have to prove 
>>> the method is only called from unique references, and that'd be a bit weird 
>>> (add a method call somewhere and suddenly the function becomes impure).
>> 
>> That seems totally fine to me.
>> 
>>> 
>>> There's also an issue with diagnostics: say you have func1 that calls func2 
>>> that calls func3. Func1 is `pure`, the other two are pure only implicitly. 
>>> Then you change something in func3, and suddenly func1 complains that it 
>>> can't call impure func2 and you are left wondering why because you haven't 
>>> changed anything in func2. Perhaps the compiler could dig in the call tree 
>>> to find the impure operation and tell you, but that's starting to look like 
>>> the awful diagnostic messages for C++ templates.
>>> 
>>> So now I'm starting to think this idea of inferring purity was perhaps a 
>>> bit reckless.
>> 
>> It all depends on how people use it (that’s why I mentioned strategic 
>> annotations), but yeah it could be ugly.  I wonder if there is a reasonable 
>> way to bound the inference to keep error messages tractable.  For example, 
>> you mentioned inference within a module.  If that’s too broad a scope for 
>> inference, maybe within a file would be ok and annotation would be required 
>> for anything with `internal` or greater visibility.  This would still 
>> address closures which would be cool and outside of crazy large files it 
>> wouldn’t be too bad to track down the meaning of an error.
> 
> If a closure can be inferred pure, then it should be pure. We already infer 
> `throws` and return types for closures, so inferring `pure` is natural. But 
> for functions declared with a full signature, I'm hesitant to allow them to 
> be inferred.
> 
> Now that I think of it, overrides could be another source of problem with 
> inference: add an impure override and the method in the base class can no 
> longer be inferred as pure. So it can't apply to any non-final class property 
> or function.

Yeah, I’m ok with requiring annotation if inference is going to be hairy or 
confusing.

> 
> -- 
> Michel Fortin
> https://michelf.ca 
___

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Michel Fortin via swift-evolution

> Le 20 févr. 2017 à 18:02, Matthew Johnson  a écrit :
> 
> 
>> On Feb 20, 2017, at 4:50 PM, Michel Fortin  wrote:
>> 
>>> Le 20 févr. 2017 à 14:45, Matthew Johnson  a écrit :
>>> 
 
 On Feb 20, 2017, at 1:42 PM, Michel Fortin  
 wrote:
 
> Le 20 févr. 2017 à 14:23, Charles Srstka  a 
> écrit :
> 
> I’m not sure how I feel about that, since it hamstrings the ability to 
> improve APIs in a lot of ways without breaking backwards compatibility. A 
> quick example off the top of my head would be all the Cocoa APIs that 
> started out having ivars representing paths backed by simple getter 
> methods, and were later refactored to be URL-based, but with the original 
> path properties become computed properties pointing to the URL’s “path” 
> property. With this, properties would not be able to be refactored in 
> this way unless the library developer had previously declared the “path” 
> property as private(set), which is unlikely for a property that was not 
> intended to be changed after the class was initialized.
 
 Version 1:
 
public class A {
public let path: String
}
 
 Version 2:
 
public class A {
public pure var path: String { return url.path }
public let path: URL
}
 
 This is assuming `let` is implicitly pure. It probably should not be. Or 
 at least it should not when crossing module boundaries. Note that internal 
 to the module it wouldn't violate any contract to allow pure code access 
 to `let` variables.
 
 Which makes me think of an idea: internal to the module, `pure` could be 
 inferred for everything. Only the published APIs would require the 
 annotations, and only if you want `pure` to be part of the API contract. 
 Attaching `pure` to an internal function could still be useful for your 
 own reasoning though.
>>> 
>>> That’s a very interesting approach that could lighten the syntactic load.  
>>> We could strategically annotate our code where we want purity verified, but 
>>> otherwise omit the annotation for members that don’t need to be visible 
>>> outside the module.  This approach works especially well for closures.  I 
>>> like it a lot!
>> 
>> There is an important limitation to this though: a class method that mutate 
>> something in the class is never going to be implicitly pure (per the rules 
>> of purity for instance methods). For that the compiler would have to prove 
>> the method is only called from unique references, and that'd be a bit weird 
>> (add a method call somewhere and suddenly the function becomes impure).
> 
> That seems totally fine to me.
> 
>> 
>> There's also an issue with diagnostics: say you have func1 that calls func2 
>> that calls func3. Func1 is `pure`, the other two are pure only implicitly. 
>> Then you change something in func3, and suddenly func1 complains that it 
>> can't call impure func2 and you are left wondering why because you haven't 
>> changed anything in func2. Perhaps the compiler could dig in the call tree 
>> to find the impure operation and tell you, but that's starting to look like 
>> the awful diagnostic messages for C++ templates.
>> 
>> So now I'm starting to think this idea of inferring purity was perhaps a bit 
>> reckless.
> 
> It all depends on how people use it (that’s why I mentioned strategic 
> annotations), but yeah it could be ugly.  I wonder if there is a reasonable 
> way to bound the inference to keep error messages tractable.  For example, 
> you mentioned inference within a module.  If that’s too broad a scope for 
> inference, maybe within a file would be ok and annotation would be required 
> for anything with `internal` or greater visibility.  This would still address 
> closures which would be cool and outside of crazy large files it wouldn’t be 
> too bad to track down the meaning of an error.

If a closure can be inferred pure, then it should be pure. We already infer 
`throws` and return types for closures, so inferring `pure` is natural. But for 
functions declared with a full signature, I'm hesitant to allow them to be 
inferred.

Now that I think of it, overrides could be another source of problem with 
inference: add an impure override and the method in the base class can no 
longer be inferred as pure. So it can't apply to any non-final class property 
or function.


-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Michel Fortin via swift-evolution
> Le 20 févr. 2017 à 17:56, David Sweeris  a écrit :
> 
> Could we only infer purity for one “level”? As a technical limitation rather 
> than part of the language spec, to be removed at some later date when we have 
> time to implement the diagnostic logic? So in your example, the purity of 
> func2 or func3 could be inferred, but the other would have to be annotated.

This is not about the diagnostic logic. It's simply that the diagnostic 
messages will almost always be overwhelming by necessity of having enough 
information to properly debug the problem.

For instance, you add a `print("debug info: blah")` in a few places, one of 
them being `func3`, and suddenly functions all over your code base start 
screaming they can no longer compile. None of these errors occur where you made 
a change, you have to follow the "call stack" in the compiler logs to find why 
the assumption about purity doesn't hold anymore. Example:

error: func1 cannot be pure because it calls func2 which isn't pure.
note: func2 isn't pure because it calls func3 which isn't pure.
note: func3 isn't pure because it calls Swift.print which isn't pure
error: foo cannot be pure because it calls bar which isn't pure.
note: bar isn't pure because it calls baz which isn't pure.
note: baz isn't pure because it calls raa which isn't pure.
note: raa isn't pure because it calls func3 which isn't pure.
note: func3 isn't pure because it calls Swift.print which isn't pure
error: wee cannot be pure because it calls ery which isn't pure.
note: ery isn't pure because it calls tyi which isn't pure.
note: tyi isn't pure because it calls func3 which isn't pure.
note: func3 isn't pure because it calls Swift.print which isn't pure

This isn't a good user experience. I've done enough C++ template debugging to 
know how confusing this can be.

While if you write `pure` in front of every function as you edit those 
functions, this doesn't happen. Errors aren't spread all over the call tree and 
are easier to link to specific edits.

-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Matthew Johnson via swift-evolution

> On Feb 20, 2017, at 4:50 PM, Michel Fortin  > wrote:
> 
>> Le 20 févr. 2017 à 14:45, Matthew Johnson > > a écrit :
>> 
>>> 
>>> On Feb 20, 2017, at 1:42 PM, Michel Fortin >> > wrote:
>>> 
 Le 20 févr. 2017 à 14:23, Charles Srstka > a écrit :
 
 I’m not sure how I feel about that, since it hamstrings the ability to 
 improve APIs in a lot of ways without breaking backwards compatibility. A 
 quick example off the top of my head would be all the Cocoa APIs that 
 started out having ivars representing paths backed by simple getter 
 methods, and were later refactored to be URL-based, but with the original 
 path properties become computed properties pointing to the URL’s “path” 
 property. With this, properties would not be able to be refactored in this 
 way unless the library developer had previously declared the “path” 
 property as private(set), which is unlikely for a property that was not 
 intended to be changed after the class was initialized.
>>> 
>>> Version 1:
>>> 
>>> public class A {
>>> public let path: String
>>> }
>>> 
>>> Version 2:
>>> 
>>> public class A {
>>> public pure var path: String { return url.path }
>>> public let path: URL
>>> }
>>> 
>>> This is assuming `let` is implicitly pure. It probably should not be. Or at 
>>> least it should not when crossing module boundaries. Note that internal to 
>>> the module it wouldn't violate any contract to allow pure code access to 
>>> `let` variables.
>>> 
>>> Which makes me think of an idea: internal to the module, `pure` could be 
>>> inferred for everything. Only the published APIs would require the 
>>> annotations, and only if you want `pure` to be part of the API contract. 
>>> Attaching `pure` to an internal function could still be useful for your own 
>>> reasoning though.
>> 
>> That’s a very interesting approach that could lighten the syntactic load.  
>> We could strategically annotate our code where we want purity verified, but 
>> otherwise omit the annotation for members that don’t need to be visible 
>> outside the module.  This approach works especially well for closures.  I 
>> like it a lot!
> 
> There is an important limitation to this though: a class method that mutate 
> something in the class is never going to be implicitly pure (per the rules of 
> purity for instance methods). For that the compiler would have to prove the 
> method is only called from unique references, and that'd be a bit weird (add 
> a method call somewhere and suddenly the function becomes impure).

That seems totally fine to me.

> 
> There's also an issue with diagnostics: say you have func1 that calls func2 
> that calls func3. Func1 is `pure`, the other two are pure only implicitly. 
> Then you change something in func3, and suddenly func1 complains that it 
> can't call impure func2 and you are left wondering why because you haven't 
> changed anything in func2. Perhaps the compiler could dig in the call tree to 
> find the impure operation and tell you, but that's starting to look like the 
> awful diagnostic messages for C++ templates.
> 
> So now I'm starting to think this idea of inferring purity was perhaps a bit 
> reckless.

It all depends on how people use it (that’s why I mentioned strategic 
annotations), but yeah it could be ugly.  I wonder if there is a reasonable way 
to bound the inference to keep error messages tractable.  For example, you 
mentioned inference within a module.  If that’s too broad a scope for 
inference, maybe within a file would be ok and annotation would be required for 
anything with `internal` or greater visibility.  This would still address 
closures which would be cool and outside of crazy large files it wouldn’t be 
too bad to track down the meaning of an error.

> 
> -- 
> Michel Fortin
> https://michelf.ca 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread David Sweeris via swift-evolution

> On Feb 20, 2017, at 2:50 PM, Michel Fortin via swift-evolution 
>  wrote:
> 
>> Le 20 févr. 2017 à 14:45, Matthew Johnson  a écrit :
>> 
>>> 
>>> On Feb 20, 2017, at 1:42 PM, Michel Fortin  wrote:
>>> 
 Le 20 févr. 2017 à 14:23, Charles Srstka  a 
 écrit :
 
 I’m not sure how I feel about that, since it hamstrings the ability to 
 improve APIs in a lot of ways without breaking backwards compatibility. A 
 quick example off the top of my head would be all the Cocoa APIs that 
 started out having ivars representing paths backed by simple getter 
 methods, and were later refactored to be URL-based, but with the original 
 path properties become computed properties pointing to the URL’s “path” 
 property. With this, properties would not be able to be refactored in this 
 way unless the library developer had previously declared the “path” 
 property as private(set), which is unlikely for a property that was not 
 intended to be changed after the class was initialized.
>>> 
>>> Version 1:
>>> 
>>> public class A {
>>> public let path: String
>>> }
>>> 
>>> Version 2:
>>> 
>>> public class A {
>>> public pure var path: String { return url.path }
>>> public let path: URL
>>> }
>>> 
>>> This is assuming `let` is implicitly pure. It probably should not be. Or at 
>>> least it should not when crossing module boundaries. Note that internal to 
>>> the module it wouldn't violate any contract to allow pure code access to 
>>> `let` variables.
>>> 
>>> Which makes me think of an idea: internal to the module, `pure` could be 
>>> inferred for everything. Only the published APIs would require the 
>>> annotations, and only if you want `pure` to be part of the API contract. 
>>> Attaching `pure` to an internal function could still be useful for your own 
>>> reasoning though.
>> 
>> That’s a very interesting approach that could lighten the syntactic load.  
>> We could strategically annotate our code where we want purity verified, but 
>> otherwise omit the annotation for members that don’t need to be visible 
>> outside the module.  This approach works especially well for closures.  I 
>> like it a lot!
> 
> There is an important limitation to this though: a class method that mutate 
> something in the class is never going to be implicitly pure (per the rules of 
> purity for instance methods). For that the compiler would have to prove the 
> method is only called from unique references, and that'd be a bit weird (add 
> a method call somewhere and suddenly the function becomes impure).
> 
> There's also an issue with diagnostics: say you have func1 that calls func2 
> that calls func3. Func1 is `pure`, the other two are pure only implicitly. 
> Then you change something in func3, and suddenly func1 complains that it 
> can't call impure func2 and you are left wondering why because you haven't 
> changed anything in func2. Perhaps the compiler could dig in the call tree to 
> find the impure operation and tell you, but that's starting to look like the 
> awful diagnostic messages for C++ templates.

Could we only infer purity for one “level”? As a technical limitation rather 
than part of the language spec, to be removed at some later date when we have 
time to implement the diagnostic logic? So in your example, the purity of func2 
or func3 could be inferred, but the other would have to be annotated.

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Michel Fortin via swift-evolution
> Le 20 févr. 2017 à 14:45, Matthew Johnson  a écrit :
> 
>> 
>> On Feb 20, 2017, at 1:42 PM, Michel Fortin  wrote:
>> 
>>> Le 20 févr. 2017 à 14:23, Charles Srstka  a écrit 
>>> :
>>> 
>>> I’m not sure how I feel about that, since it hamstrings the ability to 
>>> improve APIs in a lot of ways without breaking backwards compatibility. A 
>>> quick example off the top of my head would be all the Cocoa APIs that 
>>> started out having ivars representing paths backed by simple getter 
>>> methods, and were later refactored to be URL-based, but with the original 
>>> path properties become computed properties pointing to the URL’s “path” 
>>> property. With this, properties would not be able to be refactored in this 
>>> way unless the library developer had previously declared the “path” 
>>> property as private(set), which is unlikely for a property that was not 
>>> intended to be changed after the class was initialized.
>> 
>> Version 1:
>> 
>>  public class A {
>>  public let path: String
>>  }
>> 
>> Version 2:
>> 
>>  public class A {
>>  public pure var path: String { return url.path }
>>  public let path: URL
>>  }
>> 
>> This is assuming `let` is implicitly pure. It probably should not be. Or at 
>> least it should not when crossing module boundaries. Note that internal to 
>> the module it wouldn't violate any contract to allow pure code access to 
>> `let` variables.
>> 
>> Which makes me think of an idea: internal to the module, `pure` could be 
>> inferred for everything. Only the published APIs would require the 
>> annotations, and only if you want `pure` to be part of the API contract. 
>> Attaching `pure` to an internal function could still be useful for your own 
>> reasoning though.
> 
> That’s a very interesting approach that could lighten the syntactic load.  We 
> could strategically annotate our code where we want purity verified, but 
> otherwise omit the annotation for members that don’t need to be visible 
> outside the module.  This approach works especially well for closures.  I 
> like it a lot!

There is an important limitation to this though: a class method that mutate 
something in the class is never going to be implicitly pure (per the rules of 
purity for instance methods). For that the compiler would have to prove the 
method is only called from unique references, and that'd be a bit weird (add a 
method call somewhere and suddenly the function becomes impure).

There's also an issue with diagnostics: say you have func1 that calls func2 
that calls func3. Func1 is `pure`, the other two are pure only implicitly. Then 
you change something in func3, and suddenly func1 complains that it can't call 
impure func2 and you are left wondering why because you haven't changed 
anything in func2. Perhaps the compiler could dig in the call tree to find the 
impure operation and tell you, but that's starting to look like the awful 
diagnostic messages for C++ templates.

So now I'm starting to think this idea of inferring purity was perhaps a bit 
reckless.

-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Matthew Johnson via swift-evolution

> On Feb 20, 2017, at 1:42 PM, Michel Fortin  wrote:
> 
>> Le 20 févr. 2017 à 14:23, Charles Srstka  a écrit :
>> 
>> I’m not sure how I feel about that, since it hamstrings the ability to 
>> improve APIs in a lot of ways without breaking backwards compatibility. A 
>> quick example off the top of my head would be all the Cocoa APIs that 
>> started out having ivars representing paths backed by simple getter methods, 
>> and were later refactored to be URL-based, but with the original path 
>> properties become computed properties pointing to the URL’s “path” property. 
>> With this, properties would not be able to be refactored in this way unless 
>> the library developer had previously declared the “path” property as 
>> private(set), which is unlikely for a property that was not intended to be 
>> changed after the class was initialized.
> 
> Version 1:
> 
>   public class A {
>   public let path: String
>   }
> 
> Version 2:
> 
>   public class A {
>   public pure var path: String { return url.path }
>   public let path: URL
>   }
> 
> This is assuming `let` is implicitly pure. It probably should not be. Or at 
> least it should not when crossing module boundaries. Note that internal to 
> the module it wouldn't violate any contract to allow pure code access to 
> `let` variables.
> 
> Which makes me think of an idea: internal to the module, `pure` could be 
> inferred for everything. Only the published APIs would require the 
> annotations, and only if you want `pure` to be part of the API contract. 
> Attaching `pure` to an internal function could still be useful for your own 
> reasoning though.

That’s a very interesting approach that could lighten the syntactic load.  We 
could strategically annotate our code where we want purity verified, but 
otherwise omit the annotation for members that don’t need to be visible outside 
the module.  This approach works especially well for closures.  I like it a lot!

> 
> -- 
> Michel Fortin
> https://michelf.ca
> 

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Michel Fortin via swift-evolution
> Le 20 févr. 2017 à 14:23, Charles Srstka  a écrit :
> 
> I’m not sure how I feel about that, since it hamstrings the ability to 
> improve APIs in a lot of ways without breaking backwards compatibility. A 
> quick example off the top of my head would be all the Cocoa APIs that started 
> out having ivars representing paths backed by simple getter methods, and were 
> later refactored to be URL-based, but with the original path properties 
> become computed properties pointing to the URL’s “path” property. With this, 
> properties would not be able to be refactored in this way unless the library 
> developer had previously declared the “path” property as private(set), which 
> is unlikely for a property that was not intended to be changed after the 
> class was initialized.

Version 1:

public class A {
public let path: String
}

Version 2:

public class A {
public pure var path: String { return url.path }
public let path: URL
}

This is assuming `let` is implicitly pure. It probably should not be. Or at 
least it should not when crossing module boundaries. Note that internal to the 
module it wouldn't violate any contract to allow pure code access to `let` 
variables.

Which makes me think of an idea: internal to the module, `pure` could be 
inferred for everything. Only the published APIs would require the annotations, 
and only if you want `pure` to be part of the API contract. Attaching `pure` to 
an internal function could still be useful for your own reasoning though.

-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread David Sweeris via swift-evolution

> On Feb 20, 2017, at 11:23 AM, Charles Srstka via swift-evolution 
>  wrote:
> 
>> On Feb 20, 2017, at 12:53 PM, Matthew Johnson > > wrote:
>> 
>>> 
>>> On Feb 20, 2017, at 12:42 PM, Charles Srstka via swift-evolution 
>>> > wrote:
>>> 
>>> What if the “let” property becomes a “var” property in a future version of 
>>> the library you’re linking against?
>> 
>> That would be a breaking change if the `let` was public or if any `pure` 
>> public methods were accessing it (unless they were refactored to not rely on 
>> it anymore).
> 
> I’m not sure how I feel about that, since it hamstrings the ability to 
> improve APIs in a lot of ways without breaking backwards compatibility. A 
> quick example off the top of my head would be all the Cocoa APIs that started 
> out having ivars representing paths backed by simple getter methods, and were 
> later refactored to be URL-based, but with the original path properties 
> become computed properties pointing to the URL’s “path” property. With this, 
> properties would not be able to be refactored in this way unless the library 
> developer had previously declared the “path” property as private(set), which 
> is unlikely for a property that was not intended to be changed after the 
> class was initialized.

My understanding is that this particular nuance — a “let” being semantically 
different from a “var that for whatever reason can’t be set by you" — has 
pretty much been the case since the beginning... it just doesn’t come up much. 
Come to think of it, I don’t even know if Apple's Swift Book mentions it 
(probably should, if it doesn’t).

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Matthew Johnson via swift-evolution

> On Feb 20, 2017, at 1:23 PM, Charles Srstka  wrote:
> 
>> On Feb 20, 2017, at 12:53 PM, Matthew Johnson > > wrote:
>> 
>>> 
>>> On Feb 20, 2017, at 12:42 PM, Charles Srstka via swift-evolution 
>>> > wrote:
>>> 
 On Feb 20, 2017, at 10:55 AM, Michel Fortin via swift-evolution 
 > wrote:
 
 a) Structs/Locals:
 Structs and local variables behave similarly. You can access `let` and 
 `var` properties and mutate the later.
>>> 
>>> What if the struct contains class ivars, including private ones that you 
>>> may not know about but nonetheless get accessed as a side effect of 
>>> accessing the struct’s “var” properties?
>> 
>> You should be able to access them in accordance with the restrictions on 
>> using classes in a pure manner.
> 
> How can those restrictions be enforced, if the class is a private internal 
> property of the struct that the calling code can’t see?

If calling code can’t see it, it also can’t access it.  It can only be reached 
through a different member of the struct.  That member would need to be pure.  
That is where it would be enforced.

> 
 b) Classes:
 You can't access the variables of a class in a pure function. But you can 
 access its `let` properties. That's because as long as there is no `var` 
 in the dereferencing path, you are guarantied to be accessing a constant. 
 In classes, `let` properties are thus implicitly pure; stored `var` 
 properties are not. Which means that pure instance methods on classes can 
 only access `let` properties, in addition to computed properties that are 
 themselves `pure` and other `pure` methods.
>>> 
>>> What if the “let” property becomes a “var” property in a future version of 
>>> the library you’re linking against?
>> 
>> That would be a breaking change if the `let` was public or if any `pure` 
>> public methods were accessing it (unless they were refactored to not rely on 
>> it anymore).
> 
> I’m not sure how I feel about that, since it hamstrings the ability to 
> improve APIs in a lot of ways without breaking backwards compatibility. A 
> quick example off the top of my head would be all the Cocoa APIs that started 
> out having ivars representing paths backed by simple getter methods, and were 
> later refactored to be URL-based, but with the original path properties 
> become computed properties pointing to the URL’s “path” property. With this, 
> properties would not be able to be refactored in this way unless the library 
> developer had previously declared the “path” property as private(set), which 
> is unlikely for a property that was not intended to be changed after the 
> class was initialized.

Computed read-only properties could be `pure`.  If the refactoring was able to 
preserve this purity it shouldn’t be a breaking change (with respect to purity 
at least).  Stored `var` properties of a class would never be pure.

> 
> Charles

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Michel Fortin via swift-evolution
> Le 20 févr. 2017 à 13:42, Charles Srstka  a écrit :
> 
>> On Feb 20, 2017, at 10:55 AM, Michel Fortin via swift-evolution 
>>  wrote:
>> 
>> a) Structs/Locals:
>> Structs and local variables behave similarly. You can access `let` and `var` 
>> properties and mutate the later.
> 
> What if the struct contains class ivars, including private ones that you may 
> not know about but nonetheless get accessed as a side effect of accessing the 
> struct’s “var” properties?

You can look at the value of the pointer to that class instance (you can 
convert that pointer to a hex value and return it as a string if you want), but 
if you dereference the pointer you need to follow the rules for classes. If you 
call any accessor (because the type is opaque or for other reasons), those 
accessors must be pure (and thus follow the same rules).


>> b) Classes:
>> You can't access the variables of a class in a pure function. But you can 
>> access its `let` properties. That's because as long as there is no `var` in 
>> the dereferencing path, you are guarantied to be accessing a constant. In 
>> classes, `let` properties are thus implicitly pure; stored `var` properties 
>> are not. Which means that pure instance methods on classes can only access 
>> `let` properties, in addition to computed properties that are themselves 
>> `pure` and other `pure` methods.
> 
> What if the “let” property becomes a “var” property in a future version of 
> the library you’re linking against?

That's an interesting question. Either `let` provides purity guaranties 
implicitly (as I was suggesting), or it needs to be annotated `pure` in order 
to provide those guaranties. The later would allow changing a `let` to a `var` 
in a future version of a library without breaking clients. And you could also 
change a `pure let` to a `pure var`. Perhaps being explicit is better. In the 
end, it depends on how resilience works for `let`.

-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Charles Srstka via swift-evolution
> On Feb 20, 2017, at 12:53 PM, Matthew Johnson  wrote:
> 
>> 
>> On Feb 20, 2017, at 12:42 PM, Charles Srstka via swift-evolution 
>> > wrote:
>> 
>>> On Feb 20, 2017, at 10:55 AM, Michel Fortin via swift-evolution 
>>> > wrote:
>>> 
>>> a) Structs/Locals:
>>> Structs and local variables behave similarly. You can access `let` and 
>>> `var` properties and mutate the later.
>> 
>> What if the struct contains class ivars, including private ones that you may 
>> not know about but nonetheless get accessed as a side effect of accessing 
>> the struct’s “var” properties?
> 
> You should be able to access them in accordance with the restrictions on 
> using classes in a pure manner.

How can those restrictions be enforced, if the class is a private internal 
property of the struct that the calling code can’t see?

>>> b) Classes:
>>> You can't access the variables of a class in a pure function. But you can 
>>> access its `let` properties. That's because as long as there is no `var` in 
>>> the dereferencing path, you are guarantied to be accessing a constant. In 
>>> classes, `let` properties are thus implicitly pure; stored `var` properties 
>>> are not. Which means that pure instance methods on classes can only access 
>>> `let` properties, in addition to computed properties that are themselves 
>>> `pure` and other `pure` methods.
>> 
>> What if the “let” property becomes a “var” property in a future version of 
>> the library you’re linking against?
> 
> That would be a breaking change if the `let` was public or if any `pure` 
> public methods were accessing it (unless they were refactored to not rely on 
> it anymore).

I’m not sure how I feel about that, since it hamstrings the ability to improve 
APIs in a lot of ways without breaking backwards compatibility. A quick example 
off the top of my head would be all the Cocoa APIs that started out having 
ivars representing paths backed by simple getter methods, and were later 
refactored to be URL-based, but with the original path properties become 
computed properties pointing to the URL’s “path” property. With this, 
properties would not be able to be refactored in this way unless the library 
developer had previously declared the “path” property as private(set), which is 
unlikely for a property that was not intended to be changed after the class was 
initialized.

Charles

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Matthew Johnson via swift-evolution

> On Feb 20, 2017, at 12:42 PM, Charles Srstka via swift-evolution 
>  wrote:
> 
>> On Feb 20, 2017, at 10:55 AM, Michel Fortin via swift-evolution 
>> > wrote:
>> 
>> a) Structs/Locals:
>> Structs and local variables behave similarly. You can access `let` and `var` 
>> properties and mutate the later.
> 
> What if the struct contains class ivars, including private ones that you may 
> not know about but nonetheless get accessed as a side effect of accessing the 
> struct’s “var” properties?

You should be able to access them in accordance with the restrictions on using 
classes in a pure manner.

> 
>> b) Classes:
>> You can't access the variables of a class in a pure function. But you can 
>> access its `let` properties. That's because as long as there is no `var` in 
>> the dereferencing path, you are guarantied to be accessing a constant. In 
>> classes, `let` properties are thus implicitly pure; stored `var` properties 
>> are not. Which means that pure instance methods on classes can only access 
>> `let` properties, in addition to computed properties that are themselves 
>> `pure` and other `pure` methods.
> 
> What if the “let” property becomes a “var” property in a future version of 
> the library you’re linking against?

That would be a breaking change if the `let` was public or if any `pure` public 
methods were accessing it (unless they were refactored to not rely on it 
anymore).

> 
> 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] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread David Sweeris via swift-evolution

> On Feb 20, 2017, at 10:42 AM, Charles Srstka via swift-evolution 
>  wrote:
> 
>> On Feb 20, 2017, at 10:55 AM, Michel Fortin via swift-evolution 
>> > wrote:
>> 
>> a) Structs/Locals:
>> Structs and local variables behave similarly. You can access `let` and `var` 
>> properties and mutate the later.
> 
> What if the struct contains class ivars, including private ones that you may 
> not know about but nonetheless get accessed as a side effect of accessing the 
> struct’s “var” properties?
> 
>> b) Classes:
>> You can't access the variables of a class in a pure function. But you can 
>> access its `let` properties. That's because as long as there is no `var` in 
>> the dereferencing path, you are guarantied to be accessing a constant. In 
>> classes, `let` properties are thus implicitly pure; stored `var` properties 
>> are not. Which means that pure instance methods on classes can only access 
>> `let` properties, in addition to computed properties that are themselves 
>> `pure` and other `pure` methods.
> 
> What if the “let” property becomes a “var” property in a future version of 
> the library you’re linking against?

I think that’d be considered a breaking change anyway, since “let” means 
“immutable” whereas vars with inaccessible setters merely can’t be mutated by 
clients.

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Charles Srstka via swift-evolution
> On Feb 20, 2017, at 10:55 AM, Michel Fortin via swift-evolution 
>  wrote:
> 
> a) Structs/Locals:
> Structs and local variables behave similarly. You can access `let` and `var` 
> properties and mutate the later.

What if the struct contains class ivars, including private ones that you may 
not know about but nonetheless get accessed as a side effect of accessing the 
struct’s “var” properties?

> b) Classes:
> You can't access the variables of a class in a pure function. But you can 
> access its `let` properties. That's because as long as there is no `var` in 
> the dereferencing path, you are guarantied to be accessing a constant. In 
> classes, `let` properties are thus implicitly pure; stored `var` properties 
> are not. Which means that pure instance methods on classes can only access 
> `let` properties, in addition to computed properties that are themselves 
> `pure` and other `pure` methods.

What if the “let” property becomes a “var” property in a future version of the 
library you’re linking against?

Charles

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Matthew Johnson via swift-evolution

> On Feb 20, 2017, at 10:55 AM, Michel Fortin via swift-evolution 
>  wrote:
> 
> (continuing my thoughts from my previous post)
> 
> I think a definition of `pure` that'd work well for Swift is one that is 
> based on forbidding dereferencing of pointers (including object references) 
> so that all you ever deal with is value semantics. With some exceptions for 
> dereferencing when value semantics are preserved. Here's how it could work 
> inside a pure function:
> 
> a) Structs/Locals:
> Structs and local variables behave similarly. You can access `let` and `var` 
> properties and mutate the later.

Agree

> 
> b) Classes:
> You can't access the variables of a class in a pure function. But you can 
> access its `let` properties. That's because as long as there is no `var` in 
> the dereferencing path, you are guarantied to be accessing a constant. In 
> classes, `let` properties are thus implicitly pure; stored `var` properties 
> are not. Which means that pure instance methods on classes can only access 
> `let` properties, in addition to computed properties that are themselves 
> `pure` and other `pure` methods.

Agree

> 
> c) Classes (uniquely referenced):
> When a class is uniquely referenced (which you can check at runtime with 
> `isUniquelyReferenced`), then it's safe to access its `var` properties within 
> a pure function. There is no compiler-enforced system to deal with that 
> however, so you'll need a way to vouch for this. Instead of vouching, a 
> safety mechanism could be built for that by statically enforcing cases where 
> a class is known to be uniquely referenced.

That’s an interesting idea.

> 
> d) Copy on Write:
> COW is built on top of uniquely referenced classes. COW also needs read 
> access to the storage when not uniquely referenced (so you can make a copy) 
> which, again, would require vouching. Instead of vouching, a safety mechanism 
> could be built to statically enforce that some instance variables (those that 
> need to be copied) are only writable when the class is uniquely referenced 
> but can otherwise be read at any time (perhaps by adding an attribute to 
> those variables). This protects the pure function from external interference.

This sounds like a promising approach.

> 
> e) Generic Containers:
> Generic containers that impose requirements on their elements will pose some 
> additional problems, for instance: `Set.insert` needs to call `hashValue` and 
> `==` on its elements, making the purity of `Set.insert` constrained by the 
> purity of those functions. Without a way to express this kind of conditional 
> purity, `Set` and `Dictionary` cannot be pure.

Could we use a mechanism similar to `rethrows` to address this kind of 
transitive purity?  We have already discussed something along those lines for 
handling functions passed as arguments.  Maybe that mechanism could be designed 
to handle this use case as well.

> 
> I feel enforcement for (c) and (d) needs to be implemented first if you are 
> to implement `pure` this way so you aren't over-reliant on vouching at every 
> corner. Perhaps you won't even need a vouching mechanism once that's done.
> 
> 
>> Le 20 févr. 2017 à 11:24, Michel Fortin via swift-evolution 
>>  a écrit :
>> 
>> Le 20 févr. 2017 à 1:19, David Sweeris  a écrit :
>>> 
>>> On Feb 19, 2017, at 21:19, Xiaodi Wu  wrote:
>>> 
 This is very, very interesting. Thank you so much for the text.
 
 If I understand your take correctly, the benefits of `pure` in Swift would 
 be contingent on how pervasively it can be used (as it's the composability 
 of pure functions that gives it exponential value). And, based on your 
 discussion, very few functions in Swift would be compiler-provably pure 
 [...]
>>> 
>>> I think this might, at least partly, be because we can't restrict generic 
>>> parameters to be value types.
>> 
>> That's somewhat a problem.
>> 
>> But think a bit about the copy-on-write containers. Because the compiler 
>> itself has no notion of copy-on-write semantics, the compiler can't prove 
>> that COW types behave correctly as value types. The optimizer would have to 
>> make the pessimistic assumption that dereferencing the pointer is possibly a 
>> dependence on external state, making the function unoptimizable. Basically, 
>> any struct with a pointer (or object reference) would need to be vouched for 
>> with a "trust me" attribute, or not be vouched for if it doesn't fit value 
>> semantics.
>> 
>> And, as you say, generic containers value-typeness will depend on their 
>> generic arguments.
>> 
>> But... keep in mind that for the purpose of evaluating whether a function is 
>> pure (as in strongly, optimizable pure), what matters really is not the type 
>> but what you do with it. `Optional` is not what you would call a 
>> value type, but it does behave as a value type as long as you only 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Matthew Johnson via swift-evolution

> On Feb 20, 2017, at 10:24 AM, Michel Fortin via swift-evolution 
>  wrote:
> 
> Le 20 févr. 2017 à 1:19, David Sweeris  a écrit :
>> 
>> On Feb 19, 2017, at 21:19, Xiaodi Wu  wrote:
>> 
>>> This is very, very interesting. Thank you so much for the text.
>>> 
>>> If I understand your take correctly, the benefits of `pure` in Swift would 
>>> be contingent on how pervasively it can be used (as it's the composability 
>>> of pure functions that gives it exponential value). And, based on your 
>>> discussion, very few functions in Swift would be compiler-provably pure 
>>> [...]
>> 
>> I think this might, at least partly, be because we can't restrict generic 
>> parameters to be value types.
> 
> That's somewhat a problem.
> 
> But think a bit about the copy-on-write containers. Because the compiler 
> itself has no notion of copy-on-write semantics, the compiler can't prove 
> that COW types behave correctly as value types. The optimizer would have to 
> make the pessimistic assumption that dereferencing the pointer is possibly a 
> dependence on external state, making the function unoptimizable. Basically, 
> any struct with a pointer (or object reference) would need to be vouched for 
> with a "trust me" attribute, or not be vouched for if it doesn't fit value 
> semantics.

So maybe we should solve this problem before tackling pure functions.

> And, as you say, generic containers value-typeness will depend on their 
> generic arguments.
> 
> But... keep in mind that for the purpose of evaluating whether a function is 
> pure (as in strongly, optimizable pure), what matters really is not the type 
> but what you do with it. `Optional` is not what you would call a 
> value type, but it does behave as a value type as long as you only compare it 
> to `nil`, since you never access the object.
> 
> D doesn't make this fine-grained distinction and is fine in most cases 
> because it has transitive immutability. Swift doesn't have that, so maybe we 
> should try something a bit different.

Are there any avenues you can forsee to improving Swift such that we could have 
a similarly robust and verified `pure` as D?  In other words, is transitive 
immutability a necessary requirement to doing this or might there be other 
mechanisms that fit better in Swift, but could accomplish the same goals with 
respect to verified purity?

> 
> 
> -- 
> Michel Fortin
> https://michelf.ca
> 
> ___
> 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] Support for pure functions. Part n + 1.

2017-02-20 Thread Michel Fortin via swift-evolution
(continuing my thoughts from my previous post)

I think a definition of `pure` that'd work well for Swift is one that is based 
on forbidding dereferencing of pointers (including object references) so that 
all you ever deal with is value semantics. With some exceptions for 
dereferencing when value semantics are preserved. Here's how it could work 
inside a pure function:

a) Structs/Locals:
Structs and local variables behave similarly. You can access `let` and `var` 
properties and mutate the later.

b) Classes:
You can't access the variables of a class in a pure function. But you can 
access its `let` properties. That's because as long as there is no `var` in the 
dereferencing path, you are guarantied to be accessing a constant. In classes, 
`let` properties are thus implicitly pure; stored `var` properties are not. 
Which means that pure instance methods on classes can only access `let` 
properties, in addition to computed properties that are themselves `pure` and 
other `pure` methods.

c) Classes (uniquely referenced):
When a class is uniquely referenced (which you can check at runtime with 
`isUniquelyReferenced`), then it's safe to access its `var` properties within a 
pure function. There is no compiler-enforced system to deal with that however, 
so you'll need a way to vouch for this. Instead of vouching, a safety mechanism 
could be built for that by statically enforcing cases where a class is known to 
be uniquely referenced.

d) Copy on Write:
COW is built on top of uniquely referenced classes. COW also needs read access 
to the storage when not uniquely referenced (so you can make a copy) which, 
again, would require vouching. Instead of vouching, a safety mechanism could be 
built to statically enforce that some instance variables (those that need to be 
copied) are only writable when the class is uniquely referenced but can 
otherwise be read at any time (perhaps by adding an attribute to those 
variables). This protects the pure function from external interference.

e) Generic Containers:
Generic containers that impose requirements on their elements will pose some 
additional problems, for instance: `Set.insert` needs to call `hashValue` and 
`==` on its elements, making the purity of `Set.insert` constrained by the 
purity of those functions. Without a way to express this kind of conditional 
purity, `Set` and `Dictionary` cannot be pure.

I feel enforcement for (c) and (d) needs to be implemented first if you are to 
implement `pure` this way so you aren't over-reliant on vouching at every 
corner. Perhaps you won't even need a vouching mechanism once that's done.


> Le 20 févr. 2017 à 11:24, Michel Fortin via swift-evolution 
>  a écrit :
> 
> Le 20 févr. 2017 à 1:19, David Sweeris  a écrit :
>> 
>> On Feb 19, 2017, at 21:19, Xiaodi Wu  wrote:
>> 
>>> This is very, very interesting. Thank you so much for the text.
>>> 
>>> If I understand your take correctly, the benefits of `pure` in Swift would 
>>> be contingent on how pervasively it can be used (as it's the composability 
>>> of pure functions that gives it exponential value). And, based on your 
>>> discussion, very few functions in Swift would be compiler-provably pure 
>>> [...]
>> 
>> I think this might, at least partly, be because we can't restrict generic 
>> parameters to be value types.
> 
> That's somewhat a problem.
> 
> But think a bit about the copy-on-write containers. Because the compiler 
> itself has no notion of copy-on-write semantics, the compiler can't prove 
> that COW types behave correctly as value types. The optimizer would have to 
> make the pessimistic assumption that dereferencing the pointer is possibly a 
> dependence on external state, making the function unoptimizable. Basically, 
> any struct with a pointer (or object reference) would need to be vouched for 
> with a "trust me" attribute, or not be vouched for if it doesn't fit value 
> semantics.
> 
> And, as you say, generic containers value-typeness will depend on their 
> generic arguments.
> 
> But... keep in mind that for the purpose of evaluating whether a function is 
> pure (as in strongly, optimizable pure), what matters really is not the type 
> but what you do with it. `Optional` is not what you would call a 
> value type, but it does behave as a value type as long as you only compare it 
> to `nil`, since you never access the object.
> 
> D doesn't make this fine-grained distinction and is fine in most cases 
> because it has transitive immutability. Swift doesn't have that, so maybe we 
> should try something a bit different.
> 
> 
> -- 
> Michel Fortin
> https://michelf.ca
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-- 
Michel Fortin
https://michelf.ca

___
swift-evolution mailing list

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-20 Thread Michel Fortin via swift-evolution
Le 20 févr. 2017 à 1:19, David Sweeris  a écrit :
> 
> On Feb 19, 2017, at 21:19, Xiaodi Wu  wrote:
> 
>> This is very, very interesting. Thank you so much for the text.
>> 
>> If I understand your take correctly, the benefits of `pure` in Swift would 
>> be contingent on how pervasively it can be used (as it's the composability 
>> of pure functions that gives it exponential value). And, based on your 
>> discussion, very few functions in Swift would be compiler-provably pure [...]
> 
> I think this might, at least partly, be because we can't restrict generic 
> parameters to be value types.

That's somewhat a problem.

But think a bit about the copy-on-write containers. Because the compiler itself 
has no notion of copy-on-write semantics, the compiler can't prove that COW 
types behave correctly as value types. The optimizer would have to make the 
pessimistic assumption that dereferencing the pointer is possibly a dependence 
on external state, making the function unoptimizable. Basically, any struct 
with a pointer (or object reference) would need to be vouched for with a "trust 
me" attribute, or not be vouched for if it doesn't fit value semantics.

And, as you say, generic containers value-typeness will depend on their generic 
arguments.

But... keep in mind that for the purpose of evaluating whether a function is 
pure (as in strongly, optimizable pure), what matters really is not the type 
but what you do with it. `Optional` is not what you would call a 
value type, but it does behave as a value type as long as you only compare it 
to `nil`, since you never access the object.

D doesn't make this fine-grained distinction and is fine in most cases because 
it has transitive immutability. Swift doesn't have that, so maybe we should try 
something a bit different.


-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-19 Thread Michel Fortin via swift-evolution
The message about D was from me. I'm actually quite familiar with D so I'll try 
to summarize it's take on purity here.

# Pure in D

D has the keyword `pure`, and the compiler enforces purity constraints. There 
is basically two types of pure functions: strongly pure ones and weakly pure 
one, but in general when writing code you can ignore the distinction: they all 
use the same `pure` attribute. The strongly pure one is the kind that can be 
optimized because it has no side effect and its result can be reused. The 
weakly pure one is the kind that takes pointers to non-immutable memory and for 
which you either cannot guaranty a stable result across calls or cannot 
guaranty it won't mutate the memory behind those pointers. (Keep in mind that 
object references are a kind of pointer too.) The compiler examine the type of 
the parameters of a pure function to determine if they contain pointers 
(including pointers hidden in structs) and classify it as weakly or strongly 
pure.

Pure functions are allowed to throw, to exit the program, to run infinite 
loops, and to allocate memory. They can't access global variables unless they 
are immutable (constant), or they are passed as an argument using a pointer. 

All pure functions can only call other pure functions. This is the part where 
weakly pure is useful: a strongly pure function can call a weakly pure function 
since the weakly pure one will only be able to mutate the local state of the 
enclosing strongly pure function, always in a deterministic way.

In D, `const` and `immutable` are transitive attributes, meaning that any 
memory accessed through such pointer is also `const` or `immutable`. So if you 
pass a `const` or `immutable` value to a function in D, it won't be able to 
mutate anything. This makes many functions strongly pure even in the presence 
of pointers.

`pure` in D can also be used to create guarantied uniquely referenced objects 
and object hierarchies, which then can then become transitively immutable once 
they are returned by the pure function.

`pure` works so well in D that most functions are actually pure. There is some 
pressure in libraries to mark functions as pure because their functions then 
become usable inside other pure functions, which means that as time passes more 
and more functions get the pure attribute. To ease the burden of adding these 
attributes everywhere, pure is inferred for template functions (and only 
template functions, because non templates are allowed to be opaque).

Official reference: https://dlang.org/spec/function.html#pure-functions

# Pure in Swift?

Because Swift does not have that concept of transitive immutability, I'm under 
the impression that very few functions would be "strongly pure" in Swift, 
making optimizations impossible except for the trivial value types. Or, maybe, 
when a "trust me" attribute vouch that the implementation of a value type is 
pure-compatible.

But I'd be wary about relying much on a "trust me" attribute, as it greatly 
diminish the value of having `pure` in the first place. Add a "trust me" at the 
wrong place and the compiler will not complain when it should. Forget a "trust 
me" somewhere and the compiler will complain where it should not. The ratio of 
"trust me"/`pure` has to be very small for the whole purity system to be 
valuable.

The way I see it, `pure` is likely to make things more complicated for 
everyone, not just for those who want to use pure. Those who want to use pure 
will be asking for everything they want to use to be labeled correctly (either 
with `pure` or "trust me", whichever works).

# What about constexpr?

That's the name of a C++ feature where the compiler evaluates a function at 
compile time to set the value of a constant. This obviously only works for 
functions with no side effects. `constexpr` is the keyword attached to those 
functions.
http://en.cppreference.com/w/cpp/language/constexpr

The difference from `pure` is that this happens only at compile time. Which 
means you can implement it like D has done instead: treat all functions as 
evaluatable and only stop and emit an error upon reaching an instruction that 
cannot be evaluated. No special attribute needed. Only works for functions 
where the source code is available.
https://dlang.org/spec/function.html#interpretation

The D approach won't work for Swift across module boundaries, except perhaps 
for functions that can be inlined. For resilience you might want an attribute 
to make it a contract that the inline version is compile-time evaluable.


Le 19 févr. 2017 à 20:58, Xiaodi Wu via swift-evolution 
 a écrit :
> 
> I don't know very much about this topic, so I won't pretend that I have 
> strong feelings about Michel's questions, but they are undeniably important 
> and undoubtedly only one of many.
> 
> Before we get to any syntactic bikeshedding, can the proponents of this 
> feature write up a comparative summary to educate us about 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-19 Thread Xiaodi Wu via swift-evolution
I don't know very much about this topic, so I won't pretend that I have
strong feelings about Michel's questions, but they are undeniably important
and undoubtedly only one of many.

Before we get to any syntactic bikeshedding, can the proponents of this
feature write up a comparative summary to educate us about the current
state of the art? How have other languages have defined purity? I recall an
earlier message about D, and some rough comparisons or non-comparisons to
C++ constexpr. Roughly, it would be very helpful to get some sense of the
following:

What other C-family languages have a concept of purity?

How is purity defined in those languages?

What use cases are enabled by those definitions of purity, and just as
important, what use cases are notably excluded by them?

If there is evidence in the public record to this effect: if the designers
of those languages could do it again, have they expressed any thoughts
about how they would do it differently with respect to purity?

It has been said that Haskell and other functional languages prioritize
purity over ergonomics of impure functions like I/O. With that in mind,
what design choices surrounding purity made by those languages are
off-limits for Swift?

What use cases or even compiler optimizations are possible in Haskell and
other non-C family languages with a more expansive or stricter concept of
pure functions that we don't find in C-family languages?

If Swift were to adopt some of these beyond-C rules, how would that impact
the user experience with common impure functions (I/O, etc.)?

On Sun, Feb 19, 2017 at 14:45 T.J. Usiyan via swift-evolution <
swift-evolution@swift.org> wrote:

> I'm going to update the draft with points addressed here and the twitter
> conversation. There have been quite a few implications to consider pointed
> out.
>
> This feature is not 'for' the compiler as much as it is for humans writing
> code, but I will address that in the update.
>
> On Sun, Feb 19, 2017 at 3:34 PM, David Sweeris 
> wrote:
>
>
> On Feb 19, 2017, at 11:47, Michel Fortin via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> 7. Is it desirable that the optimizer sometime take the pure attribute to
> heart to combine multiple apparently redundant calls into a single one? Or
> is pure not intended to be usable for compiler optimizations? The ability
> to optimize will likely be affected by the answer to these question and the
> loopholes you are willing to allow.
>
>
> AFAIK, "compiler optimizations" are main point of having a keyword for
> pure functions. (Well, that and whatever role it might play in supporting
> constant expressions, but that seems like more of a compiler implementation
> detail than an actual "feature" of pure functions.)
>
> Calling fatalError() is fine IMHO because, at that point, any side-effects
> become a moot point.
>
> I'm inclined to say that passing in reference values is ok, as long as we
> can prove the function doesn't modify anything. Don't know how we'd do
> that, though, since classes don't need that `mutating` keyword for
> functions that mutate `self`.
>
> If someone is determined to use pointers to pointers to get global state
> or something to trick the compiler into accepting *semantically* impure
> code as *syntactically* pure, I'm not sure there's a way we can really
> stop them. Not and still have @pure be useful. (Or maybe we can... I'm
> merely thinking of the saying, "every time someone builds a fool-proof
> system, the world makes a bigger fool".)
>
> I would think that allocating memory is ok, as long as it's either
> deallocated by the time the function exits or it's part of the return
> value, but I don't know a lot about low-level implementation details, so
> maybe there's something I'm missing. If that is a problem, though, I think
> the answer to your "what subset..." question would, more or less, be
> whatever subset doesn't rely on the runtime (the usefulness of that subset
> should expand if/when we extend the syntax around tuples or support
> fixed-length arrays in some other way).
>
> In any case, yeah, IMHO you're correct that we should nail down the
> semantics before worrying so much about the syntax.
>
> - 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] [Pitch] Support for pure functions. Part n + 1.

2017-02-19 Thread T.J. Usiyan via swift-evolution
I'm going to update the draft with points addressed here and the twitter
conversation. There have been quite a few implications to consider pointed
out.

This feature is not 'for' the compiler as much as it is for humans writing
code, but I will address that in the update.

On Sun, Feb 19, 2017 at 3:34 PM, David Sweeris  wrote:

>
> On Feb 19, 2017, at 11:47, Michel Fortin via swift-evolution <
> swift-evolution@swift.org> wrote:
>
>
> 7. Is it desirable that the optimizer sometime take the pure attribute to
> heart to combine multiple apparently redundant calls into a single one? Or
> is pure not intended to be usable for compiler optimizations? The ability
> to optimize will likely be affected by the answer to these question and the
> loopholes you are willing to allow.
>
>
> AFAIK, "compiler optimizations" are main point of having a keyword for
> pure functions. (Well, that and whatever role it might play in supporting
> constant expressions, but that seems like more of a compiler implementation
> detail than an actual "feature" of pure functions.)
>
> Calling fatalError() is fine IMHO because, at that point, any side-effects
> become a moot point.
>
> I'm inclined to say that passing in reference values is ok, as long as we
> can prove the function doesn't modify anything. Don't know how we'd do
> that, though, since classes don't need that `mutating` keyword for
> functions that mutate `self`.
>
> If someone is determined to use pointers to pointers to get global state
> or something to trick the compiler into accepting *semantically* impure
> code as *syntactically* pure, I'm not sure there's a way we can really
> stop them. Not and still have @pure be useful. (Or maybe we can... I'm
> merely thinking of the saying, "every time someone builds a fool-proof
> system, the world makes a bigger fool".)
>
> I would think that allocating memory is ok, as long as it's either
> deallocated by the time the function exits or it's part of the return
> value, but I don't know a lot about low-level implementation details, so
> maybe there's something I'm missing. If that is a problem, though, I think
> the answer to your "what subset..." question would, more or less, be
> whatever subset doesn't rely on the runtime (the usefulness of that subset
> should expand if/when we extend the syntax around tuples or support
> fixed-length arrays in some other way).
>
> In any case, yeah, IMHO you're correct that we should nail down the
> semantics before worrying so much about the syntax.
>
> - Dave Sweeris
>
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-19 Thread David Sweeris via swift-evolution

> On Feb 19, 2017, at 11:47, Michel Fortin via swift-evolution 
>  wrote:
> 
> 7. Is it desirable that the optimizer sometime take the pure attribute to 
> heart to combine multiple apparently redundant calls into a single one? Or is 
> pure not intended to be usable for compiler optimizations? The ability to 
> optimize will likely be affected by the answer to these question and the 
> loopholes you are willing to allow.

AFAIK, "compiler optimizations" are main point of having a keyword for pure 
functions. (Well, that and whatever role it might play in supporting constant 
expressions, but that seems like more of a compiler implementation detail than 
an actual "feature" of pure functions.)

Calling fatalError() is fine IMHO because, at that point, any side-effects 
become a moot point.

I'm inclined to say that passing in reference values is ok, as long as we can 
prove the function doesn't modify anything. Don't know how we'd do that, 
though, since classes don't need that `mutating` keyword for functions that 
mutate `self`.

If someone is determined to use pointers to pointers to get global state or 
something to trick the compiler into accepting semantically impure code as 
syntactically pure, I'm not sure there's a way we can really stop them. Not and 
still have @pure be useful. (Or maybe we can... I'm merely thinking of the 
saying, "every time someone builds a fool-proof system, the world makes a 
bigger fool".)

I would think that allocating memory is ok, as long as it's either deallocated 
by the time the function exits or it's part of the return value, but I don't 
know a lot about low-level implementation details, so maybe there's something 
I'm missing. If that is a problem, though, I think the answer to your "what 
subset..." question would, more or less, be whatever subset doesn't rely on the 
runtime (the usefulness of that subset should expand if/when we extend the 
syntax around tuples or support fixed-length arrays in some other way).

In any case, yeah, IMHO you're correct that we should nail down the semantics 
before worrying so much about the syntax.

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-19 Thread Matthew Johnson via swift-evolution

> On Feb 19, 2017, at 1:47 PM, Michel Fortin via swift-evolution 
>  wrote:
> 
> I'm a bit disappointed to see this discussion bikeshedding the syntax without 
> clarifying much the semantics. Here's a few question of semantic nature.

+1.  I think the syntactic questions are important mostly because we need an 
answer that works for something as lightweight as a single expression closure 
without sacrificing the syntactic concision.  But the semantic questions are 
far more important and complex.

> 
> The base principle of a pure function is that it has no side effects. But 
> it's quite clear that at least some side effects will need to be allowed. So 
> which ones?
> 
> 1. Many basic calculations will leave flags in registers that persist until 
> the next computation. Those can be checked by the program later (after the 
> function is run in some cases). That's probably a side effect you want to 
> ignore.
> 
> 2. Floating point operations can give different results depending on flags 
> you can set in the registers. Things like setting the rounding mode for 
> instance. Will the pure function need to reset those flags before performing 
> floating point operations so it can guaranty the same result every time? What 
> are the implication if those are ignored?
> 
> 3. Is a pure function allowed to dereference pointers or object references 
> passed as parameters? A pointer or an object reference might provide access 
> to the global state of the program.

The answer I’ve seen thus far is yes, but only if the state that is referenced 
is constant after initialization or the access is marked with some kind of 
“trust me” annotation.

> 
> 4. Allocating memory requires access to the global memory layout of the 
> program. And allocating will give you a different memory address every time. 
> Are you allowed to allocate memory in a pure function?

I think we have to allow this (i.e. to lazily initialize a memorization cache) 
but it should probably require the “trust me” annotation.

> 
> 5. Many basic operations in the language will implicitly allocate memory or 
> dereference pointers. Same for the containers in the standard library. If you 
> don't allow memory allocations or pointer dereferencing, what subset of the 
> language is still usable in a pure function?

This feels the same as #4.  There will be parts of the standard library that 
use the “trust me” annotation and are therefore considered pure at the point of 
use despite doing these things. 

> 
> 6. If you do allow memory allocations inside the function, is it safe to 
> instantiate and return a new class? 

This is an interesting question.  If the instance is immutable my instinct is 
yes, at least in many cases (immutable classes can have value semantics).  If 
not, probably not?

> 
> 7. Is it desirable that the optimizer sometime take the pure attribute to 
> heart to combine multiple apparently redundant calls into a single one? Or is 
> pure not intended to be usable for compiler optimizations? The ability to 
> optimize will likely be affected by the answer to these question and the 
> loopholes you are willing to allow.

I think the answer has to be yes.  If it isn’t, what kind of purity do we 
really have?

This seems like a very good criteria to keep in mind in answering all of these 
questions.

> 
> 8. Is exiting the program (`fatalError`, etc.) allowed? That's a pretty big 
> side effect. Although it could also be considered as no side effect since the 
> program cannot go further.

Good question.  Does a pure function have to be total?  Allowing `fatalError` 
in a pure function is kind of like allowing it to be partial.  Some inputs 
crash rather than produce a result.  I would like to say no, but I think the 
engineering tradeoffs already made in Swift require us to say yes.  If not, you 
couldn’t do anything that might cause the language or library to trap (array 
subscript for example).

> 
> 9. Is throwing allowed? Maybe the thrown error should considered simply as 
> different return value.

Yes, throwing should be allowed as long as the same error is always thrown for 
the same input.  Consider Joe Groff’s recent suggestion for typed error 
handling.  Under that proposal *every* function can be thought of as returning 
a `Result`.  The error type for non-throwing functions is `Never` and for 
untyped throwing functions it is `Error`.  Throwing is implemented differently 
than a `Result` return type is conceptually similar.

> 
> 10. Is += allowed inside a pure function? Operators are functions too, but 
> can += be made pure with `inout` and no return value?

Local mutation should be allowed.  Mutation that can affect external state 
should not.  This is one of the really great aspects of the value semantics 
approach to values as opposed to the immutable / pure functional approach to 
values.

> 
> 11. Can you use a BigInt implementation in a pure function? BigInt needs to 
> allocate 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-19 Thread Michel Fortin via swift-evolution
I'm a bit disappointed to see this discussion bikeshedding the syntax without 
clarifying much the semantics. Here's a few question of semantic nature.

The base principle of a pure function is that it has no side effects. But it's 
quite clear that at least some side effects will need to be allowed. So which 
ones?

1. Many basic calculations will leave flags in registers that persist until the 
next computation. Those can be checked by the program later (after the function 
is run in some cases). That's probably a side effect you want to ignore.

2. Floating point operations can give different results depending on flags you 
can set in the registers. Things like setting the rounding mode for instance. 
Will the pure function need to reset those flags before performing floating 
point operations so it can guaranty the same result every time? What are the 
implication if those are ignored?

3. Is a pure function allowed to dereference pointers or object references 
passed as parameters? A pointer or an object reference might provide access to 
the global state of the program.

4. Allocating memory requires access to the global memory layout of the 
program. And allocating will give you a different memory address every time. 
Are you allowed to allocate memory in a pure function?

5. Many basic operations in the language will implicitly allocate memory or 
dereference pointers. Same for the containers in the standard library. If you 
don't allow memory allocations or pointer dereferencing, what subset of the 
language is still usable in a pure function?

6. If you do allow memory allocations inside the function, is it safe to 
instantiate and return a new class? 

7. Is it desirable that the optimizer sometime take the pure attribute to heart 
to combine multiple apparently redundant calls into a single one? Or is pure 
not intended to be usable for compiler optimizations? The ability to optimize 
will likely be affected by the answer to these question and the loopholes you 
are willing to allow.

8. Is exiting the program (`fatalError`, etc.) allowed? That's a pretty big 
side effect. Although it could also be considered as no side effect since the 
program cannot go further.

9. Is throwing allowed? Maybe the thrown error should considered simply as 
different return value.

10. Is += allowed inside a pure function? Operators are functions too, but can 
+= be made pure with `inout` and no return value?

11. Can you use a BigInt implementation in a pure function? BigInt needs to 
allocate internally.

13. Say you want to keep logs of what happens in the function in order to debug 
something: is there an "unsafe" way to do IO for that purpose? Or maybe you 
want to implement `fatalError` as a pure function: is there a way to print 
something before exiting?

Basically, there is no such thing as "no side effect". You need to pick which 
side effects are acceptable and then evaluate where your picks puts you on the 
scale between too lax (and of little utility) and too restrictive (and not 
usable outside of trivial examples). It might be a good idea to make the answer 
to all those questions clear in the proposal so people have an idea of what 
they can expect pure functions to do and what guaranties they provide.


-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-18 Thread David Hart via swift-evolution


> On 17 Feb 2017, at 23:30, Matthew Johnson via swift-evolution 
>  wrote:
> 
> 
>> On Feb 17, 2017, at 4:17 PM, Daniel Leping  wrote:
>> 
>> I don't think I can (fully) agree with you, because a closure purity is not 
>> something you "define". It's rather what you use inside. Though I totally 
>> understand your concern and a wish to have localized errors.
>> 
>> However, I think it's totally consistent if you use a full form in a way:
>> 
>> { (a) => B in
>> return a.toB()
>> }
>> 
>> What I mean is that short form can auto determine. If you want to be 
>> explicit... use the long form.
>> 
>> Would this work for you, @Matthew?
> 
> What I am saying is that I don’t think I should have to use the entire long 
> form just to specify it’s a pure closure.  Something like the following would 
> be acceptable:
> 
> {= $0.some.pure.expression() }
> or
> {=> $0.some.pure.expression() }

Or:
{ x => x.some.pure.expression() }

> But I don’t want to be required to write out a name for the arguments and a 
> return type for single expression closures like this.
> 
>> 
>> On Sat, 18 Feb 2017 at 0:09 Matthew Johnson  wrote:
 On Feb 17, 2017, at 4:05 PM, Daniel Leping  
 wrote:
 
 I personally like a lot => syntax for several reasons:
 1. Consistent
 2. Enforced return type
 
 As for the closures, I don't think we need an indication here. If it calls 
 any impure function or captures a variable from outside - it's impure by 
 definition. The compiler should decide if a closure can be treated pure. 
 Same as with throwing.
>>> 
>>> I’m not sure about this.  I would like the ability to syntactically state 
>>> the intent that a closure is pure, and ideally do so in a way that doesn’t 
>>> lose the conciseness of the closure (i.e. we shouldn’t have to give up any 
>>> of the syntactic sugar available for simple closures).  A big benefit of 
>>> allowing us to state intent like this is that it localizes error messages.
>>> 
 
 As for the situation with currying (and other compositions), the situation 
 is a lot more complicated than with rethrows. However, it's still 
 deductible in compile time with the same mechanism as described above for 
 closures.
 
 I tend to agree we could use ~> (looks good to me... volatile :)) for the 
 function type definitions as an "unknown purity". The return type purity 
 dependence graph can be built automatically at compile time. With this 
 graph compiler can determine the returned function purity in every place 
 function is used.
 
 The use of ~> should of course be limited to argument and return types of 
 pure functions only. I think there might be a possibility of use in 
 typealias, but need to think more about it.
 
> On Fri, 17 Feb 2017 at 22:59 Matthew Johnson via swift-evolution 
>  wrote:
 
> On Feb 17, 2017, at 2:52 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> Out of curiosity, what are the benefits to being able to define that a 
> closure must be pure as a parameter/type definition, as opposed to 
> defining a particular closure to being pure while being passed?  What 
> guarantees does it give you as the caller of the closure?
 
 If you only accept pure closures and otherwise meet the criteria of a pure 
 function then you are pure.  If you have a function like that and want to 
 accept both pure and impure closures and receive the purity of the closure 
 provided then we need syntax indicating something similar to `rethrows`, 
 but for purity.
 
> 
> Thanks,
> Jon
> 
> 
>> On Feb 16, 2017, at 1:18 PM, T.J. Usiyan  wrote:
>> 
>> I am ok with a keyword but `pure` in front of func doesn't work well 
>> with inline closures.
>> 
>> A few people talked through many of these issues starting with this 
>> tweet. https://twitter.com/griotspeak/status/832247545325842432
>> 
>> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull  wrote:
>> +1 for the idea of pure functions in swift.  Seems like it would enable 
>> a lot of good optimizations (in some cases even just evaluating the 
>> function at compile time).
>> 
>> -1 on the specific notation.  I would much rather just put the word 
>> ‘pure’ in front of ‘func’, the same way we put ‘mutating' in front of 
>> mutating functions… it seems to me like these are part of the same 
>> family.
>> 
>> I agree we should allow inout.
>> 
>> Thanks,
>> Jon
>> 
>>> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution 
>>>  wrote:
>>> 
>>> # Pure Functions
>>> 
>>> * Proposal: 
>>> 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Abe Schneider via swift-evolution
I might(?) agree with others that  `constexpr` might overlap but be
ultimately different from `pure`. However, to me `constexpr` is more
interesting because it would provide a potential macro language.

As for syntax, while I think that matters less, I suspect trying to
find why code isn't working and having to find a "->" vs. "=>" might
be difficult.

As for the pure aspect, couldn't that compiler just look at the
arguments and determine that the function has no side effects? The
only complication comes when its a method to a class. However,
something like the c++ notation of:

int bar() const { ... }

could be used. However, it might be more Swiftly to do something like:

   const func bar() -> int { ... }

as others have suggested. This would make many non-member functions
automatically get made into purely-functional forms (with potential
optimizations). You should be able to do the same thing with type
methods (static/class).

On Fri, Feb 17, 2017 at 11:18 AM, Anton Zhilin  wrote:
> I didn’t mean to emphasize any specific syntax. I’m fine with either @const,
> @constexpr, @pure or =>.
> Anyway, I see no reason why generic functions shouldn’t be supported in any
> of the suggested models.
>
> 2017-02-17 19:08 GMT+03:00 Abe Schneider :
>>
>> +1. I think this is a great idea. As I was following this thread, I
>> was wondering if someone might suggest the C++ constexpr syntax.
>>
>> Would this support generics? E.g. could you do:
>>
>> @constepxr
>> func foo(a:S, b:S) {
>>return a+b
>> }
>>
>> and have that be done at compile time? While this could potentially
>> add a huge amount of complication on the backend, I could this as
>> being useful (also related to my previous postings as to having a way
>> of determining generic types at compile time).
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Daniel Leping via swift-evolution
Second is better, but still looks ugly (no offense). I personally am
totally ok with auto determination for most cases. Explicit case doesn't
sound to me so widely used. I agree an explicit form might be of use in
some rare scenarios and as long there is a possibility to define the purity
(even in a long form) I'm ok with it.


On Sat, 18 Feb 2017 at 0:30 Matthew Johnson  wrote:

> On Feb 17, 2017, at 4:17 PM, Daniel Leping 
> wrote:
>
> I don't think I can (fully) agree with you, because a closure purity is
> not something you "define". It's rather what you use inside. Though I
> totally understand your concern and a wish to have localized errors.
>
> However, I think it's totally consistent if you use a full form in a way:
>
> { (a) => B in
> return a.toB()
> }
>
> What I mean is that short form can auto determine. If you want to be
> explicit... use the long form.
>
> Would this work for you, @Matthew?
>
>
> What I am saying is that I don’t think I should have to use the entire
> long form just to specify it’s a pure closure.  Something like the
> following would be acceptable:
>
> {= $0.some.pure.expression() }
> or
> {=> $0.some.pure.expression() }
>
> But I don’t want to be required to write out a name for the arguments and
> a return type for single expression closures like this.
>
>
> On Sat, 18 Feb 2017 at 0:09 Matthew Johnson 
> wrote:
>
> On Feb 17, 2017, at 4:05 PM, Daniel Leping 
> wrote:
>
> I personally like a lot => syntax for several reasons:
> 1. Consistent
> 2. Enforced return type
>
> As for the closures, I don't think we need an indication here. If it calls
> any impure function or captures a variable from outside - it's impure by
> definition. The compiler should decide if a closure can be treated pure.
> Same as with throwing.
>
>
> I’m not sure about this.  I would like the ability to syntactically state
> the intent that a closure is pure, and ideally do so in a way that doesn’t
> lose the conciseness of the closure (i.e. we shouldn’t have to give up any
> of the syntactic sugar available for simple closures).  A big benefit of
> allowing us to state intent like this is that it localizes error messages.
>
>
> As for the situation with currying (and other compositions), the situation
> is a lot more complicated than with rethrows. However, it's still
> deductible in compile time with the same mechanism as described above for
> closures.
>
> I tend to agree we could use ~> (looks good to me... volatile :)) for the
> function type definitions as an "unknown purity". The return type purity
> dependence graph can be built automatically at compile time. With this
> graph compiler can determine the returned function purity in every place
> function is used.
>
> The use of ~> should of course be limited to argument and return types of
> pure functions only. I think there might be a possibility of use in
> typealias, but need to think more about it.
>
> On Fri, 17 Feb 2017 at 22:59 Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Feb 17, 2017, at 2:52 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Out of curiosity, what are the benefits to being able to define that a
> closure must be pure as a parameter/type definition, as opposed to defining
> a particular closure to being pure while being passed?  What guarantees
> does it give you as the caller of the closure?
>
>
> If you only accept pure closures and otherwise meet the criteria of a pure
> function then you are pure.  If you have a function like that and want to
> accept both pure and impure closures and receive the purity of the closure
> provided then we need syntax indicating something similar to `rethrows`,
> but for purity.
>
>
> Thanks,
> Jon
>
>
> On Feb 16, 2017, at 1:18 PM, T.J. Usiyan  wrote:
>
> I am ok with a keyword but `pure` in front of func doesn't work well with
> inline closures.
>
> A few people talked through many of these issues starting with this tweet.
> https://twitter.com/griotspeak/status/832247545325842432
>
> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull  wrote:
>
> +1 for the idea of pure functions in swift.  Seems like it would enable a
> lot of good optimizations (in some cases even just evaluating the function
> at compile time).
>
> -1 on the specific notation.  I would much rather just put the word ‘pure’
> in front of ‘func’, the same way we put ‘mutating' in front of mutating
> functions… it seems to me like these are part of the same family.
>
> I agree we should allow inout.
>
> Thanks,
> Jon
>
> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> # Pure Functions
>
> * Proposal: [SE-](
> https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
> )
> * Author(s): [TJ Usiyan](https://github.com/griotspeak)
> * Status: 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution

> On Feb 17, 2017, at 4:17 PM, Daniel Leping  wrote:
> 
> I don't think I can (fully) agree with you, because a closure purity is not 
> something you "define". It's rather what you use inside. Though I totally 
> understand your concern and a wish to have localized errors.
> 
> However, I think it's totally consistent if you use a full form in a way:
> 
> { (a) => B in
> return a.toB()
> }
> 
> What I mean is that short form can auto determine. If you want to be 
> explicit... use the long form.
> 
> Would this work for you, @Matthew?

What I am saying is that I don’t think I should have to use the entire long 
form just to specify it’s a pure closure.  Something like the following would 
be acceptable:

{= $0.some.pure.expression() }
or
{=> $0.some.pure.expression() }

But I don’t want to be required to write out a name for the arguments and a 
return type for single expression closures like this.

> 
> On Sat, 18 Feb 2017 at 0:09 Matthew Johnson  > wrote:
>> On Feb 17, 2017, at 4:05 PM, Daniel Leping > > wrote:
>> 
>> I personally like a lot => syntax for several reasons:
>> 1. Consistent
>> 2. Enforced return type
>> 
>> As for the closures, I don't think we need an indication here. If it calls 
>> any impure function or captures a variable from outside - it's impure by 
>> definition. The compiler should decide if a closure can be treated pure. 
>> Same as with throwing.
> 
> I’m not sure about this.  I would like the ability to syntactically state the 
> intent that a closure is pure, and ideally do so in a way that doesn’t lose 
> the conciseness of the closure (i.e. we shouldn’t have to give up any of the 
> syntactic sugar available for simple closures).  A big benefit of allowing us 
> to state intent like this is that it localizes error messages.
> 
>> 
>> As for the situation with currying (and other compositions), the situation 
>> is a lot more complicated than with rethrows. However, it's still deductible 
>> in compile time with the same mechanism as described above for closures.
>> 
>> I tend to agree we could use ~> (looks good to me... volatile :)) for the 
>> function type definitions as an "unknown purity". The return type purity 
>> dependence graph can be built automatically at compile time. With this graph 
>> compiler can determine the returned function purity in every place function 
>> is used.
>> 
>> The use of ~> should of course be limited to argument and return types of 
>> pure functions only. I think there might be a possibility of use in 
>> typealias, but need to think more about it.
>> 
>> On Fri, 17 Feb 2017 at 22:59 Matthew Johnson via swift-evolution 
>> > wrote:
>>> On Feb 17, 2017, at 2:52 PM, Jonathan Hull via swift-evolution 
>>> > wrote:
>>> 
>>> Out of curiosity, what are the benefits to being able to define that a 
>>> closure must be pure as a parameter/type definition, as opposed to defining 
>>> a particular closure to being pure while being passed?  What guarantees 
>>> does it give you as the caller of the closure?
>> 
>> If you only accept pure closures and otherwise meet the criteria of a pure 
>> function then you are pure.  If you have a function like that and want to 
>> accept both pure and impure closures and receive the purity of the closure 
>> provided then we need syntax indicating something similar to `rethrows`, but 
>> for purity.
>> 
>>> 
>>> Thanks,
>>> Jon
>>> 
>>> 
 On Feb 16, 2017, at 1:18 PM, T.J. Usiyan > wrote:
 
 I am ok with a keyword but `pure` in front of func doesn't work well with 
 inline closures.
 
 A few people talked through many of these issues starting with this tweet. 
 https://twitter.com/griotspeak/status/832247545325842432 
 
 
 On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull > wrote:
 +1 for the idea of pure functions in swift.  Seems like it would enable a 
 lot of good optimizations (in some cases even just evaluating the function 
 at compile time).
 
 -1 on the specific notation.  I would much rather just put the word ‘pure’ 
 in front of ‘func’, the same way we put ‘mutating' in front of mutating 
 functions… it seems to me like these are part of the same family.
 
 I agree we should allow inout.
 
 Thanks,
 Jon
 
> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution 
> > wrote:
> 
> # Pure Functions
> 
> * Proposal: 
> [SE-](https://github.com/apple/swift-evolution/blob/master/proposals/-name.md

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Daniel Leping via swift-evolution
I don't think I can (fully) agree with you, because a closure purity is not
something you "define". It's rather what you use inside. Though I totally
understand your concern and a wish to have localized errors.

However, I think it's totally consistent if you use a full form in a way:

{ (a) => B in
return a.toB()
}

What I mean is that short form can auto determine. If you want to be
explicit... use the long form.

Would this work for you, @Matthew?

On Sat, 18 Feb 2017 at 0:09 Matthew Johnson  wrote:

> On Feb 17, 2017, at 4:05 PM, Daniel Leping 
> wrote:
>
> I personally like a lot => syntax for several reasons:
> 1. Consistent
> 2. Enforced return type
>
> As for the closures, I don't think we need an indication here. If it calls
> any impure function or captures a variable from outside - it's impure by
> definition. The compiler should decide if a closure can be treated pure.
> Same as with throwing.
>
>
> I’m not sure about this.  I would like the ability to syntactically state
> the intent that a closure is pure, and ideally do so in a way that doesn’t
> lose the conciseness of the closure (i.e. we shouldn’t have to give up any
> of the syntactic sugar available for simple closures).  A big benefit of
> allowing us to state intent like this is that it localizes error messages.
>
>
> As for the situation with currying (and other compositions), the situation
> is a lot more complicated than with rethrows. However, it's still
> deductible in compile time with the same mechanism as described above for
> closures.
>
> I tend to agree we could use ~> (looks good to me... volatile :)) for the
> function type definitions as an "unknown purity". The return type purity
> dependence graph can be built automatically at compile time. With this
> graph compiler can determine the returned function purity in every place
> function is used.
>
> The use of ~> should of course be limited to argument and return types of
> pure functions only. I think there might be a possibility of use in
> typealias, but need to think more about it.
>
> On Fri, 17 Feb 2017 at 22:59 Matthew Johnson via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> On Feb 17, 2017, at 2:52 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Out of curiosity, what are the benefits to being able to define that a
> closure must be pure as a parameter/type definition, as opposed to defining
> a particular closure to being pure while being passed?  What guarantees
> does it give you as the caller of the closure?
>
>
> If you only accept pure closures and otherwise meet the criteria of a pure
> function then you are pure.  If you have a function like that and want to
> accept both pure and impure closures and receive the purity of the closure
> provided then we need syntax indicating something similar to `rethrows`,
> but for purity.
>
>
> Thanks,
> Jon
>
>
> On Feb 16, 2017, at 1:18 PM, T.J. Usiyan  wrote:
>
> I am ok with a keyword but `pure` in front of func doesn't work well with
> inline closures.
>
> A few people talked through many of these issues starting with this tweet.
> https://twitter.com/griotspeak/status/832247545325842432
>
> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull  wrote:
>
> +1 for the idea of pure functions in swift.  Seems like it would enable a
> lot of good optimizations (in some cases even just evaluating the function
> at compile time).
>
> -1 on the specific notation.  I would much rather just put the word ‘pure’
> in front of ‘func’, the same way we put ‘mutating' in front of mutating
> functions… it seems to me like these are part of the same family.
>
> I agree we should allow inout.
>
> Thanks,
> Jon
>
> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> # Pure Functions
>
> * Proposal: [SE-](
> https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
> )
> * Author(s): [TJ Usiyan](https://github.com/griotspeak)
> * Status: **Awaiting review**
> * Review manager: TBD
>
> ## Introduction
>
> Some functions are, essentially, only meant to be transformations of their
> input and–as such–do not and should not reference any variables other than
> those passed in. These same functions are not meant to have any effects
> other than the aforementioned transformation of input. Currently, Swift
> cannot assist the developer and confirm that any given function is one of
> these 'pure' functions. To facilitate this, this proposal adds syntax to
> signal that a function is 'pure'.
>
> 'pure', in this context, means:
> 1. The function must have a return value
> 1. This function can only call other pure functions
> 1. This function cannot access/modify global or static variables.
>
> ## Motivation
>
> Consider the following example where `_computeNullability(of:)` is meant
> to create its output solely based on the provided recognizer.
>

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution

> On Feb 17, 2017, at 4:05 PM, Daniel Leping  wrote:
> 
> I personally like a lot => syntax for several reasons:
> 1. Consistent
> 2. Enforced return type
> 
> As for the closures, I don't think we need an indication here. If it calls 
> any impure function or captures a variable from outside - it's impure by 
> definition. The compiler should decide if a closure can be treated pure. Same 
> as with throwing.

I’m not sure about this.  I would like the ability to syntactically state the 
intent that a closure is pure, and ideally do so in a way that doesn’t lose the 
conciseness of the closure (i.e. we shouldn’t have to give up any of the 
syntactic sugar available for simple closures).  A big benefit of allowing us 
to state intent like this is that it localizes error messages.

> 
> As for the situation with currying (and other compositions), the situation is 
> a lot more complicated than with rethrows. However, it's still deductible in 
> compile time with the same mechanism as described above for closures.
> 
> I tend to agree we could use ~> (looks good to me... volatile :)) for the 
> function type definitions as an "unknown purity". The return type purity 
> dependence graph can be built automatically at compile time. With this graph 
> compiler can determine the returned function purity in every place function 
> is used.
> 
> The use of ~> should of course be limited to argument and return types of 
> pure functions only. I think there might be a possibility of use in 
> typealias, but need to think more about it.
> 
> On Fri, 17 Feb 2017 at 22:59 Matthew Johnson via swift-evolution 
> > wrote:
>> On Feb 17, 2017, at 2:52 PM, Jonathan Hull via swift-evolution 
>> > wrote:
>> 
>> Out of curiosity, what are the benefits to being able to define that a 
>> closure must be pure as a parameter/type definition, as opposed to defining 
>> a particular closure to being pure while being passed?  What guarantees does 
>> it give you as the caller of the closure?
> 
> If you only accept pure closures and otherwise meet the criteria of a pure 
> function then you are pure.  If you have a function like that and want to 
> accept both pure and impure closures and receive the purity of the closure 
> provided then we need syntax indicating something similar to `rethrows`, but 
> for purity.
> 
>> 
>> Thanks,
>> Jon
>> 
>> 
>>> On Feb 16, 2017, at 1:18 PM, T.J. Usiyan >> > wrote:
>>> 
>>> I am ok with a keyword but `pure` in front of func doesn't work well with 
>>> inline closures.
>>> 
>>> A few people talked through many of these issues starting with this tweet. 
>>> https://twitter.com/griotspeak/status/832247545325842432 
>>> 
>>> 
>>> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull >> > wrote:
>>> +1 for the idea of pure functions in swift.  Seems like it would enable a 
>>> lot of good optimizations (in some cases even just evaluating the function 
>>> at compile time).
>>> 
>>> -1 on the specific notation.  I would much rather just put the word ‘pure’ 
>>> in front of ‘func’, the same way we put ‘mutating' in front of mutating 
>>> functions… it seems to me like these are part of the same family.
>>> 
>>> I agree we should allow inout.
>>> 
>>> Thanks,
>>> Jon
>>> 
 On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution 
 > wrote:
 
 # Pure Functions
 
 * Proposal: 
 [SE-](https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
  
 )
 * Author(s): [TJ Usiyan](https://github.com/griotspeak 
 )
 * Status: **Awaiting review**
 * Review manager: TBD
 
 ## Introduction
 
 Some functions are, essentially, only meant to be transformations of their 
 input and–as such–do not and should not reference any variables other than 
 those passed in. These same functions are not meant to have any effects 
 other than the aforementioned transformation of input. Currently, Swift 
 cannot assist the developer and confirm that any given function is one of 
 these 'pure' functions. To facilitate this, this proposal adds syntax to 
 signal that a function is 'pure'.
 
 'pure', in this context, means:
 1. The function must have a return value
 1. This function can only call other pure functions
 1. This function cannot access/modify global or static variables.
 
 ## Motivation
 
 Consider the following example where `_computeNullability(of:)` is meant 
 to create its output solely based on the provided 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Daniel Leping via swift-evolution
I personally like a lot => syntax for several reasons:
1. Consistent
2. Enforced return type

As for the closures, I don't think we need an indication here. If it calls
any impure function or captures a variable from outside - it's impure by
definition. The compiler should decide if a closure can be treated pure.
Same as with throwing.

As for the situation with currying (and other compositions), the situation
is a lot more complicated than with rethrows. However, it's still
deductible in compile time with the same mechanism as described above for
closures.

I tend to agree we could use ~> (looks good to me... volatile :)) for the
function type definitions as an "unknown purity". The return type purity
dependence graph can be built automatically at compile time. With this
graph compiler can determine the returned function purity in every place
function is used.

The use of ~> should of course be limited to argument and return types of
pure functions only. I think there might be a possibility of use in
typealias, but need to think more about it.

On Fri, 17 Feb 2017 at 22:59 Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

> On Feb 17, 2017, at 2:52 PM, Jonathan Hull via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Out of curiosity, what are the benefits to being able to define that a
> closure must be pure as a parameter/type definition, as opposed to defining
> a particular closure to being pure while being passed?  What guarantees
> does it give you as the caller of the closure?
>
>
> If you only accept pure closures and otherwise meet the criteria of a pure
> function then you are pure.  If you have a function like that and want to
> accept both pure and impure closures and receive the purity of the closure
> provided then we need syntax indicating something similar to `rethrows`,
> but for purity.
>
>
> Thanks,
> Jon
>
>
> On Feb 16, 2017, at 1:18 PM, T.J. Usiyan  wrote:
>
> I am ok with a keyword but `pure` in front of func doesn't work well with
> inline closures.
>
> A few people talked through many of these issues starting with this tweet.
> https://twitter.com/griotspeak/status/832247545325842432
>
> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull  wrote:
>
> +1 for the idea of pure functions in swift.  Seems like it would enable a
> lot of good optimizations (in some cases even just evaluating the function
> at compile time).
>
> -1 on the specific notation.  I would much rather just put the word ‘pure’
> in front of ‘func’, the same way we put ‘mutating' in front of mutating
> functions… it seems to me like these are part of the same family.
>
> I agree we should allow inout.
>
> Thanks,
> Jon
>
> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> # Pure Functions
>
> * Proposal: [SE-](
> https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
> )
> * Author(s): [TJ Usiyan](https://github.com/griotspeak)
> * Status: **Awaiting review**
> * Review manager: TBD
>
> ## Introduction
>
> Some functions are, essentially, only meant to be transformations of their
> input and–as such–do not and should not reference any variables other than
> those passed in. These same functions are not meant to have any effects
> other than the aforementioned transformation of input. Currently, Swift
> cannot assist the developer and confirm that any given function is one of
> these 'pure' functions. To facilitate this, this proposal adds syntax to
> signal that a function is 'pure'.
>
> 'pure', in this context, means:
> 1. The function must have a return value
> 1. This function can only call other pure functions
> 1. This function cannot access/modify global or static variables.
>
> ## Motivation
>
> Consider the following example where `_computeNullability(of:)` is meant
> to create its output solely based on the provided recognizer.
>
> ```
> class Recognizer {
> var nullabilityMemo: Bool?
> var isNullable: Bool {
> func _computeNullability(of recognizer: Recognizer) -> Bool {…}
> if let back = nullabilityMemo {
> return back
> } else {
> let back =  _computeNullability(of: self)
> nullabilityMemo = back
> return back
> }
> }
> }
> ```
> if `_computeNullability(of:)` is recursive at all, there exists a real
> potential to accidentally reference `self` in its body and the mistake,
> depending on circumstance, can be terribly subtle. Converting
> `_computeNullability(of:)` to a `static` function is an option but
> obfuscates the fact that it is *only* to be called within `isNullable`.
>
>
> ## Proposed solution
>
> Given the ability to indicate that `_computeNullability(of:)` is a 'pure'
> function, the developer gains assurance from the tooling that it doesn't
> reference anything or cause any side effects.
>
>
> ```
> class Recognizer {
> var nullabilityMemo: Bool?
> var isNullable: Bool {
> pfunc _computeNullability(of recognizer: Recognizer) -> Bool {…}
> if let 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution

> On Feb 17, 2017, at 2:52 PM, Jonathan Hull via swift-evolution 
>  wrote:
> 
> Out of curiosity, what are the benefits to being able to define that a 
> closure must be pure as a parameter/type definition, as opposed to defining a 
> particular closure to being pure while being passed?  What guarantees does it 
> give you as the caller of the closure?

If you only accept pure closures and otherwise meet the criteria of a pure 
function then you are pure.  If you have a function like that and want to 
accept both pure and impure closures and receive the purity of the closure 
provided then we need syntax indicating something similar to `rethrows`, but 
for purity.

> 
> Thanks,
> Jon
> 
> 
>> On Feb 16, 2017, at 1:18 PM, T.J. Usiyan > > wrote:
>> 
>> I am ok with a keyword but `pure` in front of func doesn't work well with 
>> inline closures.
>> 
>> A few people talked through many of these issues starting with this tweet. 
>> https://twitter.com/griotspeak/status/832247545325842432 
>> 
>> 
>> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull > > wrote:
>> +1 for the idea of pure functions in swift.  Seems like it would enable a 
>> lot of good optimizations (in some cases even just evaluating the function 
>> at compile time).
>> 
>> -1 on the specific notation.  I would much rather just put the word ‘pure’ 
>> in front of ‘func’, the same way we put ‘mutating' in front of mutating 
>> functions… it seems to me like these are part of the same family.
>> 
>> I agree we should allow inout.
>> 
>> Thanks,
>> Jon
>> 
>>> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution 
>>> > wrote:
>>> 
>>> # Pure Functions
>>> 
>>> * Proposal: 
>>> [SE-](https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
>>>  
>>> )
>>> * Author(s): [TJ Usiyan](https://github.com/griotspeak 
>>> )
>>> * Status: **Awaiting review**
>>> * Review manager: TBD
>>> 
>>> ## Introduction
>>> 
>>> Some functions are, essentially, only meant to be transformations of their 
>>> input and–as such–do not and should not reference any variables other than 
>>> those passed in. These same functions are not meant to have any effects 
>>> other than the aforementioned transformation of input. Currently, Swift 
>>> cannot assist the developer and confirm that any given function is one of 
>>> these 'pure' functions. To facilitate this, this proposal adds syntax to 
>>> signal that a function is 'pure'.
>>> 
>>> 'pure', in this context, means:
>>> 1. The function must have a return value
>>> 1. This function can only call other pure functions
>>> 1. This function cannot access/modify global or static variables.
>>> 
>>> ## Motivation
>>> 
>>> Consider the following example where `_computeNullability(of:)` is meant to 
>>> create its output solely based on the provided recognizer.
>>> 
>>> ```
>>> class Recognizer {
>>> var nullabilityMemo: Bool?
>>> var isNullable: Bool {
>>> func _computeNullability(of recognizer: Recognizer) -> Bool {…}
>>> if let back = nullabilityMemo {
>>> return back 
>>> } else {
>>> let back =  _computeNullability(of: self)
>>> nullabilityMemo = back
>>> return back
>>> }
>>> }
>>> }
>>> ```
>>> if `_computeNullability(of:)` is recursive at all, there exists a real 
>>> potential to accidentally reference `self` in its body and the mistake, 
>>> depending on circumstance, can be terribly subtle. Converting 
>>> `_computeNullability(of:)` to a `static` function is an option but 
>>> obfuscates the fact that it is *only* to be called within `isNullable`.
>>> 
>>> 
>>> ## Proposed solution
>>> 
>>> Given the ability to indicate that `_computeNullability(of:)` is a 'pure' 
>>> function, the developer gains assurance from the tooling that it doesn't 
>>> reference anything or cause any side effects.
>>> 
>>> 
>>> ```
>>> class Recognizer {
>>> var nullabilityMemo: Bool?
>>> var isNullable: Bool {
>>> pfunc _computeNullability(of recognizer: Recognizer) -> Bool {…}
>>> if let back = nullabilityMemo {
>>> return back 
>>> } else {
>>> let back =  _computeNullability(of: self)
>>> nullabilityMemo = back
>>> return back
>>> }
>>> }
>>> }
>>> ```
>>> 
>>> ## Detailed design
>>> 
>>> This proposal introduces a new annotation `=>`, which is to be accepted 
>>> everywhere `->` currently is. Members created using this kewyord must 
>>> follow the rules listed in the 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Jonathan Hull via swift-evolution
Out of curiosity, what are the benefits to being able to define that a closure 
must be pure as a parameter/type definition, as opposed to defining a 
particular closure to being pure while being passed?  What guarantees does it 
give you as the caller of the closure?

Thanks,
Jon


> On Feb 16, 2017, at 1:18 PM, T.J. Usiyan  wrote:
> 
> I am ok with a keyword but `pure` in front of func doesn't work well with 
> inline closures.
> 
> A few people talked through many of these issues starting with this tweet. 
> https://twitter.com/griotspeak/status/832247545325842432 
> 
> 
> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull  > wrote:
> +1 for the idea of pure functions in swift.  Seems like it would enable a lot 
> of good optimizations (in some cases even just evaluating the function at 
> compile time).
> 
> -1 on the specific notation.  I would much rather just put the word ‘pure’ in 
> front of ‘func’, the same way we put ‘mutating' in front of mutating 
> functions… it seems to me like these are part of the same family.
> 
> I agree we should allow inout.
> 
> Thanks,
> Jon
> 
>> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution 
>> > wrote:
>> 
>> # Pure Functions
>> 
>> * Proposal: 
>> [SE-](https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
>>  
>> )
>> * Author(s): [TJ Usiyan](https://github.com/griotspeak 
>> )
>> * Status: **Awaiting review**
>> * Review manager: TBD
>> 
>> ## Introduction
>> 
>> Some functions are, essentially, only meant to be transformations of their 
>> input and–as such–do not and should not reference any variables other than 
>> those passed in. These same functions are not meant to have any effects 
>> other than the aforementioned transformation of input. Currently, Swift 
>> cannot assist the developer and confirm that any given function is one of 
>> these 'pure' functions. To facilitate this, this proposal adds syntax to 
>> signal that a function is 'pure'.
>> 
>> 'pure', in this context, means:
>> 1. The function must have a return value
>> 1. This function can only call other pure functions
>> 1. This function cannot access/modify global or static variables.
>> 
>> ## Motivation
>> 
>> Consider the following example where `_computeNullability(of:)` is meant to 
>> create its output solely based on the provided recognizer.
>> 
>> ```
>> class Recognizer {
>>  var nullabilityMemo: Bool?
>>  var isNullable: Bool {
>>  func _computeNullability(of recognizer: Recognizer) -> Bool {…}
>>  if let back = nullabilityMemo {
>>  return back 
>>  } else {
>>  let back =  _computeNullability(of: self)
>>  nullabilityMemo = back
>>  return back
>>  }
>>  }
>> }
>> ```
>> if `_computeNullability(of:)` is recursive at all, there exists a real 
>> potential to accidentally reference `self` in its body and the mistake, 
>> depending on circumstance, can be terribly subtle. Converting 
>> `_computeNullability(of:)` to a `static` function is an option but 
>> obfuscates the fact that it is *only* to be called within `isNullable`.
>> 
>> 
>> ## Proposed solution
>> 
>> Given the ability to indicate that `_computeNullability(of:)` is a 'pure' 
>> function, the developer gains assurance from the tooling that it doesn't 
>> reference anything or cause any side effects.
>> 
>> 
>> ```
>> class Recognizer {
>>  var nullabilityMemo: Bool?
>>  var isNullable: Bool {
>>  pfunc _computeNullability(of recognizer: Recognizer) -> Bool {…}
>>  if let back = nullabilityMemo {
>>  return back 
>>  } else {
>>  let back =  _computeNullability(of: self)
>>  nullabilityMemo = back
>>  return back
>>  }
>>  }
>> }
>> ```
>> 
>> ## Detailed design
>> 
>> This proposal introduces a new annotation `=>`, which is to be accepted 
>> everywhere `->` currently is. Members created using this kewyord must follow 
>> the rules listed in the introduction.
>> 
>> ## Impact on existing code
>> 
>> This is an additive feature unless alternative 2 is chosen and, as such, 
>> should not require an effect on existing code. It could be used to annotate 
>> closures accepted by methods in the standard library such as `map`, 
>> `filter`, and `reduce`. While this would fit well with their typical use, 
>> such a change is not necessarily part of this proposal.
>> 
>> ## Alternatives considered
>> 
>> It should be noted that neither of these alternatives can remain consistent 
>> for inline closures.
>> 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread T.J. Usiyan via swift-evolution
There shouldn't be a need for a third arrow with regard to purity. Impure
encompasses pure in that there is simply no guarantee of purity with an
impure function. You should be able to use a pure function in place of an
impure function without any issue whatsoever.

On Fri, Feb 17, 2017 at 1:35 PM, Adrian Zubarev via swift-evolution <
swift-evolution@swift.org> wrote:

> My suggestion is that -> would be the conditional arrow that can be both
> *pure* or *impure*. That would make @pure func foo(_ f: @pure (Int) ->
> Int) -> Int equivalent to func foo(_ f: (Int) ~> Int) -> Int. Plus
> depending on the implementation the compiler *might* be able to help and
> tell you that foo could use ~> instead.
>
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 17. Februar 2017 um 19:25:41, Anton Zhilin (antonyzhi...@gmail.com)
> schrieb:
>
> Just let
>
> @pure func foo(_ f: (Int) -> Int) -> Int
>
> be the same as those two combined:
>
> @pure func foo(_ f: @pure (Int) -> Int) -> Int
> func foo(_ f: (Int) -> Int) -> Int
>
> No need for anything like “re-pure” or ≃>.
> ​
>
>
> ___
> 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] Support for pure functions. Part n + 1.

2017-02-17 Thread Florent Vilmart via swift-evolution
I'm really not sold about the ~> operator, as it would be easy to miss. Swift 
is known and loved for the expressiveness of the language, using that operator 
doesn't help with that.

On another hand, I agree that this is the sexiest, less intrusive solution.

On 17 févr. 2017 13:36 -0500, Adrian Zubarev via swift-evolution 
, wrote:
> My suggestion is that -> would be the conditional arrow that can be both pure 
> or impure. That would make @pure func foo(_ f: @pure (Int) -> Int) -> Int 
> equivalent to func foo(_ f: (Int) ~> Int) -> Int. Plus depending on the 
> implementation the compiler might be able to help and tell you that foo could 
> use ~> instead.
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 17. Februar 2017 um 19:25:41, Anton Zhilin (antonyzhi...@gmail.com) 
> schrieb:
> > Just let
> >
> > @pure func foo(_ f: (Int) -> Int) -> Int
> >
> > be the same as those two combined:
> >
> > @pure func foo(_ f: @pure (Int) -> Int) -> Int
> > func foo(_ f: (Int) -> Int) -> Int
> >
> > No need for anything like “re-pure” or ≃>.
> >
> ___
> 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] Support for pure functions. Part n + 1.

2017-02-17 Thread Adrian Zubarev via swift-evolution
That autocorrection sometimes :/

Purity could easily be expressed through the arrow, plus it enforces you to 
have a return type (other than Void).


-- 
Adrian Zubarev
Sent with Airmail

Am 17. Februar 2017 um 19:27:12, Adrian Zubarev 
(adrian.zuba...@devandartist.com) schrieb:

Purity could be easily be expressed throw the arrow, plus it enforces you to 
have a return type (other than Void).
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread David Sweeris via swift-evolution

> On Feb 17, 2017, at 9:51 AM, André “Zephyz” Videla via swift-evolution 
>  wrote:
> 
>> But given the scope capturing nature of closures I was actually wondering if 
>> this 'purity' should be applied to closures.
> I think It should, pure closure cannot have outside references and therefore 
> cannot create reference cycles even though they are escaping.
> 
> I tend toward using the => sign since it doesn't require a lot of change, it 
> has a nice lightweight syntax and seems different enough from -> .
> The pure keyword in front of the function signature looks like a lot of noise 
> for such a simple concept. And It will only get worse in function signatures.
> 
> see the difference between 
> 
> func pureCurryCompose(f: @pure(B) -> C) -> @pure(@pure(A) -> B) -> 
> (@pure(A) -> C)
> 
> and 
> 
> func pureCurryCompose(f: (B) => C) => ((A) => B) => (A) => C
> 
> The second is easiest to read.
> 
> (of course I would argue that 
> 
> func pureCurryCompose(f: B => C) => (A => B) => (A => C) 
> 
> is the most readable of all but I'm too late for that proposal )

I don’t think it’s worth burning an operator for this (especially since the 
ones that are visually similar to “->” and “=“ are likely to be used by people 
trying to “wrap” functions or assignment).

I’m also currently -1 on the idea of giving some attributes special syntax… 
What happens when we decide some other attribute is worth adding? Does, say, 
“distributive" get to be written as “func * (x:Foo, y:Foo) %> Foo”? How would 
we denote a function that’s both “pure” and “distributive”? “func * (x:Foo, 
y:Foo) %~> Foo”? That gets real hard to read (and eats up large swathes of 
operators) real fast.

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Adrian Zubarev via swift-evolution
Who said that pure functions should be newcomer friendly? Swift attributes are 
way at the end of the swift’s book. Using the -> arrow at first won’t break 
anything. If one would optimize some functions by annotating them to be pure, 
the change to something like ~> would be really easy.

IMHO clustering the whole code with hundred’s of different attributes isn’t the 
right way either. Purity could be easily be expressed throw the arrow, plus it 
enforces you to have a return type (other than Void).



-- 
Adrian Zubarev
Sent with Airmail

Am 17. Februar 2017 um 18:59:17, Nicolas Fezans (nicolas.fez...@gmail.com) 
schrieb:

The arrow proposals -> vs. ~> vs. => are not really much shorter than 
the 4 letters of the pure keyword but just confusing and frightening 
for newcomers (BTW __pure exists in GCC if I remember well) whereas 
"pure func" is something that people can easily google in case they 
need to learn the concept. The different arrows are very compact but 
feel a bit like J, which is a language I would not like swift to look 
like. 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Anton Zhilin via swift-evolution
Just let

@pure func foo(_ f: (Int) -> Int) -> Int

be the same as those two combined:

@pure func foo(_ f: @pure (Int) -> Int) -> Int
func foo(_ f: (Int) -> Int) -> Int

No need for anything like “re-pure” or ≃>.
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Adrian Zubarev via swift-evolution
Exactly, there is none. What I was trying to describe is that -> would become 
the conditional operator that could swallow purity and impurity. However if one 
would want to be explicit about purity, you’d have to use ~> instead.



-- 
Adrian Zubarev
Sent with Airmail

Am 17. Februar 2017 um 18:59:17, Nicolas Fezans (nicolas.fez...@gmail.com) 
schrieb:

I do not see the rationale behind marking impure functions explicitly.  
The useful property is to be pure, in case a function is impure or  
it's status is unknown you just have to assume the worse, i.e. that it  
is impure.  

The arrow proposals -> vs. ~> vs. => are not really much shorter than  
the 4 letters of the pure keyword but just confusing and frightening  
for newcomers (BTW __pure exists in GCC if I remember well) whereas  
"pure func" is something that people can easily google in case they  
need to learn the concept. The different arrows are very compact but  
feel a bit like J, which is a language I would not like swift to look  
like.  

For closure I would rather see it as in this example  

[2.0 , 3.0 , 4.0].map(pure {(x: Double)->Double in return x*x})  

just pure preceding the closure and it would preceeds "func" in "pure  
func". (it could be @pure in both case too)  

Nicolas  


On Fri, Feb 17, 2017 at 6:36 PM, Adrian Zubarev via swift-evolution  
 wrote:  
> That problem could be solved with the combining tilde, however it isn’t  
> easy, because it’s simply not easy to type. If ~> would describe the pure  
> function and -> an impure function then the combination of both would be ≃>.  
>  
> One thing I noticed, you said that the function itself will become pure or  
> impure depending on the other function. Doesn’t this imply that -> is  
> exactly this pure OR impure function. It’s either or but never both right?  
> Otherwise it might lead us to a huge breaking change. A suggestion building  
> on top of the arrow syntax we could have:  
>  
> pure function: ~>  
> impure function: ≈> (That’s a ‘double tilde’)  
> pure or impure function: -> (it is as to top and bottom tilde was merged and  
> smoothed together)  
>  
>  
>  
> --  
> Adrian Zubarev  
> Sent with Airmail  
>  
> Am 17. Februar 2017 um 17:43:21, Matthew Johnson (matt...@anandabits.com)  
> schrieb:  
>  
> Well sure, but then you have just supplied the type annotation. I am  
> describing a specific scenario where an API can accept a function that is  
> pure or a function that is impure and will have the purity of the function  
> passed into it.  
>  
>  
> ___  
> 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] Support for pure functions. Part n + 1.

2017-02-17 Thread Nicolas Fezans via swift-evolution
I do not see the rationale behind marking impure functions explicitly.
The useful property is to be pure, in case a function is impure or
it's status is unknown you just have to assume the worse, i.e. that it
is impure.

The arrow proposals -> vs. ~> vs. => are not really much shorter than
the 4 letters of the pure keyword but just confusing and frightening
for newcomers (BTW __pure exists in GCC if I remember well) whereas
"pure func" is something that people can easily google in case they
need to learn the concept. The different arrows are very compact but
feel a bit like J, which is a language I would not like swift to look
like.

For closure I would rather see it as in this example

[2.0 , 3.0 , 4.0].map(pure {(x: Double)->Double in return x*x})

just pure preceding the closure and it would preceeds "func" in "pure
func". (it could be @pure in both case too)

Nicolas


On Fri, Feb 17, 2017 at 6:36 PM, Adrian Zubarev via swift-evolution
 wrote:
> That problem could be solved with the combining tilde, however it isn’t
> easy, because it’s simply not easy to type. If ~> would describe the pure
> function and -> an impure function then the combination of both would be ≃>.
>
> One thing I noticed, you said that the function itself will become pure or
> impure depending on the other function. Doesn’t this imply that -> is
> exactly this pure OR impure function. It’s either or but never both right?
> Otherwise it might lead us to a huge breaking change. A suggestion building
> on top of the arrow syntax we could have:
>
> pure function: ~>
> impure function: ≈> (That’s a ‘double tilde’)
> pure or impure function: -> (it is as to top and bottom tilde was merged and
> smoothed together)
>
>
>
> --
> Adrian Zubarev
> Sent with Airmail
>
> Am 17. Februar 2017 um 17:43:21, Matthew Johnson (matt...@anandabits.com)
> schrieb:
>
> Well sure, but then you have just supplied the type annotation.  I am
> describing a specific scenario where an API can accept a function that is
> pure or a function that is impure and will have the purity of the function
> passed into it.
>
>
> ___
> 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] Support for pure functions. Part n + 1.

2017-02-17 Thread Vladimir.S via swift-evolution

On 17.02.2017 20:18, Matthew Johnson via swift-evolution wrote:

If we do go with the => means pure one option for closures without a
signature would be something like this: {= $0.pureMethod() }


I feel this will be more clear: {=> in $0.pureMethod() }
i.e. "in" is required to highlight that this is a "modifier" not the 
closure body.

in case you have parameters: {=> x,y in $0.pureMethod(x,y) }




This keeps the closure concise and uses = to indicate purity.  The fact
that it looks a little bit like assignment is interesting since a pure
function always has to have a return value.

Sent from my iPad

On Feb 17, 2017, at 10:59 AM, Matthew Johnson via swift-evolution
> wrote:


How do you suggest a closure indicate its purity? Something like this?

{ pure in $0.property }


On Feb 17, 2017, at 10:57 AM, Florent Vilmart > wrote:

We were discussing the topic yesterday with others and some suggested
adding a pure keyword, for improved readability, just before the
function declaration:

Ex:

pure func(a:Some) -> Else {}



On Feb 17, 2017, 11:51 AM -0500, Matthew Johnson via swift-evolution
>, wrote:



On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution
> wrote:


On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution
> wrote:


I haven’t yet read all the feedback in this topic but I’d like to
throw some bikeshedding of mine into the room. :)

How about this?

  * Version 1: |func(pure) …|
  * Version 2: |func label(…) ~> ReturnType|


Version 2 is going to upset those who use "~>" as an operator.

As the # of possible attributes grows, having an obvious grouping
mechanism for them, like version 1, might be worthwhile simply to help
make the list clearer. What about allowing "@(list, of, attributes)"
instead of "@list, @of, @attributes”?


That would be a little bit awkward for attributes that are
parameterized.  And if we did do this we should allow the parens to be
omitted when there is only one attribute.



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


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


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



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


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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread André “Zephyz” Videla via swift-evolution
> But given the scope capturing nature of closures I was actually wondering if 
> this 'purity' should be applied to closures.
I think It should, pure closure cannot have outside references and therefore 
cannot create reference cycles even though they are escaping.

I tend toward using the => sign since it doesn't require a lot of change, it 
has a nice lightweight syntax and seems different enough from -> .
The pure keyword in front of the function signature looks like a lot of noise 
for such a simple concept. And It will only get worse in function signatures.

see the difference between 

func pureCurryCompose(f: @pure(B) -> C) -> @pure(@pure(A) -> B) -> 
(@pure(A) -> C)

and 

func pureCurryCompose(f: (B) => C) => ((A) => B) => (A) => C

The second is easiest to read.

(of course I would argue that 

func pureCurryCompose(f: B => C) => (A => B) => (A => C) 

is the most readable of all but I'm too late for that proposal )

> On 17 Feb 2017, at 18:02, Florent Vilmart via swift-evolution 
>  wrote:
> 
> We could do:
> 
> pure let closure = { _-> Else in }
> 
> But given the scope capturing nature of closures I was actually wondering if 
> this 'purity' should be applied to closures.
> 
> After all an inline defined func would do.
> 
> 
> On Feb 17, 2017, 11:59 AM -0500, Matthew Johnson , 
> wrote:
>> How do you suggest a closure indicate its purity? Something like this?  
>> 
>> { pure in $0.property } 
>> 
>>> On Feb 17, 2017, at 10:57 AM, Florent Vilmart >> > wrote:
>>> 
>>> We were discussing the topic yesterday with others and some suggested 
>>> adding a pure keyword, for improved readability, just before the function 
>>> declaration:
>>> 
>>> Ex:
>>> 
>>> pure func(a:Some) -> Else {}
>>> 
>>> 
>>> 
>>> On Feb 17, 2017, 11:51 AM -0500, Matthew Johnson via swift-evolution 
>>> >, wrote:
 
> On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
> > wrote:
> 
> 
> On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
> > wrote:
> 
>> I haven’t yet read all the feedback in this topic but I’d like to throw 
>> some bikeshedding of mine into the room. :)
>> 
>> How about this?
>> 
>> Version 1: func(pure) …
>> Version 2: func label(…) ~> ReturnType
> Version 2 is going to upset those who use "~>" as an operator.
> 
> As the # of possible attributes grows, having an obvious grouping 
> mechanism for them, like version 1, might be worthwhile simply to help 
> make the list clearer. What about allowing "@(list, of, attributes)" 
> instead of "@list, @of, @attributes”?
 
 That would be a little bit awkward for attributes that are parameterized.  
 And if we did do this we should allow the parens to be omitted when there 
 is only one attribute.
 
> 
> - Dave Sweeris
> ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
 
 ___
 swift-evolution mailing list
 swift-evolution@swift.org 
 https://lists.swift.org/mailman/listinfo/swift-evolution 
 
>> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Adrian Zubarev via swift-evolution
That problem could be solved with the combining tilde, however it isn’t easy, 
because it’s simply not easy to type. If ~> would describe the pure function 
and -> an impure function then the combination of both would be ≃>.

One thing I noticed, you said that the function itself will become pure or 
impure depending on the other function. Doesn’t this imply that -> is exactly 
this pure OR impure function. It’s either or but never both right? Otherwise it 
might lead us to a huge breaking change. A suggestion building on top of the 
arrow syntax we could have:

pure function: ~>
impure function: ≈> (That’s a ‘double tilde’)
pure or impure function: -> (it is as to top and bottom tilde was merged and 
smoothed together)


-- 
Adrian Zubarev
Sent with Airmail

Am 17. Februar 2017 um 17:43:21, Matthew Johnson (matt...@anandabits.com) 
schrieb:

Well sure, but then you have just supplied the type annotation.  I am 
describing a specific scenario where an API can accept a function that is pure 
or a function that is impure and will have the purity of the function passed 
into it.  
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution
If we do go with the => means pure one option for closures without a signature 
would be something like this: {= $0.pureMethod() }

This keeps the closure concise and uses = to indicate purity.  The fact that it 
looks a little bit like assignment is interesting since a pure function always 
has to have a return value. 

Sent from my iPad

> On Feb 17, 2017, at 10:59 AM, Matthew Johnson via swift-evolution 
>  wrote:
> 
> How do you suggest a closure indicate its purity? Something like this?  
> 
> { pure in $0.property } 
> 
>> On Feb 17, 2017, at 10:57 AM, Florent Vilmart  wrote:
>> 
>> We were discussing the topic yesterday with others and some suggested adding 
>> a pure keyword, for improved readability, just before the function 
>> declaration:
>> 
>> Ex:
>> 
>> pure func(a:Some) -> Else {}
>> 
>> 
>> 
>>> On Feb 17, 2017, 11:51 AM -0500, Matthew Johnson via swift-evolution 
>>> , wrote:
>>> 
 On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
  wrote:
 
 
 On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
  wrote:
 
> I haven’t yet read all the feedback in this topic but I’d like to throw 
> some bikeshedding of mine into the room. :)
> 
> How about this?
> 
> Version 1: func(pure) …
> Version 2: func label(…) ~> ReturnType
 Version 2 is going to upset those who use "~>" as an operator.
 
 As the # of possible attributes grows, having an obvious grouping 
 mechanism for them, like version 1, might be worthwhile simply to help 
 make the list clearer. What about allowing "@(list, of, attributes)" 
 instead of "@list, @of, @attributes”?
>>> 
>>> That would be a little bit awkward for attributes that are parameterized.  
>>> And if we did do this we should allow the parens to be omitted when there 
>>> is only one attribute.
>>> 
 
 - Dave Sweeris
 ___
 swift-evolution mailing list
 swift-evolution@swift.org
 https://lists.swift.org/mailman/listinfo/swift-evolution
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Florent Vilmart via swift-evolution
Another usecase would be for the type aliases:

typealias PureFunc = pure (Some)->Else

Or

pure typealias PureFunc = (Some)->Else

I'm not sure where the keyword should stand

On Feb 17, 2017, 12:03 PM -0500, Matthew Johnson via swift-evolution 
, wrote:
>
> > On Feb 17, 2017, at 10:55 AM, David Sweeris  > (mailto:daveswee...@mac.com)> wrote:
> >
> > On Feb 17, 2017, at 08:49, Matthew Johnson  > (mailto:matt...@anandabits.com)> wrote:
> >
> > >
> > > > On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
> > > >  wrote:
> > > >
> > > > On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
> > > >  wrote:
> > > >
> > > > >
> > > > > I haven’t yet read all the feedback in this topic but I’d like to 
> > > > > throw some bikeshedding of mine into the room. :)
> > > > >
> > > > >
> > > > > How about this?
> > > > >
> > > > > Version 1: func(pure) …
> > > > > Version 2: func label(…) ~> ReturnType
> > > > >
> > > > >
> > > > >
> > > >
> > > > Version 2 is going to upset those who use "~>" as an operator.
> > > >
> > > > As the # of possible attributes grows, having an obvious grouping 
> > > > mechanism for them, like version 1, might be worthwhile simply to help 
> > > > make the list clearer. What about allowing "@(list, of, attributes)" 
> > > > instead of "@list, @of, @attributes”?
> > >
> > > That would be a little bit awkward for attributes that are parameterized.
> >
> > Are there any parameterized attributes other than "@inline(always|never)”?
>
> I am not sure, but there has been discussion of introducing them. For 
> example, regardless of what syntax we choose for indicating a public enum is 
> closed it will need to have an optional parameter indicating the first 
> version of the library in which it was closed (which can be omitted if it was 
> closed the first time it appeared). One option for indicating this is to use 
> an attribute.
> >
> > > And if we did do this we should allow the parens to be omitted when there 
> > > is only one attribute.
> > Agreed.
> >
> > - 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] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Florent Vilmart via swift-evolution
We could do:

pure let closure = { _-> Else in }

But given the scope capturing nature of closures I was actually wondering if 
this 'purity' should be applied to closures.

After all an inline defined func would do.

On Feb 17, 2017, 11:59 AM -0500, Matthew Johnson , 
wrote:
> How do you suggest a closure indicate its purity? Something like this?
>
> { pure in $0.property }
>
> > On Feb 17, 2017, at 10:57 AM, Florent Vilmart  > (mailto:flor...@flovilmart.com)> wrote:
> > We were discussing the topic yesterday with others and some suggested 
> > adding a pure keyword, for improved readability, just before the function 
> > declaration:
> >
> > Ex:
> >
> > pure func(a:Some) -> Else {}
> >
> >
> >
> > On Feb 17, 2017, 11:51 AM -0500, Matthew Johnson via swift-evolution 
> > , wrote:
> > >
> > > > On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
> > > >  wrote:
> > > >
> > > > On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
> > > >  wrote:
> > > >
> > > > >
> > > > > I haven’t yet read all the feedback in this topic but I’d like to 
> > > > > throw some bikeshedding of mine into the room. :)
> > > > >
> > > > >
> > > > > How about this?
> > > > >
> > > > > Version 1: func(pure) …
> > > > > Version 2: func label(…) ~> ReturnType
> > > > >
> > > > >
> > > > >
> > > >
> > > > Version 2 is going to upset those who use "~>" as an operator.
> > > >
> > > > As the # of possible attributes grows, having an obvious grouping 
> > > > mechanism for them, like version 1, might be worthwhile simply to help 
> > > > make the list clearer. What about allowing "@(list, of, attributes)" 
> > > > instead of "@list, @of, @attributes”?
> > >
> > > That would be a little bit awkward for attributes that are parameterized. 
> > > And if we did do this we should allow the parens to be omitted when there 
> > > is only one attribute.
> > > >
> > > > - Dave Sweeris ___
> > > > swift-evolution mailing list
> > > > swift-evolution@swift.org (mailto:swift-evolution@swift.org)
> > > > https://lists.swift.org/mailman/listinfo/swift-evolution
> > >
> > > ___
> > > swift-evolution mailing list
> > > swift-evolution@swift.org (mailto: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] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution
How do you suggest a closure indicate its purity? Something like this?  

{ pure in $0.property } 

> On Feb 17, 2017, at 10:57 AM, Florent Vilmart  wrote:
> 
> We were discussing the topic yesterday with others and some suggested adding 
> a pure keyword, for improved readability, just before the function 
> declaration:
> 
> Ex:
> 
> pure func(a:Some) -> Else {}
> 
> 
> 
> On Feb 17, 2017, 11:51 AM -0500, Matthew Johnson via swift-evolution 
> , wrote:
>> 
>>> On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
>>> > wrote:
>>> 
 I haven’t yet read all the feedback in this topic but I’d like to throw 
 some bikeshedding of mine into the room. :)
 
 How about this?
 
 Version 1: func(pure) …
 Version 2: func label(…) ~> ReturnType
>>> Version 2 is going to upset those who use "~>" as an operator.
>>> 
>>> As the # of possible attributes grows, having an obvious grouping mechanism 
>>> for them, like version 1, might be worthwhile simply to help make the list 
>>> clearer. What about allowing "@(list, of, attributes)" instead of "@list, 
>>> @of, @attributes”?
>> 
>> That would be a little bit awkward for attributes that are parameterized.  
>> And if we did do this we should allow the parens to be omitted when there is 
>> only one attribute.
>> 
>>> 
>>> - Dave Sweeris
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution

> On Feb 17, 2017, at 10:55 AM, David Sweeris  wrote:
> 
> 
> On Feb 17, 2017, at 08:49, Matthew Johnson  > wrote:
> 
>> 
>>> On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
>>> > wrote:
>>> 
>>> 
>>> On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
>>> > wrote:
>>> 
 I haven’t yet read all the feedback in this topic but I’d like to throw 
 some bikeshedding of mine into the room. :)
 
 How about this?
 
 Version 1: func(pure) …
 Version 2: func label(…) ~> ReturnType
>>> Version 2 is going to upset those who use "~>" as an operator.
>>> 
>>> As the # of possible attributes grows, having an obvious grouping mechanism 
>>> for them, like version 1, might be worthwhile simply to help make the list 
>>> clearer. What about allowing "@(list, of, attributes)" instead of "@list, 
>>> @of, @attributes”?
>> 
>> That would be a little bit awkward for attributes that are parameterized.
> 
> Are there any parameterized attributes other than "@inline(always|never)”?

I am not sure, but there has been discussion of introducing them.  For example, 
regardless of what syntax we choose for indicating a public enum is closed it 
will need to have an optional parameter indicating the first version of the 
library in which it was closed (which can be omitted if it was closed the first 
time it appeared).  One option for indicating this is to use an attribute.

> 
>> And if we did do this we should allow the parens to be omitted when there is 
>> only one attribute.
> 
> Agreed.
> 
> - Dave Sweeris 

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Florent Vilmart via swift-evolution
We were discussing the topic yesterday with others and some suggested adding a 
pure keyword, for improved readability, just before the function declaration:

Ex:

pure func(a:Some) -> Else {}

On Feb 17, 2017, 11:51 AM -0500, Matthew Johnson via swift-evolution 
, wrote:
>
> > On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
> >  wrote:
> >
> > On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
> >  wrote:
> >
> > >
> > > I haven’t yet read all the feedback in this topic but I’d like to throw 
> > > some bikeshedding of mine into the room. :)
> > >
> > >
> > > How about this?
> > >
> > > Version 1: func(pure) …
> > > Version 2: func label(…) ~> ReturnType
> > >
> > >
> > >
> >
> > Version 2 is going to upset those who use "~>" as an operator.
> >
> > As the # of possible attributes grows, having an obvious grouping mechanism 
> > for them, like version 1, might be worthwhile simply to help make the list 
> > clearer. What about allowing "@(list, of, attributes)" instead of "@list, 
> > @of, @attributes”?
>
> That would be a little bit awkward for attributes that are parameterized. And 
> if we did do this we should allow the parens to be omitted when there is only 
> one attribute.
> >
> > - Dave Sweeris ___
> > swift-evolution mailing list
> > swift-evolution@swift.org (mailto: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] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread David Sweeris via swift-evolution

> On Feb 17, 2017, at 08:49, Matthew Johnson  wrote:
> 
> 
>> On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
>>  wrote:
>> 
>> 
>> On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
>>  wrote:
>> 
>>> I haven’t yet read all the feedback in this topic but I’d like to throw 
>>> some bikeshedding of mine into the room. :)
>>> 
>>> How about this?
>>> 
>>> Version 1: func(pure) …
>>> Version 2: func label(…) ~> ReturnType
>> Version 2 is going to upset those who use "~>" as an operator.
>> 
>> As the # of possible attributes grows, having an obvious grouping mechanism 
>> for them, like version 1, might be worthwhile simply to help make the list 
>> clearer. What about allowing "@(list, of, attributes)" instead of "@list, 
>> @of, @attributes”?
> 
> That would be a little bit awkward for attributes that are parameterized.

Are there any parameterized attributes other than "@inline(always|never)"?

> And if we did do this we should allow the parens to be omitted when there is 
> only one attribute.

Agreed.

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution

> On Feb 17, 2017, at 10:46 AM, David Sweeris via swift-evolution 
>  wrote:
> 
> 
> On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
> > wrote:
> 
>> I haven’t yet read all the feedback in this topic but I’d like to throw some 
>> bikeshedding of mine into the room. :)
>> 
>> How about this?
>> 
>> Version 1: func(pure) …
>> Version 2: func label(…) ~> ReturnType
> Version 2 is going to upset those who use "~>" as an operator.
> 
> As the # of possible attributes grows, having an obvious grouping mechanism 
> for them, like version 1, might be worthwhile simply to help make the list 
> clearer. What about allowing "@(list, of, attributes)" instead of "@list, 
> @of, @attributes”?

That would be a little bit awkward for attributes that are parameterized.  And 
if we did do this we should allow the parens to be omitted when there is only 
one attribute.

> 
> - 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] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread David Sweeris via swift-evolution

> On Feb 17, 2017, at 08:21, Adrian Zubarev via swift-evolution 
>  wrote:
> 
> I haven’t yet read all the feedback in this topic but I’d like to throw some 
> bikeshedding of mine into the room. :)
> 
> How about this?
> 
> Version 1: func(pure) …
> Version 2: func label(…) ~> ReturnType
Version 2 is going to upset those who use "~>" as an operator.

As the # of possible attributes grows, having an obvious grouping mechanism for 
them, like version 1, might be worthwhile simply to help make the list clearer. 
What about allowing "@(list, of, attributes)" instead of "@list, @of, 
@attributes"?

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution

> On Feb 17, 2017, at 10:33 AM, Adrian Zubarev 
>  wrote:
> 
> Regardless the issue you described with rethrows couldn’t we simply 
> explicitly tell the compiler the closures type which would include the pure 
> arrow?
> 
> let _: (T) ~> SomeType = { … }
> 
> That is similar to the behavior we now have with IUOs. (let myView: UIView = 
> self.view inside UIViewController on iOS)
> 
> I don’t know if the tilde is heavily used in any other programming patterns 
> and might create confusion here, but from the aesthetic point of view I’d 
> prefer ~> over =>.
> 
> 

Well sure, but then you have just supplied the type annotation.  I am 
describing a specific scenario where an API can accept a function that is pure 
or a function that is impure and will have the purity of the function passed 
into it.  

In many cases such APIs are used with simple closures, often single-expression 
closures.  Our options for determining purity of the closure are:

1. Allow the compiler to infer the purity of these closures.
2. Require an annotation indicating the programmers intent of purity (hopefully 
one that doesn’t eliminate the conciseness of single-expression closures)

We also need a way for the API to indicate it’s conditional purity (something 
like rethrows).  If we don’t have this then we would be forced to write pure 
and impure overloads when we want to support both and retain the purity when 
the provided closure is pure.

> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 17. Februar 2017 um 15:37:15, Matthew Johnson via swift-evolution 
> (swift-evolution@swift.org ) schrieb:
> 
>> Also, what about pure closures that have no need to state a signature 
>> because it is inferred?  This syntactic sugar is a pretty important aspect 
>> of Swift and often times some of our smallest closures will be pure.  For 
>> example Array’s map should be pure when the closure is pure and many map 
>> closures are very small.  We don’t want to have to annotate these closures 
>> with a signature.  
> 

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Charles Srstka via swift-evolution
> On Feb 17, 2017, at 7:37 AM, David Hart  wrote:
> 
> On 17 Feb 2017, at 08:59, Nicolas Fezans via swift-evolution 
> > wrote:
> 
>> > Not only that, but even if you pass a value type as a parameter, that 
>> > value type might have reference types as ivars.
>> 
>> I think that arguments passed to a pure function shall be checked against 
>> containing such references or objects that contains such references 
>> themselves: I guess that this check could be made by the compiler.
>> Programmers will then have to see whether they choose a) to go to "pure 
>> value-type arguments" (i.e. not containing directly nor indirectly such 
>> references) and be able to declare some of their functions as pure or b) to 
>> keep these references and not declare the corresponding functions as pure.
> 
> Wouldn't we need a way to declare value semantics? Array has such references 
> but has value semantics so should be fine, no?

Arrays can contain reference types. If you have an array of references, you can 
call a mutating function on one of them…

There’s also the other built-in value types that are backed by reference types: 
URL is backed by NSURL, Data is backed by NSData. They won’t mutate, because 
they’re set up to make sure they get immutable versions of them, but how is the 
compiler going to prove it?

Charles

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Adrian Zubarev via swift-evolution
Regardless the issue you described with rethrows couldn’t we simply explicitly 
tell the compiler the closures type which would include the pure arrow?

let _: (T) ~> SomeType = { … }

That is similar to the behavior we now have with IUOs. (let myView: UIView = 
self.view inside UIViewController on iOS)

I don’t know if the tilde is heavily used in any other programming patterns and 
might create confusion here, but from the aesthetic point of view I’d prefer ~> 
over =>.



-- 
Adrian Zubarev
Sent with Airmail

Am 17. Februar 2017 um 15:37:15, Matthew Johnson via swift-evolution 
(swift-evolution@swift.org) schrieb:

Also, what about pure closures that have no need to state a signature because 
it is inferred?  This syntactic sugar is a pretty important aspect of Swift and 
often times some of our smallest closures will be pure.  For example Array’s 
map should be pure when the closure is pure and many map closures are very 
small.  We don’t want to have to annotate these closures with a signature.  
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Adrian Zubarev via swift-evolution
I haven’t yet read all the feedback in this topic but I’d like to throw some 
bikeshedding of mine into the room. :)

How about this?

Version 1: func(pure) …
Version 2: func label(…) ~> ReturnType


-- 
Adrian Zubarev
Sent with Airmail

Am 17. Februar 2017 um 17:16:49, Anton Zhilin via swift-evolution 
(swift-evolution@swift.org) schrieb:

2017-02-17 17:13 GMT+03:00 T.J. Usiyan :

It is my opinion that you are describing an entirely different, and somewhat 
orthogonal, feature. I would like the feature that you describe. Constant 
expressions are powerful and open up quite a few optimizations. What constexpr 
addresses is not purity, at the heart of it. Pure expressions that accept 
compile-time-known values are, by happy accident, compile-time-computable, but 
pure expressions that accept dynamic values are not. Conflating the two 
qualities of being compile-time-known and being pure within the same keyword 
and overloading it in this way is not desirable to me.
I see now. I’d say that access to global state is not vital, and  
@pure functions are more useful than  
@const functions, so I’m OK with having only  
@const functions.

To control growth of compilation time, we could have both  
@pure function annotation and  
@const variable annotation to ensure that a  
@pure expression is computed at compilation time.

I’d also want to infer  
@pure whenever possible, but is it possible with functions in different modules?

___
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] Support for pure functions. Part n + 1.

2017-02-17 Thread Anton Zhilin via swift-evolution
I didn’t mean to emphasize any specific syntax. I’m fine with either @const,
@constexpr, @pure or =>.
Anyway, I see no reason why generic functions shouldn’t be supported in any
of the suggested models.

2017-02-17 19:08 GMT+03:00 Abe Schneider :

+1. I think this is a great idea. As I was following this thread, I
> was wondering if someone might suggest the C++ constexpr syntax.
>
> Would this support generics? E.g. could you do:
>
> @constepxr
> func foo(a:S, b:S) {
>return a+b
> }
>
> and have that be done at compile time? While this could potentially
> add a huge amount of complication on the backend, I could this as
> being useful (also related to my previous postings as to having a way
> of determining generic types at compile time).
>
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Anton Zhilin via swift-evolution
2017-02-17 17:13 GMT+03:00 T.J. Usiyan :

It is my opinion that you are describing an entirely different, and
> somewhat orthogonal, feature. I would like the feature that you describe.
> Constant expressions are powerful and open up quite a few optimizations.
> What constexpr addresses is not purity, at the heart of it. Pure
> expressions that accept compile-time-known values are, by happy accident,
> compile-time-computable, but pure expressions that accept dynamic values
> are not. Conflating the two qualities of being compile-time-known and being
> pure within the same keyword and overloading it in this way is not
> desirable to me.
>
I see now. I’d say that access to global state is not vital, and @pure
functions are more useful than @const functions, so I’m OK with having only
@const functions.

To control growth of compilation time, we could have both @pure function
annotation and @const variable annotation to *ensure* that a @pure
expression is computed at compilation time.

I’d also want to infer @pure whenever possible, but is it possible with
functions in different modules?
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Abe Schneider via swift-evolution
+1. I think this is a great idea. As I was following this thread, I
was wondering if someone might suggest the C++ constexpr syntax.

Would this support generics? E.g. could you do:

@constepxr
func foo(a:S, b:S) {
   return a+b
}

and have that be done at compile time? While this could potentially
add a huge amount of complication on the backend, I could this as
being useful (also related to my previous postings as to having a way
of determining generic types at compile time).


On Fri, Feb 17, 2017 at 8:01 AM, Anton Zhilin via swift-evolution
 wrote:
> My vision of “pure” functions was the following:
>
> Compiler automatically marks all functions and expressions as pure, wherever
> possible
>
> We should be interested not in “Haskell-ish pure” functions, but in
> “computable during compilation” functions
> Therefore I prefer to use @constexpr or const instead of @pure
>
> We can mark a function as const to assert that it is indeed pure
> We can mark a variable as const to ensure that it’s computed at compilation
> time
>
> Compiler might compute some non-const expressions, but no guarantees given
>
> One issue is, we don’t have or suggest any facilities to make use of pure
> functions, other than some optimization, which can be performed anyway as of
> now.
>
> One use-case would be conversion of metatypes to types:
>
> const let x: Any = makeSomething()
> typealias T = type(of: x)
>
> This feature can be powerful enough to fill the niche of macros in Swift,
> without unsafety of C++ or specific syntax of Rust.
>
> 2017-02-17 14:14 GMT+03:00 Haravikk via swift-evolution
> :
>>
>> I like the idea of having pure functions in Swift, but my first thought
>> is; should we have to declare it at all? Is it not easier to just have the
>> compiler automatically flag a function as pure or not?
>>
>> With that in mind we don't need any new syntax, but a simple @pure
>> attribute should be sufficient. This can be used anywhere that a function is
>> declared, or a closure is accepted as a parameter, allowing us to be
>> explicit that we are trying to define a pure function, or only accept pure
>> closures.
>>
>> The big benefit of this is that it is retroactive; all existing functions
>> that are pure will be automatically detected as such, and can be passed into
>> any method accepting only pure functions. The new capability will be that
>> developers can specify that a function *must* be pure and thus produce an
>> error if it isn't.
>
>
> ___
> 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] Support for pure functions. Part n + 1.

2017-02-17 Thread Nicolas Fezans via swift-evolution
+1 for pure functions
+1 for combining them with constexpr
-1 for the syntax originally proposed
+1 for pure or @pure keywords (before func and before a closure opening { )

One thing is probably worth considering if pure functions and closures are
combined with constexpr and evaluated at compile-time. This might be
problematic if the produced results are large (in size) and in that case it
might be interesting to have the possibility to delay the computation at
run-time... maybe with another keyword then?

Nicolas


On Fri, 17 Feb 2017 at 15:37, Matthew Johnson via swift-evolution <
swift-evolution@swift.org> wrote:

> On Feb 16, 2017, at 3:18 PM, T.J. Usiyan via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I am ok with a keyword but `pure` in front of func doesn't work well with
> inline closures.
>
>
> The `=>` function arrow syntax is a clever way to avoid making pure
> functions heaver syntactically than impure functions.  That said, I don’t
> think it will stand out very clearly when reading code and is likely to be
> confusing for new programmers who don’t understand purity or why you would
> sometimes want it and other times that it won’t be possible.
>
> Also, what about pure closures that have no need to state a signature
> because it is inferred?  This syntactic sugar is a pretty important aspect
> of Swift and often times some of our smallest closures will be pure.  For
> example Array’s map should be pure when the closure is pure and many map
> closures are very small.  We don’t want to have to annotate these closures
> with a signature.
>
> Could we allow inference of purity for closures when they are used in a
> context which accepts a pure function?  If we had an annotation similar to
> `rethrows` maybe inference could prefer purity, but fall back to an impure
> semantic for `map` (or other methods using the annotation) when the closure
> isn’t pure.  Come to think of it, using `->` vs `=>` to make the
> distinction kind of falls apart when the purity of a function is
> conditional depending on the purity of its arguments.  Have you thought
> about how to handle this?
>
> Overall, I *really* want to see pure functions in Swift and would be very
> excited to see them make it into Swift 4.  That said, I’m on the fence
> about the syntax you have proposed.
>
>
> A few people talked through many of these issues starting with this tweet.
> https://twitter.com/griotspeak/status/832247545325842432
>
> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull  wrote:
>
> +1 for the idea of pure functions in swift.  Seems like it would enable a
> lot of good optimizations (in some cases even just evaluating the function
> at compile time).
>
> -1 on the specific notation.  I would much rather just put the word ‘pure’
> in front of ‘func’, the same way we put ‘mutating' in front of mutating
> functions… it seems to me like these are part of the same family.
>
> I agree we should allow inout.
>
> Thanks,
> Jon
>
> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> # Pure Functions
>
> * Proposal: [SE-](
> https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
> )
> * Author(s): [TJ Usiyan](https://github.com/griotspeak)
> * Status: **Awaiting review**
> * Review manager: TBD
>
> ## Introduction
>
> Some functions are, essentially, only meant to be transformations of their
> input and–as such–do not and should not reference any variables other than
> those passed in. These same functions are not meant to have any effects
> other than the aforementioned transformation of input. Currently, Swift
> cannot assist the developer and confirm that any given function is one of
> these 'pure' functions. To facilitate this, this proposal adds syntax to
> signal that a function is 'pure'.
>
> 'pure', in this context, means:
> 1. The function must have a return value
> 1. This function can only call other pure functions
> 1. This function cannot access/modify global or static variables.
>
> ## Motivation
>
> Consider the following example where `_computeNullability(of:)` is meant
> to create its output solely based on the provided recognizer.
>
> ```
> class Recognizer {
> var nullabilityMemo: Bool?
> var isNullable: Bool {
> func _computeNullability(of recognizer: Recognizer) -> Bool {…}
> if let back = nullabilityMemo {
> return back
> } else {
> let back =  _computeNullability(of: self)
> nullabilityMemo = back
> return back
> }
> }
> }
> ```
> if `_computeNullability(of:)` is recursive at all, there exists a real
> potential to accidentally reference `self` in its body and the mistake,
> depending on circumstance, can be terribly subtle. Converting
> `_computeNullability(of:)` to a `static` function is an option but
> obfuscates the fact that it is *only* to be called within `isNullable`.
>
>
> ## Proposed solution
>
> Given the ability to indicate that `_computeNullability(of:)` is a 'pure'
> function, the developer 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Matthew Johnson via swift-evolution

> On Feb 16, 2017, at 3:18 PM, T.J. Usiyan via swift-evolution 
>  wrote:
> 
> I am ok with a keyword but `pure` in front of func doesn't work well with 
> inline closures.

The `=>` function arrow syntax is a clever way to avoid making pure functions 
heaver syntactically than impure functions.  That said, I don’t think it will 
stand out very clearly when reading code and is likely to be confusing for new 
programmers who don’t understand purity or why you would sometimes want it and 
other times that it won’t be possible.  

Also, what about pure closures that have no need to state a signature because 
it is inferred?  This syntactic sugar is a pretty important aspect of Swift and 
often times some of our smallest closures will be pure.  For example Array’s 
map should be pure when the closure is pure and many map closures are very 
small.  We don’t want to have to annotate these closures with a signature.  

Could we allow inference of purity for closures when they are used in a context 
which accepts a pure function?  If we had an annotation similar to `rethrows` 
maybe inference could prefer purity, but fall back to an impure semantic for 
`map` (or other methods using the annotation) when the closure isn’t pure.  
Come to think of it, using `->` vs `=>` to make the distinction kind of falls 
apart when the purity of a function is conditional depending on the purity of 
its arguments.  Have you thought about how to handle this?

Overall, I *really* want to see pure functions in Swift and would be very 
excited to see them make it into Swift 4.  That said, I’m on the fence about 
the syntax you have proposed.

> 
> A few people talked through many of these issues starting with this tweet. 
> https://twitter.com/griotspeak/status/832247545325842432 
> 
> 
> On Thu, Feb 16, 2017 at 4:13 PM, Jonathan Hull  > wrote:
> +1 for the idea of pure functions in swift.  Seems like it would enable a lot 
> of good optimizations (in some cases even just evaluating the function at 
> compile time).
> 
> -1 on the specific notation.  I would much rather just put the word ‘pure’ in 
> front of ‘func’, the same way we put ‘mutating' in front of mutating 
> functions… it seems to me like these are part of the same family.
> 
> I agree we should allow inout.
> 
> Thanks,
> Jon
> 
>> On Feb 16, 2017, at 9:03 AM, T.J. Usiyan via swift-evolution 
>> > wrote:
>> 
>> # Pure Functions
>> 
>> * Proposal: 
>> [SE-](https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
>>  
>> )
>> * Author(s): [TJ Usiyan](https://github.com/griotspeak 
>> )
>> * Status: **Awaiting review**
>> * Review manager: TBD
>> 
>> ## Introduction
>> 
>> Some functions are, essentially, only meant to be transformations of their 
>> input and–as such–do not and should not reference any variables other than 
>> those passed in. These same functions are not meant to have any effects 
>> other than the aforementioned transformation of input. Currently, Swift 
>> cannot assist the developer and confirm that any given function is one of 
>> these 'pure' functions. To facilitate this, this proposal adds syntax to 
>> signal that a function is 'pure'.
>> 
>> 'pure', in this context, means:
>> 1. The function must have a return value
>> 1. This function can only call other pure functions
>> 1. This function cannot access/modify global or static variables.
>> 
>> ## Motivation
>> 
>> Consider the following example where `_computeNullability(of:)` is meant to 
>> create its output solely based on the provided recognizer.
>> 
>> ```
>> class Recognizer {
>>  var nullabilityMemo: Bool?
>>  var isNullable: Bool {
>>  func _computeNullability(of recognizer: Recognizer) -> Bool {…}
>>  if let back = nullabilityMemo {
>>  return back 
>>  } else {
>>  let back =  _computeNullability(of: self)
>>  nullabilityMemo = back
>>  return back
>>  }
>>  }
>> }
>> ```
>> if `_computeNullability(of:)` is recursive at all, there exists a real 
>> potential to accidentally reference `self` in its body and the mistake, 
>> depending on circumstance, can be terribly subtle. Converting 
>> `_computeNullability(of:)` to a `static` function is an option but 
>> obfuscates the fact that it is *only* to be called within `isNullable`.
>> 
>> 
>> ## Proposed solution
>> 
>> Given the ability to indicate that `_computeNullability(of:)` is a 'pure' 
>> function, the developer gains assurance from the tooling that it doesn't 
>> reference anything or cause any side effects.
>> 
>> 
>> ```
>> class Recognizer {
>>  var 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread T.J. Usiyan via swift-evolution
Anton,

It is my opinion that you are describing an entirely different, and
somewhat orthogonal, feature. I would like the feature that you describe.
Constant expressions are powerful and open up quite a few optimizations.
What constexpr addresses is not purity, at the heart of it. Pure
expressions that accept compile-time-known values are, by happy accident,
compile-time-computable, but pure expressions that accept dynamic values
are not. Conflating the two qualities of being compile-time-known and being
pure within the same keyword and overloading it in this way is not
desirable to me.


Thank you,
TJ

On Fri, Feb 17, 2017 at 8:01 AM, Anton Zhilin via swift-evolution <
swift-evolution@swift.org> wrote:

> My vision of “pure” functions was the following:
>
>1. Compiler automatically marks all functions and expressions as pure,
>wherever possible
>   - We should be interested not in “Haskell-ish pure” functions, but
>   in “computable during compilation” functions
>   - Therefore I prefer to use @constexpr or const instead of @pure
>2. We can mark a function as const to *assert* that it is indeed pure
>3. We can mark a variable as const to *ensure* that it’s computed at
>compilation time
>   - Compiler might compute some non-const expressions, but no
>   guarantees given
>
> One issue is, we don’t have or suggest any facilities to make use of pure
> functions, other than some optimization, which can be performed anyway as
> of now.
>
> One use-case would be conversion of metatypes to types:
>
> const let x: Any = makeSomething()
> typealias T = type(of: x)
>
> This feature can be powerful enough to fill the niche of macros in Swift,
> without unsafety of C++ or specific syntax of Rust.
>
> 2017-02-17 14:14 GMT+03:00 Haravikk via swift-evolution <
> swift-evolution@swift.org>:
>
> I like the idea of having pure functions in Swift, but my first thought
>> is; should we have to declare it at all? Is it not easier to just have the
>> compiler automatically flag a function as pure or not?
>>
>> With that in mind we don't need any new syntax, but a simple @pure
>> attribute should be sufficient. This can be used anywhere that a function
>> is declared, or a closure is accepted as a parameter, allowing us to be
>> explicit that we are trying to define a pure function, or only accept pure
>> closures.
>>
>> The big benefit of this is that it is retroactive; all existing functions
>> that are pure will be automatically detected as such, and can be passed
>> into any method accepting only pure functions. The new capability will be
>> that developers can specify that a function *must* be pure and thus produce
>> an error if it isn't.
>>
> ​
>
> ___
> 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] Support for pure functions. Part n + 1.

2017-02-17 Thread David Hart via swift-evolution

> On 17 Feb 2017, at 08:59, Nicolas Fezans via swift-evolution 
>  wrote:
> 
> > Not only that, but even if you pass a value type as a parameter, that value 
> > type might have reference types as ivars.
> 
> I think that arguments passed to a pure function shall be checked against 
> containing such references or objects that contains such references 
> themselves: I guess that this check could be made by the compiler.
> Programmers will then have to see whether they choose a) to go to "pure 
> value-type arguments" (i.e. not containing directly nor indirectly such 
> references) and be able to declare some of their functions as pure or b) to 
> keep these references and not declare the corresponding functions as pure.

Wouldn't we need a way to declare value semantics? Array has such references 
but has value semantics so should be fine, no?

> This seems to me to be the first and relatively easy way to solve this 
> problem. Later on I could imagine even that the compiler would be clever 
> enough to check whether the contained references are used (regardless of 
> whether it is just for a read access or also to mutate some values existing 
> outside the scope of the function itself) and if they are not used the purity 
> of the function could be validated also in that case.
> 
> 
> Nicolas
> 
> 
> 
>> On Fri, Feb 17, 2017 at 8:26 AM, Charles Srstka via swift-evolution 
>>  wrote:
>> On Feb 16, 2017, at 1:27 PM, Sean Heber via swift-evolution 
>>  wrote:
>> >
>> > Doesn’t this break down if you can pass a reference as a parameter to a 
>> > pure function? If that’s not allowed, I guess I must have missed it. Also 
>> > this seems to require the function has a return value. I suppose generally 
>> > a pure function without a return value wouldn’t make much sense - unless 
>> > you pass it a reference.
>> 
>> Not only that, but even if you pass a value type as a parameter, that value 
>> type might have reference types as ivars. So since any call to any reference 
>> type can potentially mutate it, and any call to any value type could call 
>> through to a reference type which might then be mutated, it does seem that 
>> purity is quite difficult to guarantee.
>> 
>> 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
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Anton Zhilin via swift-evolution
My vision of “pure” functions was the following:

   1. Compiler automatically marks all functions and expressions as pure,
   wherever possible
  - We should be interested not in “Haskell-ish pure” functions, but in
  “computable during compilation” functions
  - Therefore I prefer to use @constexpr or const instead of @pure
   2. We can mark a function as const to *assert* that it is indeed pure
   3. We can mark a variable as const to *ensure* that it’s computed at
   compilation time
  - Compiler might compute some non-const expressions, but no
  guarantees given

One issue is, we don’t have or suggest any facilities to make use of pure
functions, other than some optimization, which can be performed anyway as
of now.

One use-case would be conversion of metatypes to types:

const let x: Any = makeSomething()
typealias T = type(of: x)

This feature can be powerful enough to fill the niche of macros in Swift,
without unsafety of C++ or specific syntax of Rust.

2017-02-17 14:14 GMT+03:00 Haravikk via swift-evolution <
swift-evolution@swift.org>:

I like the idea of having pure functions in Swift, but my first thought is;
> should we have to declare it at all? Is it not easier to just have the
> compiler automatically flag a function as pure or not?
>
> With that in mind we don't need any new syntax, but a simple @pure
> attribute should be sufficient. This can be used anywhere that a function
> is declared, or a closure is accepted as a parameter, allowing us to be
> explicit that we are trying to define a pure function, or only accept pure
> closures.
>
> The big benefit of this is that it is retroactive; all existing functions
> that are pure will be automatically detected as such, and can be passed
> into any method accepting only pure functions. The new capability will be
> that developers can specify that a function *must* be pure and thus produce
> an error if it isn't.
>
​
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Haravikk via swift-evolution
I like the idea of having pure functions in Swift, but my first thought is; 
should we have to declare it at all? Is it not easier to just have the compiler 
automatically flag a function as pure or not?

With that in mind we don't need any new syntax, but a simple @pure attribute 
should be sufficient. This can be used anywhere that a function is declared, or 
a closure is accepted as a parameter, allowing us to be explicit that we are 
trying to define a pure function, or only accept pure closures.

The big benefit of this is that it is retroactive; all existing functions that 
are pure will be automatically detected as such, and can be passed into any 
method accepting only pure functions. The new capability will be that 
developers can specify that a function *must* be pure and thus produce an error 
if it isn't.

> On 16 Feb 2017, at 17:03, T.J. Usiyan via swift-evolution 
>  wrote:
> 
> # Pure Functions
> 
> * Proposal: 
> [SE-](https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
>  
> )
> * Author(s): [TJ Usiyan](https://github.com/griotspeak 
> )
> * Status: **Awaiting review**
> * Review manager: TBD
> 
> ## Introduction
> 
> Some functions are, essentially, only meant to be transformations of their 
> input and–as such–do not and should not reference any variables other than 
> those passed in. These same functions are not meant to have any effects other 
> than the aforementioned transformation of input. Currently, Swift cannot 
> assist the developer and confirm that any given function is one of these 
> 'pure' functions. To facilitate this, this proposal adds syntax to signal 
> that a function is 'pure'.
> 
> 'pure', in this context, means:
> 1. The function must have a return value
> 1. This function can only call other pure functions
> 1. This function cannot access/modify global or static variables.
> 
> ## Motivation
> 
> Consider the following example where `_computeNullability(of:)` is meant to 
> create its output solely based on the provided recognizer.
> 
> ```
> class Recognizer {
>   var nullabilityMemo: Bool?
>   var isNullable: Bool {
>   func _computeNullability(of recognizer: Recognizer) -> Bool {…}
>   if let back = nullabilityMemo {
>   return back 
>   } else {
>   let back =  _computeNullability(of: self)
>   nullabilityMemo = back
>   return back
>   }
>   }
> }
> ```
> if `_computeNullability(of:)` is recursive at all, there exists a real 
> potential to accidentally reference `self` in its body and the mistake, 
> depending on circumstance, can be terribly subtle. Converting 
> `_computeNullability(of:)` to a `static` function is an option but obfuscates 
> the fact that it is *only* to be called within `isNullable`.
> 
> 
> ## Proposed solution
> 
> Given the ability to indicate that `_computeNullability(of:)` is a 'pure' 
> function, the developer gains assurance from the tooling that it doesn't 
> reference anything or cause any side effects.
> 
> 
> ```
> class Recognizer {
>   var nullabilityMemo: Bool?
>   var isNullable: Bool {
>   pfunc _computeNullability(of recognizer: Recognizer) -> Bool {…}
>   if let back = nullabilityMemo {
>   return back 
>   } else {
>   let back =  _computeNullability(of: self)
>   nullabilityMemo = back
>   return back
>   }
>   }
> }
> ```
> 
> ## Detailed design
> 
> This proposal introduces a new annotation `=>`, which is to be accepted 
> everywhere `->` currently is. Members created using this kewyord must follow 
> the rules listed in the introduction.
> 
> ## Impact on existing code
> 
> This is an additive feature unless alternative 2 is chosen and, as such, 
> should not require an effect on existing code. It could be used to annotate 
> closures accepted by methods in the standard library such as `map`, `filter`, 
> and `reduce`. While this would fit well with their typical use, such a change 
> is not necessarily part of this proposal.
> 
> ## Alternatives considered
> 
> It should be noted that neither of these alternatives can remain consistent 
> for inline closures.
> 1. keyword `pfunc` (pronounciation: pifəŋk) for 'pure' functions. 
> 2. `proc` keyword for 'impure' functions and 'func' for 'pure' functions. 
> This would be a massively source breaking change and, as such, is unlikely to 
> have any feasibility. It is, however, the most clean semantically, in my 
> opinion.
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread James Froggatt via swift-evolution
This syntax is actually a really clean solution, which can be generalised to 
arguments and composes well:

A -> B => C -> D
vs
A -> (@pure B -> C -> D)

 Begin Message  
Group: gmane.comp.lang.swift.evolution 
MsgID: 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread James Froggatt via swift-evolution
This syntax is actually a really clean solution, which can be generalised to 
arguments and composes well:

A -> B => C -> D
vs
A -> (@pure B -> C -> D)

 Begin Message  
Group: gmane.comp.lang.swift.evolution 
MsgID: 

Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-17 Thread Nicolas Fezans via swift-evolution
> Not only that, but even if you pass a value type as a parameter, that
value type might have reference types as ivars.

I think that arguments passed to a pure function shall be checked against
containing such references or objects that contains such references
themselves: I guess that this check could be made by the compiler.
Programmers will then have to see whether they choose a) to go to "pure
value-type arguments" (i.e. not containing directly nor indirectly such
references) and be able to declare some of their functions as pure or b) to
keep these references and not declare the corresponding functions as pure.

This seems to me to be the first and relatively easy way to solve this
problem. Later on I could imagine even that the compiler would be clever
enough to check whether the contained references are used (regardless of
whether it is just for a read access or also to mutate some values existing
outside the scope of the function itself) and if they are not used the
purity of the function could be validated also in that case.


Nicolas



On Fri, Feb 17, 2017 at 8:26 AM, Charles Srstka via swift-evolution <
swift-evolution@swift.org> wrote:

> On Feb 16, 2017, at 1:27 PM, Sean Heber via swift-evolution <
> swift-evolution@swift.org> wrote:
> >
> > Doesn’t this break down if you can pass a reference as a parameter to a
> pure function? If that’s not allowed, I guess I must have missed it. Also
> this seems to require the function has a return value. I suppose generally
> a pure function without a return value wouldn’t make much sense - unless
> you pass it a reference.
>
> Not only that, but even if you pass a value type as a parameter, that
> value type might have reference types as ivars. So since any call to any
> reference type can potentially mutate it, and any call to any value type
> could call through to a reference type which might then be mutated, it does
> seem that purity is quite difficult to guarantee.
>
> 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] [Pitch] Support for pure functions. Part n + 1.

2017-02-16 Thread Charles Srstka via swift-evolution
On Feb 16, 2017, at 1:27 PM, Sean Heber via swift-evolution 
 wrote:
> 
> Doesn’t this break down if you can pass a reference as a parameter to a pure 
> function? If that’s not allowed, I guess I must have missed it. Also this 
> seems to require the function has a return value. I suppose generally a pure 
> function without a return value wouldn’t make much sense - unless you pass it 
> a reference.

Not only that, but even if you pass a value type as a parameter, that value 
type might have reference types as ivars. So since any call to any reference 
type can potentially mutate it, and any call to any value type could call 
through to a reference type which might then be mutated, it does seem that 
purity is quite difficult to guarantee.

Charles

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-16 Thread Michel Fortin via swift-evolution
I'm just going to point out to the documentation about pure functions in the D 
language which has an unusual but very practical take on enforcing purity. It's 
interesting, and it might also provide a list for things that might need be 
addressed in this proposal.
https://dlang.org/spec/function.html#pure-functions

> Le 16 févr. 2017 à 12:03, T.J. Usiyan via swift-evolution 
>  a écrit :
> 
> # Pure Functions
> 
> * Proposal: 
> [SE-](https://github.com/apple/swift-evolution/blob/master/proposals/-name.md
>  
> )
> * Author(s): [TJ Usiyan](https://github.com/griotspeak 
> )
> * Status: **Awaiting review**
> * Review manager: TBD
> 
> ## Introduction
> 
> Some functions are, essentially, only meant to be transformations of their 
> input and–as such–do not and should not reference any variables other than 
> those passed in. These same functions are not meant to have any effects other 
> than the aforementioned transformation of input. Currently, Swift cannot 
> assist the developer and confirm that any given function is one of these 
> 'pure' functions. To facilitate this, this proposal adds syntax to signal 
> that a function is 'pure'.
> 
> 'pure', in this context, means:
> 1. The function must have a return value
> 1. This function can only call other pure functions
> 1. This function cannot access/modify global or static variables.
> 
> ## Motivation
> 
> Consider the following example where `_computeNullability(of:)` is meant to 
> create its output solely based on the provided recognizer.
> 
> ```
> class Recognizer {
>   var nullabilityMemo: Bool?
>   var isNullable: Bool {
>   func _computeNullability(of recognizer: Recognizer) -> Bool {…}
>   if let back = nullabilityMemo {
>   return back 
>   } else {
>   let back =  _computeNullability(of: self)
>   nullabilityMemo = back
>   return back
>   }
>   }
> }
> ```
> if `_computeNullability(of:)` is recursive at all, there exists a real 
> potential to accidentally reference `self` in its body and the mistake, 
> depending on circumstance, can be terribly subtle. Converting 
> `_computeNullability(of:)` to a `static` function is an option but obfuscates 
> the fact that it is *only* to be called within `isNullable`.
> 
> 
> ## Proposed solution
> 
> Given the ability to indicate that `_computeNullability(of:)` is a 'pure' 
> function, the developer gains assurance from the tooling that it doesn't 
> reference anything or cause any side effects.
> 
> 
> ```
> class Recognizer {
>   var nullabilityMemo: Bool?
>   var isNullable: Bool {
>   pfunc _computeNullability(of recognizer: Recognizer) -> Bool {…}
>   if let back = nullabilityMemo {
>   return back 
>   } else {
>   let back =  _computeNullability(of: self)
>   nullabilityMemo = back
>   return back
>   }
>   }
> }
> ```
> 
> ## Detailed design
> 
> This proposal introduces a new annotation `=>`, which is to be accepted 
> everywhere `->` currently is. Members created using this kewyord must follow 
> the rules listed in the introduction.
> 
> ## Impact on existing code
> 
> This is an additive feature unless alternative 2 is chosen and, as such, 
> should not require an effect on existing code. It could be used to annotate 
> closures accepted by methods in the standard library such as `map`, `filter`, 
> and `reduce`. While this would fit well with their typical use, such a change 
> is not necessarily part of this proposal.
> 
> ## Alternatives considered
> 
> It should be noted that neither of these alternatives can remain consistent 
> for inline closures.
> 1. keyword `pfunc` (pronounciation: pifəŋk) for 'pure' functions. 
> 2. `proc` keyword for 'impure' functions and 'func' for 'pure' functions. 
> This would be a massively source breaking change and, as such, is unlikely to 
> have any feasibility. It is, however, the most clean semantically, in my 
> opinion.
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-- 
Michel Fortin
https://michelf.ca

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-16 Thread David Sweeris via swift-evolution

> On Feb 16, 2017, at 18:00, Slava Pestov  wrote:
> 
> 
>>> On Feb 16, 2017, at 5:15 PM, David Sweeris via swift-evolution 
>>>  wrote:
>>> 
>>> 
>>> On Feb 16, 2017, at 3:13 PM, David Hart via swift-evolution 
>>>  wrote:
>>> 
>>> Now that I've thought more about it, I have a question. Escaping/unescaping 
>>> is an important concept to have in the language: if the API provider makes 
>>> the promise that a closure is non-escaping, the API client doesn't have to 
>>> worry about the closure capturing variables and creating strong references 
>>> to them.
>>> 
>>> But in the case of pure functions, I fail to get the benefit from the 
>>> examples. Could someone explain to me the advantages with a more in-depth 
>>> example?
>> 
>> AFAIK, the two most direct benefits are memoization (without an “r”) and 
>> concurrency. Because the everything the function does is contained within 
>> the function itself and it can’t change or be affected by any global state, 
>> the compiler can prove it’s ok to, for instance, parallelize a loop for you 
>> if everything inside the loop is “pure". Additionally, because a pure 
>> function will always give you the same output for the same input, you (or 
>> the compiler, if it supports that level of optimization) can safely cache 
>> the results of a function call in a Dictionary or something, and next time 
>> the function is called do a quick lookup to see if you already know the 
>> answer before passing the inputs along to the “real" function. The benefits 
>> of this obviously depend on what the function is doing… it wouldn’t make 
>> sense to cache simple integer addition, but if your function has, IDK, loops 
>> nested 23 levels deep and they all involve floating point division and 
>> matrix multiplication or something, caching the answer will likely pay off.
> 
> I think memoization should be opt-in rather than something the compiler 
> automatically infers. It has non-trivial time and space complexity tradeoffs, 
> and I wouldn’t want the compiler making these decisions behind my back, or 
> the behavior of a program changing between optimized and debug builds.

Oh, totally, yeah (same for auto-parallelization, too... maybe I want those 
cores doing something else).

Giving the compiler some notion of a "pure function" is a pre-requisite for 
implementing either in the compiler, though, and in the meantime, having the 
annotation helps the people trying to manually memoize:

struct Memoizer  {
var cache = [T:U]()
let transform: (T)->U
init(_ transform: @pure (T)->U) {
self.transform = transform
}
subscript(_ arg: T) -> U {
if let ans = cache[arg] {
return ans
} else {
let ans = transform(arg)
cache[arg] = ans
return ans
}
}
}

Without the compiler enforcing the @pure part, this becomes unsafe.

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


Re: [swift-evolution] [Pitch] Support for pure functions. Part n + 1.

2017-02-16 Thread Slava Pestov via swift-evolution

> On Feb 16, 2017, at 5:15 PM, David Sweeris via swift-evolution 
>  wrote:
> 
> 
>> On Feb 16, 2017, at 3:13 PM, David Hart via swift-evolution 
>> > wrote:
>> 
>> Now that I've thought more about it, I have a question. Escaping/unescaping 
>> is an important concept to have in the language: if the API provider makes 
>> the promise that a closure is non-escaping, the API client doesn't have to 
>> worry about the closure capturing variables and creating strong references 
>> to them.
>> 
>> But in the case of pure functions, I fail to get the benefit from the 
>> examples. Could someone explain to me the advantages with a more in-depth 
>> example?
> 
> AFAIK, the two most direct benefits are memoization (without an “r”) and 
> concurrency. Because the everything the function does is contained within the 
> function itself and it can’t change or be affected by any global state, the 
> compiler can prove it’s ok to, for instance, parallelize a loop for you if 
> everything inside the loop is “pure". Additionally, because a pure function 
> will always give you the same output for the same input, you (or the 
> compiler, if it supports that level of optimization) can safely cache the 
> results of a function call in a Dictionary or something, and next time the 
> function is called do a quick lookup to see if you already know the answer 
> before passing the inputs along to the “real" function. The benefits of this 
> obviously depend on what the function is doing… it wouldn’t make sense to 
> cache simple integer addition, but if your function has, IDK, loops nested 23 
> levels deep and they all involve floating point division and matrix 
> multiplication or something, caching the answer will likely pay off.

I think memoization should be opt-in rather than something the compiler 
automatically infers. It has non-trivial time and space complexity tradeoffs, 
and I wouldn’t want the compiler making these decisions behind my back, or the 
behavior of a program changing between optimized and debug builds.

Slava

> 
> Here’s a article/site/blog/etc that talks about the more “quality of life” 
> kind of benefits: http://scalafp.com/book/benefits-of-pure-functions.html 
>  (note that some 
> people will vigorously contest the “easier to reason about” claim)
> 
> - 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


  1   2   >