LINUX.ORG.RU

Можно ли создать рекурсивную анонимную функцию?

 , ,


0

4

Речь не о том, о чём вы подумали.

Нужно вызывать безымянную/анонимную функцию внутри себя самой, при этом не сохраняя её ни в каких переменных.

Это же Perl, Luke, должна быть такая фича.

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

Анонимы на ЛОРе должны знать ;)

★★★★★

Ответ на: комментарий от Debasher

LISP при том, что когда я рекурсивно программлю на Perl - почему-то вспоминаю о функциональных языках и в частности - о LISP :)

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

LISP при том, что когда я рекурсивно программлю на Perl - почему-то вспоминаю о функциональных языках и в частности - о LISP :)

Как я понял, тебе нужно не ФП-решение (Y комбинатор), а какой-то перлячий хак. Соответственно - Lisp тут явно лишний.

Sectoid ★★★★★
()
Ответ на: комментарий от theNamelessOne
((lambda (fun &rest args)
   (apply fun fun args))
 (lambda (self n acc)
   (if (zerop n)
       acc
     (funcall self self (1- n) (* n acc))))
 5 1) ; => 120
theNamelessOne ★★★★★
()

Удваиваю вариант с __SUB__. Но он относительно новый, поэтому далеко не всюду взлетит.

joy4eg ★★★★★
()

Всегда можно накостылить - положить лямбду в переменную и передать её другой лямбде, как это сделал чуть выше theNamelessOne. В Common Lisp это можно спрятать за макрос и сделать красиво.

Gentooshnik ★★★★★
()
print sub { my $f = shift;
      return $f->($f, @_);}->
    (sub {
        my ($self, $n, $acc) = @_;
        if ($n == 0)
        { return $acc; }
        { return $self->($self, $n-1, $n*$acc);}}, 5, 1);

120
monk ★★★★★
()

никакого смысла давать им имена нет

Это зря. Избегаю полностью анонимных функций - удобно когда стектрейсы помогают дебагу:

my $maybe_set_subname = sub { $ARG[1]; };

# Supported on Perl 5.22+
eval {
    require Sub::Util;

    if (my $set_subname = Sub::Util->can('set_subname')) {
        $maybe_set_subname = $set_subname;
    }
};

my $lambda= sub {};
$maybe_set_subname->('name_of_lambda', $lambda);
outtaspace ★★★
()
Ответ на: комментарий от Virtuos86

Пояснение: первая анонимная функция только запускает рекурсию, дальше работает анонимная функция-аргумент. В реальном коде первая функция-«пускалка» будет иметь тот же вид, а рабочая усложняться.

Virtuos86 ★★★★★
()

Функциональные фичи perl'а во многом представляют собой синтактический сахар, поэтому только костыльные варианты есть, в то же время в lisp'e или ocaml'e рекурсивная анонимная функция создается стандартными средствами.

anonymous
()
Ответ на: комментарий от anonymous

поэтому только костыльные варианты есть, в то же время в lisp'e или ocaml'e рекурсивная анонимная функция создается стандартными средствами.

Чем вариант на лиспе менее костылен, чем аналогичный на perl?

monk ★★★★★
()
Ответ на: комментарий от anonymous

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

В свою очередь его пример калька с лиспового варианта theNamelessOne.

Virtuos86 ★★★★★
()
Последнее исправление: Virtuos86 (всего исправлений: 2)
fix (\blah -> if blabla then blah else quu    )
       ^--- анонимная рекурсивная функция -^^

не лисп и не перл правда

qnikst ★★★★★
()
Ответ на: комментарий от Virtuos86

Почти всегда так оно и получается) Хотя практичнее там будет писать в «явном» стиле, где есть более-менее стандартные ключевые слова

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.