> 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