[swift-evolution] [Proposal idea] Support for pure functions

Andrew Bennett cacoyi at gmail.com
Sun Jan 10 17:42:13 CST 2016


Hi Jimmy,

Interesting ideas with !, although I'm worried it would clash with other
uses of the operator. For example: optional return types. There's probably
more precedent for this syntax: sin!(x), but it will also clash in some
cases (optional function in objc protocol, optional closure).

I think something much more verbose (a function) would be fine as it's
probably not going to be called often. I expect initially it's probably
sufficient for it to be a Builtin function only used in the standard
library. Failing that a global clearly unsafe function:
unsafelyPurifyFunction(...).

With inout I don't think it is actually weaker, I could be wrong. I see the
following as equivalent (from a purity standpoint):

func test1(inout a: Int) @pure -> Double {}
x = test1(&a)

func test2(a: Int) @pure -> (Double, Int) {}
(x, a) = test2(a)


If they're equivalent then this can be pure:

extension Int {

mutating func addSome(x: Int) @pure {

self += x

}

}

let x: (inout Int, Int) @pure -> Void = Int.addOne


However the curried function signature must be adjusted so it cannot be
partially applied, previously it would have been this:

let x: (inout Int) -> (Int) -> Void = Int.addOne


If we're happy with this equivalence, I don't think it's a useful to
distinguish inout and other pure functions (no need for @pure(unsafe)
here). As long as the parameters predictably cover everything affected I am
happy.

Reference types may be an issue here, but no more than elsewhere.

----

As far as weak-pure goes: I think references have a lot of issues with
@pure. It may be necessary to know if any types a @pure function uses
interact at all with a reference type, stores it, uses it to compute, etc.

A gotcha example:

AnySequence uses a class internally (dynamic dispatch for type erasure), a
pure function may want to return AnySequence, which appears to be a value
type. See ExistentialCollection.swift.gyb.

The compiler may not be able to ensure two sequences with the same input
are equivalent because their internal class has a different reference.
Equitable could definitely work, but at compile time?

This is going to be a problem for referential transparency.

Possible Solutions
 1) Reference types or types composed of reference types are initially
unavailable to @pure functions, unless locally scoped.
 2) Relax the referential transparency requirement when the output is a
reference type or composed of reference types.
 3) Add a @copy keyword for types, this would mean it can be safely use
copy-on-write with no shared references. I think this would be useful in
other cases too, but should be avoided if possible as it's a large change
that would require other proposal(s).

Not entirely a solution, but interesting:

You cannot return a newly allocated reference type, but you can return a
closure: () -> ReferenceType

It can still use memoization to always return the same closure, avoid any
computation to derive the closure, but the closure doesn't necessarily
return the same reference.



On Mon, Jan 11, 2016 at 8:27 AM, Jimmy Sambuo <jsambuo at gmail.com> wrote:

> Thanks Andrew and everyone for your ideas and inputs.
>
> Andrew, your summary is amazing. It covers so many non-trivial cases of
> this feature.
> I believe this is the archive of the other thread:
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160104/006005.html
>
> I was hesitant to add more to this discussion because I was only able to
> think of the trivial case, and I know this can have lots of hidden
> complexities and implications. Looking at Andrew's summary gave me some
> ideas for talking points. Specifically, the section with inout parameters
> and pure mutating functions seems strange to me as I wasn't expecting
> mutation to occur, but this may be a valid scenario for "weakly pure"
> functions, where parameters can be modified.
>
> Chris had mentioned that there probably should be some way to to unsafely
> "force a call to a non-pure function to be allowed in a pure one," and that it
> would probably make sense as an attribute @pure instead of a declmodifier.
> Perhaps this is another form of "weakly pure" functions. I'm thinking in
> this case, pure is acting as a marker, the type system does not have to
> know about actual purity and an effects system would not have to be
> implemented in this case. This should make implementation simpler and less
> invasive to the existing type system.
>
> Imagine if ! was used to call an impure function within a pure function:
>
> ```swift
> /// Wrapper around C sin()
> func sin(x: Double) @pure -> Double {
>     return sin(x)!
> }
> ```
>
> In my mind, seeing ! tells me something could be wrong there so pay closer
> attention. I would think `sin` is a C function so Swift doesn't know it
> should be pure, but sine is a math function so it should be safe. What
> about for actually impure functions? Optionals and try! crashes when
> expectations are not met. Should `potentiallyImpureFunc()!` or
> `mostlyPureFunc()!` crash if an "impure" value or side effect occurs? How
> would the runtime know this if purity is defined by annotations? Maybe it
> shouldn't crash, but now ! is slightly different from optionals and try!.
> Perhaps there should be a different symbol for "unwrapping" impure
> functions. Then there would be two different symbols for unwrapping.
>
> My major concern is I'd want to avoid a situation where developers are
> adding @pure and unwrapping impure functions just to make their app
> compile, making @pure meaningless since most of their pure functions will
> actually be impure. I'm not sure of a good way to prevent this.
>
>
> On Sun, Jan 10, 2016 at 12:41 AM, Andrew Bennett via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>> Hi,
>>
>> I started another thread on @pure in swift, luckily Chris Lattner
>> reminded me about this one. I'm going to continue any discussion here so we
>> don't fragment the conversation.
>>
>> The other thread was a pre-proposal discussion called "Proposal proposal:
>> @pure keyword", it isn't archived so I cannot link it.
>>
>> I've summarised the progress so far here (it's in the proposals directory
>> for convenience):
>>
>>
>> https://github.com/therealbnut/swift/blob/therealbnut-pure-preproprosal/docs/proposals/PureKeyword.rst
>>
>> If I've missed anything or you want to update, clarify, fix typos, etc.
>> please submit a PR :) I'm trying to keep it focused on things that have
>> little contention.
>>
>> I've tried to unify the ideas from both the other thread and this one
>> into that summary. As it's not really a proposal I haven't included the
>> excellent justifications that Jimmy initially stated, they can be added if
>> it becomes a proposal. Please add a PR if you would like them there.
>>
>>
>> On Tue, Dec 22, 2015 at 9:08 AM, Joe Groff via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>>>
>>> > On Dec 21, 2015, at 2:04 PM, Alex Popov via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>> >
>>> > Slight tangent, would a guarantee of purity also allow for more
>>> Tail-Call Optimizations? A cursory glance at SO seems to point to TCO not
>>> always being applied, especially when ARC is involved.
>>>
>>>
>>> I don't think any reasonable meaning for `pure` in Swift would affect
>>> the possibility of TCO. There was another thread about TCO here you might
>>> read back on; as I explained there, ARC is not a barrier to TCO, our
>>> ownership and machine-level calling conventions are. We would need to be
>>> able to use a specific calling convention for guaranteed-TCOable entry
>>> points.
>>>
>>> -Joe
>>>
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
>
> --
> Jimmy Sambuo
> www.sambuo.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160111/b3c7bb36/attachment.html>


More information about the swift-evolution mailing list