Передача функциональных объектов и их использование в других функциях в Python 3.8.4 - PullRequest
1 голос
/ 14 июля 2020

Я смотрел на этот вопрос:

cons(a, b) создает пару, а car(pair) и cdr(pair) возвращает первый и последний элемент этой пары. Например, car(cons(3, 4)) возвращает 3, а cdr(cons(3, 4)) возвращает 4.

Учитывая эту реализацию минусов:

def cons(a, b):
    def pair(f):
        return f(a,b)
    return pair

Реализовать автомобиль и cdr.

Я узнал лямбда-выражение, но я все еще не знаю, как оно работает. Ответ дается как:

def car(f):
    z = lambda x, y: x
    return f(z)

def cdr(f):
    z = lambda x, y: y
    return f(z)

Если f является функциональным объектом, не передает z в f, вызывая lambda f : f(a,b), где z имеет 2 аргумента, а другая лямбда имеет только 1 аргумент?

Как работает это решение?

Ответы [ 2 ]

1 голос
/ 14 июля 2020

Вы должны понимать, как пара представлена ​​. Пара состоит из трех вещей: первого элемента, второго элемента и функции. Наиболее важно, что два элемента не доступны «напрямую» (хотя см. Ниже): вы можете только получить к ним доступ через третий член пары. Эта функция принимает другую функцию и возвращает результат применения этой функции к двум «скрытым» элементам.

car принимает парную функцию и применяет ее к функции, которая возвращает первый из двух аргументов.

cdr принимает парную функцию и применяет ее к функции, которая возвращает второй из двух своих аргументов.

Вы можете отследить это следующим образом, это будет проще, если переписываешь cons = lambda a, b: lambda f: f(a, b):

car(cons(3, 5)) == cons(3, 5)(lambda x, y: x)
                == (lambda a, b: lambda f: f(a, b))(3, 5)(lambda x, y: x)
                == (lambda f: f(3, 5))(lambda x, y: x)
                == (lambda x, y: x)(3, 5)
                == 3


cdr(cons(3, 5)) == cons(3, 5)(lambda x, y: y)
                == (lambda a, b: lambda f: f(a, b))(3, 5)(lambda x, y: y)
                == (lambda f: f(3, 5))(lambda x, y: y)
                == (lambda x, y: y)(3, 5)
                == 5

cons(3, 5) по существу сохраняет значения 3 и 5 в атрибуте __closure__ создаваемой им функции pair.

>>> p1 = cons(3, 5)
>>> p1.__closure__[0].cell_contents
3
>>> p1.__closure__[1].cell_contents
5
0 голосов
/ 14 июля 2020

Давайте оценим car(cons(3, 4)).

cons(3, 4)

a = 3
b = 4
def pair(f):
    return f(3, 4)
return pair

Итак, сейчас у нас есть car(pair), где pair это:

def pair(f):
    return f(3, 4)

car(pair)

Давайте посмотрим, что происходит в car:

f = pair
z = lambda x, y: x
return f(z)

Таким образом, последний оператор может быть фактически прочитан как:

return pair(z)

или

return pair(lambda x, y: y)

Давайте для простоты перепишем z как обычную функцию:

def z(x, y):
    return x

return pair(z)

Теперь мы запускаем pair с z в качестве параметра .

Помните, pair определяется как:

def f(n):
    return n(3, 4)

Итак, n = z, и мы должны вернуть:

z(3, 4)

Что делает z, так это собственно "вернуть первый параметр".

И ... Вот он:)

...