> As Andy says, the major problem is that public API (which you can't see the implementation of in general) would all need to be marked up properly.
The use-case I'm most interested in is reducing programmer error, I'm personally not too concerned about optimisations achieved by "pure" at this stage. This means I'd be happy in the short-term to ignore a verified strong purity requirement, and allow "pure" to be achieved in multiple stages/releases. A gradual adoption would also make it easier to enforce the concept strictly in future. Purity could initial be defined in two levels, weak and strong. - *strong purity*: everything in the function has strong purity, what we've been discussing - *weak purity*: everything in the function is strong-pure, weak-pure, or says "trust me" The following code suggest how this might work, it introduces a few things: - *pure* keyword, indicates that a function is has either weak or strong purity - *pretendPure* (ignore the name) pretends whatever happens inside it is pure, it has weak purity func strongPurityFunction(_ lhs: Int, rhs: Int) pure -> Int { return lhs + rhs } func weakPurityFunction(value: Int) pure -> Int { return pretendPure { functionFromAnotherLibrary(value) } } func anotherWeakPurityFunction(value: Int) pure -> Int { return weakPurityFunction(value: value) } When this gets compiled to SIL the pure annotations would specialised as: func strongPurityFunction(_ lhs: Int, rhs: Int) _strong_pure -> Int func weakPurityFunction(value: Int) _weak_pure -> Int func anotherWeakPurityFunction(value: Int) _weak_pure -> Int Marking a function as pure, but using an unannotated function could start as a warning, then become an error. func failingFunction(value: Int) pure -> Int { return nonPureFunction(value: value) } The staged rollout could go something like this: - _weak_pure only with *pretendPure* or equivalent - _strong_pure, _weak_pure, and *pretendPure* - _strong_pure, deprecate _weak_pure, and *pretendPure* - _strong_pure only On Sun, Sep 10, 2017 at 3:01 PM, David Sweeris via swift-evolution < swift-evolution@swift.org> wrote: > > > On Sep 9, 2017, at 10:48 AM, Dave Abrahams via swift-evolution < > swift-evolution@swift.org> wrote: > > > > on Wed Aug 23 2017, Joe Groff <swift-evolution@swift.org> wrote: > >>>> On Aug 18, 2017, at 12:10 PM, Chris Lattner via swift-evolution < > swift-evolution@swift.org> wrote: Splitting this out from the > concurrency thread: > >>>> > >>>>> On Aug 18, 2017, at 6:12 AM, Matthew Johnson <matt...@anandabits.com> > wrote: > >>>>>> On Aug 17, 2017, at 11:53 PM, Chris Lattner <clatt...@nondot.org> > wrote: > >>>>>> In the manifesto you talk about restrictions on passing functions > across an actor message. You didn’t discuss pure functions, presumably > because Swift doesn’t have them yet. I imagine that if (hopefully when) > Swift has compiler support for verifying pure functions these would also be > safe to pass across an actor message. Is that correct? > >>>>> Correct. The proposal is specifically/intentionally designed to be > light on type system additions, but there are many that could make it > better in various ways. The logic for this approach is that I expect *a > lot* of people will be writing mostly straight-forward concurrent code, and > that goal is harmed by presenting significant type system hurdles for them > to jump over, because that implies a higher learning curve. This is why > the proposal doesn’t focus on a provably memory safe system: If someone > slaps “ValueSemantical” on a type that doesn’t obey, they will break the > invariants of the system. There are lots of ways to solve that problem > (e.g. the capabilities system in Pony) but it introduces a steep learning > curve. I haven’t thought a lot about practically getting pure functions > into Swift, because it wasn’t clear what problems it would solve (which > couldn’t be solved another way). You’re right though that this could be an > interesting motivator. > >>>> I can provide a concrete example of why this is definitely and > important motivator. My current project uses pure functions, value > semantics and declarative effects at the application level and moves as > much of the imperative code as possible (including effect handling) into > library level code. This is working out really well and I plan to continue > with this approach. The library level code needs the ability to schedule > user code in the appropriate context. There will likely be some > declarative ability for application level code to influence the context, > priority, etc, but it is the library that will be moving the functions to > the final context. They are obviously not closure literals from the > perspective of the library. Pure functions are obviously important to the > semantics of this approach. We can get by without compiler verification, > using documentation just as we do for protocol requirements that can't be > verified. That said, it would be pretty disappointing to have to avoid > using actors in the implementation simply because we can't move pure > functions from one actor to another as necessary. To be clear, I am > talking in the context of "the fullness of time". It would be perfectly > acceptable to ship actors before pure functions. That said, I do think it's > crucial that we eventually have the ability to verify pure functions and > move them around at will. > >>> Right. Pure functions are also nice when you care about thread > safety, and there is a lot of work on this. C has __attribute__((const)) > and ((pure)) for example, c++ has constexpr, and many research languages > have built full blown effects systems. My principle concern is that > things like this quickly become infectious: LOTS of things are pure > functions, and requiring them all to be marked as such becomes a lot of > boilerplate and conceptual overhead. This is happening in the C++ > community with constexpr for example. The secondary concern is that you > need to build out the model enough that you don’t prevent abstractions. A > pure function should be able to create an instance of a struct, mutate it > (i.e. calling non-pure functions) etc. This requires a non-trivial design, > and as the design complexity creeps, you run the risk of it getting out of > control. > >> Now that inout parameters are guaranteed exclusive, a mutating method > on a struct or a function that takes inout parameters is isomorphic to one > that consumes the initial value as a pure argument and returns the modified > value back. This provides a value-semantics-friendly notion of purity, > where a function can still be considered pure if the only thing it mutates > is its unescaped local state and its inout parameters and it doesn't read > or write any shared mutable state such as mutable globals, instance > properties, or escaped variables. That gives you the ability to declare > local variables and composably apply "pure" mutating operations to them > inside a pure function. We've already brought Swift somewhat into the > effects-system design space with "throws" (and "async", if it gets taken as > we've currently proposed it), and we already have some abstraction debt to > pay off with "throws"; if we wanted to, we could conceivably fold "impure" > into that system as well. While it's true that there would be a lot of > effort in propagating pure annotations to the right places, that's going to > be true of any attempt to move the current everything-goes world into a > more robust and constrained framework. I don't think we should write off > the notion completely. > > > > I agree with Joe here... in principle. We keep finding features we want > to add that have effects-system-like semantics, and I expect that we will > continue to do so. The best language design would probably result from > addressing this category of feature in some holistic way. My main concern > is that in practice, it seems unlikely to be doable before ABI lockdown > makes it too late. > > Is there anything in particular that would make it more likely to be > doable before ABI lockdown? (Other that pushing it back again, I mean) > > I'd guess that if it were as simple as adding a few "reserved for future > use" bits in the on-disk representation, you wouldn't have raised the issue. > > - 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