Какие функции Perl делают его функциональным языком программирования?

Вдохновленный немного: https://stackoverflow.com/info/30977789/why-is-c-not-a-functional-programming-language

Я нашел: Более высокий порядок Perl

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

Однако я нашел список что делает функциональный язык программирования:

  • Функции первого класса
  • Функции более высокого порядка
  • Лексические замыкания
  • Соответствие шаблону
  • Одиночное задание
  • Lazy Evaluation
  • Коллекция мусора
  • Тип вывода
  • Оптимизация вызовов по времени
  • Описание списка
  • Монадические эффекты

Теперь некоторые из них я хорошо знаю:

Сбор мусора, например, является подсчетом ссылок на Perl и освобождением памяти, когда это больше не требуется.

Лексические замыкания являются частью FAQ: Что такое закрытие? - там, вероятно, есть лучшая статья: http://www.perl.com/pub/2002/05/29/closure.html

Но я немного запутался в некоторых из них - List Comprehensions, например, я думаю, что ссылаясь на map/grep (List::Util и reduce?)

Я могу помочь мне заполнить пробелы здесь? Что из перечисленного может сделать Perl легко (и есть ли простой пример), и есть ли примеры, где он падает?

Ответы

Ответ 1

Полезные вещи, которые имеют значение:

Perl monks rant о функциональном программировании

Более высокий порядок Perl

определения функционального программирования C2.com

Функции первого класса

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

Итак, в Perl:

my $print_something = sub { print "Something\n" };

sub do_something {
    my ($function) = @_;
    $function->();
}

do_something($print_something);

Вердикт: поддерживается с внутренней стороны

Функции более высокого порядка

В математике и информатике функция более высокого порядка (также функциональная форма, функционал или функтор) - это функция, которая выполняет хотя бы одно из следующих действий:

  • принимает одну или несколько функций в качестве входа

  • выводит функцию

Что касается этот пост на perlmonks:

В терминологии Perl мы часто называем их обратными вызовами, фабриками и функциями, возвращающими код ref (обычно закрытие).

Вердикт: поддерживается с внутренней стороны

Лексические замыкания

Внутри FAQ по perl у нас есть вопросы относительно What is a closure?:

Закрытие - это термин компьютерной науки с точным, но трудно объясняемым значением. Обычно закрытие реализовано в Perl как анонимные подпрограммы с прочными ссылками на лексические переменные за пределами их собственных областей. Эти лексики магически относятся к переменным, которые были вокруг, когда была определена подпрограмма (глубокая привязка).

Закрытия чаще всего используются в языках программирования, где вы можете иметь возвращаемое значение функции как функции, как вы можете в Perl.

Это объясняется, возможно, немного более ясно в статье: Достижение закрытия

sub make_hello_printer {
    my $message = "Hello, world!";
    return sub { print $message; }
}

my $print_hello = make_hello_printer();
$print_hello->()

Вердикт: поддерживается с внутренней стороны

Соответствие шаблону

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

Таблицы диспетчеризации являются ближайшим приближением - по существу хеш либо анонимных подстановок, либо код ref.

use strict;
use warnings;

sub do_it {
    print join( ":", @_ );
}
my $dispatch = {
    'onething'      => sub { print @_; },
    'another_thing' => \&do_it,
};

$dispatch->{'onething'}->("fish");

Поскольку он just хеш, вы можете добавить ссылки на код и анонимные подпрограммы. (Примечание - не совсем отличается от объектно-ориентированного программирования)

Вердикт: Обход проблемы

Одиночное задание

Любое присваивание, которое изменяет существующее значение (например, x: = x + 1), запрещено в чисто функциональных языках. 4 В функциональном программировании, присваивание не рекомендуется в одиночном назначении, также называемое инициализацией. Одно назначение - пример привязки имени и отличается от присваивания, как описано в этой статье, в том, что его можно выполнить только один раз, обычно при создании переменной; не допускается последующее переназначение.

Я не уверен, что perl действительно это делает. Ближайшим приближением могут быть ссылки/анонимные субмарины или, возможно, constant.

Вердикт: не поддерживается

Lazy Evaluation

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

Примеры ленивых методов оценки в Perl 5?

И снова вернемся к Более высокий порядок Perl (я не связан с этой книгой, честный - это просто похоже ключевых текстов по этому вопросу).

Основная идея здесь - создать "связанный список" в perl (используя объектно-ориентированные методы), но вставить ссылку на код на ваш "конечный маркер", который оценивает, если вы когда-либо доберетесь до этого.

Вердикт: Обход проблемы

Сбор мусора

"GarbageCollection (GC), также известный как автоматическое управление памятью, - это автоматическая утилизация памяти кучи".

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

В частности - круговые ссылки, которые описаны в perldoc perlref

Вердикт: коренная поддержка

Запрос типа

TypeInference - это анализ программы для вывода типов некоторых или всех выражений, обычно в CompileTime

Perl делает неявным использование значений взад и вперед, как это необходимо. Обычно это работает достаточно хорошо, что вам не нужно возиться с ним. Иногда вам нужно "принудительно" выполнить процесс, сделав явную операцию с числами или строкой. Канонически это либо добавление 0, либо объединение пустой строки.

Вы можете перегрузить скаляр, чтобы делать разные вещи, используя dualvars

Вердикт: коренная поддержка

Оптимизация звонков

Оптимизация хвостового вызова (или слияние хвостового вызова или устранение хвостового вызова) - это обобщение TailRecursion: если последнее, что делает процедура перед тем, как оно возвращается, вызывает другую процедуру, вместо того, чтобы выполнять команду "прыгать и добавлять", stack-frame, за которым сразу следует pop-stack-frame-and-return-to-caller, должно быть безопасно просто перейти к началу второй процедуры, позволяя повторно использовать первый стек стека подпрограмм (среда).

Почему Perl так боится "глубокой рекурсии" ?

Он будет работать, но он будет предупреждать, если ваша глубина рекурсии > 100. Вы можете отключить это, добавив:

no warnings 'recursion';

Но, очевидно, вам нужно быть осторожным относительно глубины рекурсии и объема памяти.

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

Tailcalls поддерживается perl. Либо увидеть goto & sub; обозначение или увидеть синтаксис оперта для него, предоставленный Sub::Call::Tail

Вердикт: Родной

Список понятий

Список понятий - это особенность многих современных функциональных программных языков. В соответствии с определенными правилами они предоставляют краткую нотацию для GeneratingElements? в списке. Понимание списка - SyntacticSugar для комбинации приложений функций concat, map и filter

Perl имеет map, grep, reduce.

Он также справляется с расширением диапазонов и повторений:

my @letters = ( "a" .. "z" ); 

Итак, вы можете:

my %letters = map { $_ => 1 } ( "A" .. "z" ); 

Вердикт: родной (List::Utils является основным модулем)

Монадические эффекты

... нет, все еще есть проблемы с ними. Это либо намного проще, либо намного сложнее, чем я могу заглянуть.

Если у кого-нибудь есть что-то еще, попробуйте чип или отредактируйте этот пост или... что-то. Я по-прежнему отрывочен в отношении некоторых концепций, поэтому этот пост является скорее отправной точкой.

Ответ 2

Действительно хорошая тема, я хотел написать статью под названием "ссылка на верблюда". Позвольте мне внести свой вклад с некоторым кодом.

Perl также поддерживает такие анонимные функции, как

 sub check_config {
    my ( $class, $obj ) = @_;

    my $separator = ' > ';

    # Build message from class namespace.
    my $message = join $separator, ( split '::', $class );

    # Use provided object $obj or
    # create an instance of class with defaults, provided by configuration.
    my $object = $obj || $class->new;

    # Return a Function.
    return sub {
        my $attribute = shift;

        # Compare attribute with configuration,
        # just to ensure it is read from there.
        is $object->config->{$attribute},

            # Call attribute accessor so it is read from config,
            # and validated by type checking.
            $object->$attribute,

            # Build message with attribute.
            join $separator, ( $message, $attribute );
        }
}

sub check_config_attributes {
    my ( $class, $obj ) = @_;

    return sub {
        my $attributes = shift;
        check_config( $class, $obj )->($_) for (@$attributes);
        }
}