Ещё один Y Combinator (2)

первая часть

Но что будет, если наша функция рекурсивная?

def fact(n):
if n<=1: return 1
else: return n*fact(n-1)

map(fact,range(0,10))

Как нам представить её в виде однострочной лямбда-функции? Прежде всего, нам надо избавиться от прямого вызова самой рекурсивной функции, в её теле, по имени. Для этого мы будем передавать её как аргумент:

def urfact(f,n):
if n<=1:
return 1
else:
return n*f(f,n-1)

Чтобы вызвать её с единственным параметром n, добавим функцию-обёртку:

def fact1(n):
return urfact(urfact,n)

map(fact1,range(0,10))

Отсюда очевидным образом мы переходим к безымянной лямбде:

map(lambda n:urfact(urfact,n), range(0,10))

Финальный вопрос: а как бы теперь и urfact переписать в одну строчку?

Piponi приводит вот такой вариант:

def urfact1(f,n):
return {True:1,False:n*f(f,n-1)}[n<=1]

сразу же отмечая, что он не сработает, так как оцениваться будут обе «ветки» условия (на самом деле, это просто словарь, который индексируется логическим результатом условия проверки).

Я не знаю, почему он не использовал подходящий нативный синтаксис Питона вроде такого (отлично работает):

def urfact1(f,n):
return 1 if n<=1 else n*f(f,n-1)

В результате Пипони пошёл по вот такому кривому пути:

def urfact2(f,n):
return {True:lambda:1,False:lambda:n*f(f,n-1)}[n<=1]()

итд.

Естественный же питоновский код будет таков:

map(lambda n: (lambda f:f(f,n))(lambda f,n: (1 if n<=1 else n*f(f,n-1))), range(0,10))

Поделиться статьей ...Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0Share on VKPrint this page

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *