Hi, I wanted to discussed an idea that I’ve been thinking for the last couple 
of weeks. First I want to give you a little bit of context. I am the technical 
leader  in the iOS project I am working on. We have been using Swift for almost 
one year and half. Most of the first part of the project was desinged by me. I 
am being trying to apply concepts from the functional paradigm and in 
particular we heavily depend on ReactiveCocoa. For the last year two less 
experienced developers joined the team. I was in charge of teaching them about 
iOS programming (this was the first time doing an iOS app for them), functional 
programming (they are still college student with a background in OOP) and the 
details of our code base.

Coming from a background in OOP and imperative programming makes the change to 
a more functional approach quite “interesting”. I really like Swift and its 
flexibility to be able to tackle both low level and high level problems. But 
some times this flexibility makes it more error prone when you try to apply 
functional programming concepts. For example I found my self reviewing and 
correcting pull request with things like “When you use functions like map or 
filter on a collection or a SignalProducer don’t inject side effects”.

This led me to the idea of introducing a @pure annotation for functions. Full 
disclosure: I have almost no background in compilers and the internals of the 
Swift language so I have no idea if this makes sense at all. Such a annotation 
(it could also be a keyword like override o mutating) will make the compiler 
check if the function is actually a pure function, where by Pure I mean

        - It doesn’t mutate any internal or global state 
        - It doesn’t call any non-pure function
        - It must have a return type != from Void
        - It can access non mutable state

In this context a pure function is “stronger” than the mutating keyword in the 
sense that the pure function won’t allow any type of mutation even if you are 
calling a non-pure method (which performs a mutation or a side effect) on an 
object (reference type) instead of a struct. For example

final class Foo {
    
    
    private var count = 0
    
    func foo(x: Int) -> Int {
        count += x
        return count
    }
    
}

struct Bar {
    
    var count: Int
    var foo: Foo
    
    // This method performs a mutation
    // even though is not marked as mutating
    // You could call it a "transitive mutation".
    func bar(x: Int) -> Int {
        return foo.foo(x)
    }
    
    mutating func baz(x: Int) -> Int {
        count += x
        return count
    }
    
    
}


This could be extended to classes and structs. Adding “pure” to a class or 
structs makes all of its methods pure.

The benefit of such feature is that you could gradually add more functional 
code that is checked by the compiler and it is optional. I am most probably 
missing a lot issues here. This is just a rough idea but I wanted to share it 
with the community to better understand the tradeoffs.

If this has already been discussed can anyone point me to that discussion?

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

Reply via email to