> On 4 May 2016, at 00:46, Aleksandar Petrovic via swift-evolution 
> <[email protected]> wrote:
> 
> Hi swift-evolution,
> 
> I want to apologize in advance for my clumsy English. It's (obviously) not my 
> first language.
> 
> Recent discussion about property behaviours reminded me of function 
> decorators in Python. I think decorators can nicely fit in Swift, too.
> 
> First, a bit of explanation for the uninitiated. Decorator is a function that 
> transform other function - it receives some function and returns a function 
> of the same signature. Lets make some dead simple decorator:
> 
> typealias Decorated = (Double, Double) -> Double
> 
> func hiDecorator(fn: Decorated) -> Decorated {
>     return { x, y in
>         print("Hi from decorator!")
>         return fn(x, y)
>     }
> } 
> 
> func multiply(a: Double, _ b: Double) -> Double {
>    return a * b
> }
> 
> let decoratedMultiply = hiDecorator(multiply)
> print("Result: \(decoratedMultiply(2, 3))") 
> 
> 
> The above code should print:
> Hi from decorator!
> Result: 6
> 
> We can use decorators with the current Swift, but they're a bit cumbersome - 
> either we need to store decorated function and remember to use it instead of 
> the original one, or remember to do the decoration on every call.
> 
> Instead, we can write something like this:
> 
> [hiDecorator]
> func multiply(a: Double, _ b: Double) -> Double {
>     return a * b
> }
> 
> ... and that code should be transformed into following during compilation:
> 
> func multiply(a: Double, _ b: Double) -> Double {
>      let fn: (Double, Double) -> Double { _a, _b in
>          return _a * _b
>      }
>      
>      let decorated = hiDecorator(fn)     
>      return decorated(a, b)
> }
> 
> Outside, the function looks like before, so the change is compatible with 
> virtual or interface extension functions.
> 
> Sometimes we'll need to pass some additional data to the decorator. That's 
> fine, as long as the last argument is the target function:
> 
> func logUsage<I, O>(fnName: String, fn: (I) -> O) -> ((I) -> O) {
>     return { _i in
>         print("Function \(fnName) enter")
>         defer { print("Function \(fnName) exit") }
>         return fn(_i)
>     }
> }
> 
> Let's use it:
> 
> [logUsage("increment")]
> func increment(a: Int) -> Int { return a + 1 }
> 
> [logUsage("justPrint")]
> func justPrint(s: String) { print(s) }
> 
> In the above code, the compiler should generate internal decorator call by 
> combining provided parameter and decorated function.
> 
> 
> Why decorators?
> 
> It's important to say that proposed decorators change are pure syntactic 
> sugar. Everything we can do with this change can be accomplished with the 
> current Swift language. But, it gives to programmer a tool to express 
> intentions more clearly and move repeating code away. 
> 
> Sometimes decorators are just a convenient way to quickly add code. In the 
> example above, logging is added with just one line of code and can be easily 
> removed - the function body is not changed. 
> 
> Sometimes decorators can be used as a poor man dependency injection 
> mechanism, so we can write functions like this:
> 
> // if conn is nil, dbInit decorator will provide (global) one, and properly 
> close it after doSomeDbWork exits
> [dbInit]
> func doSomeDbWork(conn: DbConnection? = nil) { ... } 
> 
> 
> We can use decorators in the standard library to, in a way, extend language:
> 
> [asyncMain]
> func doSomething() { ... }  // this function will be posted to main queue
> 
> [synchronized]
> func foo() { ... } // synchronized decorator uses either objc_sync_enter/exit 
> or post on some queue to ensure mutual exclusion
> 
> Or to do some more exotic operations:
> 
> [repeatUntilDone(maxAttempt: 5)]
> func connectToServer(url: String) -> Bool { ... }
> 
> Abstract functions are frowned upon in Swift community, but if we can't live 
> without it, we can signal our intent more clearly with decorator:
> 
> class T {
>      [abstract] func bar() {} // abstract decorator will assert on call
> }
> 
> Etc, etc. Sounds interesting?
> 
> Alex                                    
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution


Given that we might be doing "property behaviours” 
(https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md
 
<https://github.com/apple/swift-evolution/blob/master/proposals/0030-property-behavior-decls.md>),
 which are basically property decorators, it probably makes sense to look at 
how that could work for function decorators.

After all, you could create a property behaviour around a closure and use that 
as a kind of function decorator. It would just be messy.

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

Reply via email to