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

Jimmy Sambuo jsambuo at gmail.com
Sat Dec 19 23:00:33 CST 2015


Hi Swift-Evolution,

I've been playing around with an idea, and I wanted to see what you think
about it.

My proposal is to add a `pure` keyword/attribute to Swift.

Similar to throws, you would mark a function as pure to say it will not
cause any observable side-effects and hold referential transparency:

```swift

func pure add(x: Int, y: Int) -> Int {

    return x + y

}

```

By adding this attribute, the function is guaranteed to have some
properties:

   1. The function must have a return value
   2. This function can only call other pure functions
   3. This function cannot access/modify global or static variables.

```swift

func pure getDate() -> NSDate {

    return NSDate.date() // Error: pure function 'getDate' cannot call
impure function 'date'

}

```

This would be similar to the pure keyword in D (
https://dlang.org/spec/function.html#pure-functions) or the noSideEffect
pragma in Nim (
http://nim-lang.org/docs/manual.html#pragmas-nosideeffect-pragma).

My motivation for this is that I want to create applications that follow a
"Functional Core, Imperative Shell" style [Gary Bernhardt]. By marking all
of my functions within the functional core as pure, the compiler can help
me if I accidentally start writing impure functions. In theory, this should
make my application simpler and more testable. Reviewing pull requests will
also be simpler since in the functional portion of my codebase, checking
for pure can be a criteria. Ideally, I'd run a static analyzer to see that
I have more pure functions than impure ones, which should help me control
complexity by encouraging me to have a larger "value" layer and smaller
"object" layer [Andy Matuschak].

Logically, I think of this as Swift having all functions return "Implicitly
Impure Values" (similar to how every object from objective-c is an
implicitly unwrapped optional). All existing Swift functions are actually
returning a IO<SomeType>, and functions using that are implicitly
unwrapping them. Swift can be super nice by hiding this fact, making the
language much more familiar and accessible to developers not used to
purity. Adding `pure` allows devs to tap into the compiler's power and
prevent unwanted side-effects without directly exposing the IO type.

The benefits I see are:

   - Explicit intentions - This allows design decisions to be communicated
   clearly to other developers and maintainers, as well as the compiler and
   other static analysis tools.
   - Compile-time guarantee - The compiler can help prevent unintentional
   state modifications.
   - Encouragement of better state management practices - More people will
   be aware of the concept of functional purity and may try to design their
   code to have more pure functions, which should make more code simpler and
   testable. This isn't a guarantee it will happen, but more people should
   understand it if it brings concrete results instead of just being an
   abstract concept.
   - Reduced cognitive load when understanding code - More pure functions
   should make it easier to reason about code.
   - Opt-in to purity - Swift will be just as accessible to new developers,
   but experienced developers will be able to take advantage of this.
   - Backwards compatible (mostly) - Existing codebases should still
   compile without any change (unless pure was used as a variable/method/class
   name).

Of course, there are risks of this feature. Some of the risks include:

   - This could make the language more difficult to work with. Developers
   maintaining an existing codebase with lots of pure function may become
   confused or frustrated when they realize they cannot do easy things such as
   logging within the method.
      - A counterargument to this may be that when Swift was introduced,
      optionals also made the language difficult to use. People implicitly
      unwrapped them just so things will compile, or returned them from methods
      without much consideration to what that implies. Nevertheless, this made
      Swift a safer language to use by explicitly when nil is a possible value.
      Developers are more conscious about nil being a potential value.
Similarly,
      I think developers should be more aware about side-effect causing
      functions. Being clear about this and separating these concerns should
      bring about more safer and testable Swift applications.
   - Implementation of this feature could be difficult. Swift can implement
   it in several different ways depending on the desired result of this
   feature, such as having stronger or weaker purity guarantees to make the
   feature easier to use or simpler to implement. An effect system may have to
   be created.
      - Alternatively, this could be done in a lightweight manner where the
      feature is introduced and known "pure-like" functions are marked
      in swift-corelibs-foundation.

To be honest, I don't have much experience in languages that have this
feature. I would imagine many people are interested in the notion of pure
functions, but the question here is if it would be worth it, feasible, or
even aligned with Swift's goals to have this feature. I'm half-expecting
that this has already been brought up and determined to be out of scope or
not a good idea.

Thanks for your consideration. Please let me know what you think.
-- 
Jimmy Sambuo
www.sambuo.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151219/c3ef5a98/attachment.html>


More information about the swift-evolution mailing list