Ответ 1
Существует обходное решение:
func unimplemented<T>() -> T
{
fatalError()
}
func recursive<T, U>(f: (@escaping (((T) -> U), T) -> U)) -> ((T) -> U)
{
var g: ((T) -> U) = { _ in unimplemented() }
g = { f(g, $0) }
return g
}
recursive
- это функция, которая принимает замыкание (((T) -> U), T) -> U
, где ((T) -> U)
является ссылкой на разделенную версию замыкания и возвращает полезную функцию g
.
g
изначально назначается фальшивая функция (которая падает при вызове). Это делается для включения рекурсии для нового значения g
, где g
передается на f
вместе с входным значением T
. Важно отметить, что g
в g = { f(g, $0) }
относится к самому себе, а не к фальшивой функции, назначенной ему ранее. Поэтому всякий раз, когда в f
указывается параметр ((T) -> U)
, это ссылка на g
, которая, в свою очередь, ссылается сама.
Эта функция допускает встроенную рекурсию, такую как:
recursive { f, x in x != 10 ? f(x + 1) : "success" }(0)
Эта функция повторяется в общей сложности 11 раз, без необходимости объявлять одну переменную.
Обновление: Теперь это работает с Swift 3 preview 6!
Лично говоря, на данный момент я считаю это довольно элегантным решением, потому что я чувствую, что он упрощает мой код до минимума. A Y combinator, например, ниже
func recursive<T, U>(_ f: (@escaping (@escaping (T) -> U) -> ((T) -> U))) -> ((T) -> U)
{
return { x in return f(recursive(f))(x) }
}
хотел бы, чтобы я возвращал функцию, закрывающую закрытие в пределах закрывающейся крышки!
recursive { f in { x in x != 10 ? f(x + 1) : "success" } }(0)
Приведенный выше код недействителен, если не для внутреннего атрибута @escaping
. Он также требует другого набора фигурных скобок, что делает его более подробным, чем то, что мне нравится при написании встроенного кода.