0

In Kotlin, we could create a scope function as below.

    inline fun <R> run(block: () -> R): R {
        return block()
    }

We could use it as below to choice which view to show.

    run {
        if (choice) viewOne else viewTwo
    }?.show()

In Swift, we could also declare as below

    @inline(__always) func run<R>(block: () -> R) -> R {
        return block()
    }

However, when we use it, it has to be really verbose as below.

    run { () -> View? in     // Need to explicitly show `View is return
        if choice {
            return viewOne   // Need to explicitly return
        } else {
            return viewTwo   // Need to explicitly return
        }
    }?.show()

Is there anywhere we could reduce the verbosity of Swift that I'm not aware, that it looks more concise? (matching closer to Kotlin)

UPDATE

Show entire code

@inline(__always) func run<R>(block: () -> R) -> R {
    return block()
}

class View {
    func show() {print("A")}
}

let viewOne: View = View()
let viewTwo: View = View()

var choice = true

run { () -> View in
    return choice ? viewOne : viewTwo
}.show()
Elye
  • 53,639
  • 54
  • 212
  • 474
  • 1
    Where did you declare that func, in what scope? I cannot compile your code in a playground. Btw the body of your closure can definitely be simplified to `return choice ? viewOne : viewTwo`. – Dávid Pásztor Mar 16 '20 at 11:20
  • Nice one on ternary. I forgot about that, after using Kotlin for awhile as it's not available on Kotlin. As for the `run` it is not scope. It is declare as global function. – Elye Mar 16 '20 at 11:28
  • It can't be a global func, that produces several compiler errors, including _"Global function cannot return 'Self'"._ Also in your question, the function declaration shows `let`, not `run` - not that the function name would make a difference regarding the type issues. – Dávid Pásztor Mar 16 '20 at 11:36
  • 1
    Hi @DávidPásztor, I have updated with the entire code that compiles on playground – Elye Mar 16 '20 at 11:41
  • Ops, I show the wrong one. Let me update with `run` instead. Sorry! – Elye Mar 16 '20 at 11:43
  • 2
    “Need to explicitly ... ” – No, `run { choice ? viewOne : viewTwo }.show()` compiles without problems. – Martin R Mar 16 '20 at 11:44
  • Nice!! Looks like it can only be done with ternary. If the normal if-else, it can't. Is that correct? – Elye Mar 16 '20 at 11:46
  • In another word, if it is more than one line, then we have to have `() -> View in` there, correct? – Elye Mar 16 '20 at 11:48
  • 2
    @Elye: The return type can be inferred from a single-expression closure, or from the context. Compare [Why can't the Swift compiler infer this closure's type?](https://stackoverflow.com/q/42534207/1187415). – Martin R Mar 16 '20 at 11:50
  • Isn’t the run function redundant in either language? Just wrap the ternary in parentheses. In Kotlin, if/else is a ternary expression. – Tenfour04 Mar 16 '20 at 12:36
  • This `{ choice ? viewOne : viewTwo }.show()` doesn't work. This works `run { choice ? viewOne : viewTwo }.show()` – Elye Mar 17 '20 at 05:32

1 Answers1

1

The issues is that the compiler cannot infer the return type of multi-line closures. However, you can easily reduce your closure to a single line using the ternary operator instead of an if-else. This way you can get rid of both the return statements and the type annotation.

run { choice ? viewOne : viewTwo }.show()
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116