Милый лямбда-трюк в Схеме: возможно ли в Swift? - PullRequest
0 голосов
/ 26 ноября 2018

Давным-давно, в далекой галактике, во время курса на Схеме нам давался пример лямбда-игр:

(define (foo x)
  (lambda (y) (x (x (x y)))))

Теперь, очевидно, ((foo 1+) 0) напечатает 3. (1+ - это стандартный оператор инкремента Схемы) Но самое интересное, что вы можете применить foo к себе, а затем вы можете делать такие забавные вещи, как:

    (((foo foo) 1+) 0)

, что, конечно, печатает 27. И затемэто действительно смешно:

(define a (foo foo))
(((a foo) 1+) 0)

Я проделал этот трюк в CommonLisp, Clojure, Ruby, Python, Haskell, Erlang и Julia ...

Так что возникает вопрос, можете ли вы сделать этов Свифт ?Я знаю, что вы можете выполнять функции более высокого порядка, но можете ли вы создать такие функции, которые будут такими же «рефлексивными», как и в чисто функциональных языках?

Tx!

1 Ответ

0 голосов
/ 26 ноября 2018

Вы можете сделать это, если вы сделаете foo generic:

func foo<T>(_ x: @escaping (T) -> T) -> (T) -> T {
    return { y in x(x(x(y))) }
}

func inc(x: Int) -> Int {
    return x + 1
}

foo(inc)(0)  // 3
foo(foo)(inc)(0)  // 27

Поскольку foo является универсальным, это падает, когда вы пытаетесь определить a.

This:

let a = foo(foo)

не компилируется.

a само по себе должно быть универсальным, и, как отмечено в комментариях @MartinR, в Swift только функции могут быть универсальными.Так что a нужно будет определить как функцию.

Вот моя попытка:

func a<T>(_ x: @escaping (T) -> T) -> (T) -> T {
    return foo(foo)(x)
}

a(foo)(inc)(0)  // this runs for quite a long time ...  
...