Как называется эта взаимная «рекурсия»? - PullRequest
5 голосов
/ 19 апреля 2010

Моя проблема связана с определенным стилем кода, который очень напоминает рекурсию, но не совсем .Рекурсия - это, по выражению Wikipedia , «метод определения функций, в котором определяемая функция применяется в своем собственном определении».Аналогичным образом взаимная рекурсия применяет другую функцию, которая прямо или косвенно применяет определяемую нами функцию.

Проблема в том, что код, над которым я размышляю и работаю, не использует ту же функцию!Он использует тот же код в другой функции (как метод или замыкание).

Проблема в том, что, хотя мой код одинаков, функции не совпадают.Взгляните на следующий базовый пример взаимной рекурсии:

def is_even(x):
    if x == 0:
        return True
    else:
        return is_odd(x - 1)

def is_odd(x):
    if x == 0:
        return False
    else:
        return is_even(x - 1)

Это несколько интуитивно понятно и очень четко взаимно рекурсивно.Однако, если я закрою каждую функцию как внутреннюю функцию, которая создается один раз при каждом вызове, она становится менее ясной:

def make_is_even(): 
    def is_even(x):
        if x == 0:
            return True
        else:
           return make_is_odd()(x - 1)
    return is_even

def make_is_odd(): 
    def is_odd(x):
        if x == 0:
            return False
        else:
            return make_is_even()(x - 1)
    return is_odd

def is_even2(x):
    return make_is_even()(x)

def is_odd2(x):
    return make_is_odd()(x)

Без учета оптимизаций, таких как неявное запоминание и т. Д., Это создает цепочку вызовов функций, которая нене является строго рекурсивным, создавая и вызывая различные новые функции, никогда не вызывая одну и ту же функцию дважды.Тем не менее, все эти функции следуют общему шаблону и являются одной и той же функцией, создаваемой снова и снова (возможно, с различными свободными переменными.

И снова, мы можем придумать прямой эквивалент (в конце концов, классына самом деле это просто замыкания, верно;) реализация с использованием классов. Это особенно важно, поскольку этот стиль [вставьте здесь имя] используется, например, в Composite Pattern . Разница в том,что с помощью шаблона проектирования Composite и большинства применений (даже замыканий) экземпляры обычно создаются не на лету, а по сути все так же.

class EvenChecker(object):
    def check(self, x):
        if x == 0:
            return True
        else:
            return OddChecker().check(x - 1)

class OddChecker(object):
    def check(self, x):
        if x == 0:
            return False
        else:
            return EvenChecker().check(x - 1)

def is_even3(x):
    return EvenChecker().check(x)

def is_odd3(x):
    return OddChecker().check(x)

На этот раз цепочка объектоввызовы создания и метода, но принцип тот же. (Я бы на самом деле заметил, что он немного другой, в том смысле, что Python определяет простую обертку для каждого объекта, которая сама каждый раз вызывает одну и ту же функцию - ноэто не обязательно то, что мы должны знать, и это не должно быть правдой для другихее реализации классов и объектов.Но, строго говоря, это является взаимно рекурсивным, а также ... чем-то большим, и это еще одна вещь, которую я хочу знать.)

Ответы [ 3 ]

2 голосов
/ 19 апреля 2010

Как вы указали, это все еще взаимная рекурсия. Я не думаю, что у «чего-то большего», о котором вы спрашиваете, есть имя; если это произойдет, я никогда не слышал.

2 голосов
/ 19 апреля 2010

Взаимная рекурсия - это особый случай косвенной рекурсии .

1 голос
/ 19 апреля 2010

Видимо, это называется Взаимная рекурсия :)

В статье даже приведен тот же пример, что и у вас, с функциями odd? и even?.

...