> On Feb 19, 2017, at 11:19 PM, Xiaodi Wu via swift-evolution 
> <[email protected]> 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, 
> meaning any realistic adoption would have to mean "trust me, compiler, it's 
> pure even though you can't prove it" as opposed to "go ahead, compiler, test 
> my assertion that this function is pure." If Swift is to keep its promise of 
> safety by default (granted, principally memory safety), this is going to have 
> to prompt some soul-searching as to whether that's a very safe thing to add. 
> It would also mean that lots of things would have to be manually annotated 
> "trust me" after careful analysis of whether that trust is warranted, as 
> opposed to the compiler being able to work that out for itself for free.
> 
> Can I venture an operational definition of semantic purity? Maybe this would 
> be a basis to talk about what "trust me, it's pure" would mean, if we wanted 
> it:
> 
> Consider two variables `a` and `b`, without regard to whether they are 
> instances of value types or reference types, and without regard to whether 
> those types are Equatable.
> 
> ```
> let aa = a
> let bb = b
> ```
> 
> Let's define, only for the purposes of this discussion and not as an actual 
> syntax, a notion of pseudo-equality. We will say that `aa` is pseudo-equal to 
> `a` and `bb` is pseudo-equal to `b`. (I deliberately choose not to conflate 
> this notion with Equatable's `==` or with `===`.) Now, consider a function 
> `f(_:_:)`.
> 
> ```
> let result1 = f(a, b)
> // ...
> // arbitrary code to be executed here
> // ...
> let result2 = f(aa, bb)
> ```
> 
> The function `f(_:_:)` is pure if, for any `aa` pseudo-equal to `a` and for 
> any `bb` pseudo-equal to `b`, and for any arbitrary code in the middle, the 
> snippet above could be replaced by the snippet below with no observable 
> change in behavior:
> 
> ```
> let result1 = f(a, b)
> // ...
> // arbitrary code to be executed here
> // ...
> let result2 = result1
> ```
> 
> Now, this naive definition would preclude I/O and inout, but it would not 
> preclude infinite loops, fatal errors, etc.

This looks like it corresponds with my intuition of pure.  It is certainly a 
minimum requirement anything considered pure should meet (whether compiler 
verified or “trust me”). 

> 
> 
> On Sun, Feb 19, 2017 at 10:49 PM, Michel Fortin <[email protected] 
> <mailto:[email protected]>> wrote:
> 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 
> <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 
> <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 
> <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 
> <[email protected] <mailto:[email protected]>> 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 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 
>> <[email protected] <mailto:[email protected]>> 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 <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> On Feb 19, 2017, at 11:47, Michel Fortin via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> 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
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> -- 
> Michel Fortin
> https://michelf.ca <https://michelf.ca/>
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to