Чисто функциональное программирование на D - PullRequest
22 голосов
/ 28 апреля 2011

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

Несколько вещей, которые я заметил:

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

Кажется, что определенные пользователем структуры имеют проблемы (как показано ниже) с:
1. чистыми деструкторами во вложенной структуре
2. чистой постблит-функцией даже наnon-nested struct

Следующий код в настоящее время выдает несколько ошибок в DMD 2.052 win 32-bit

struct InnerStruct
{
    pure this(this) {}
    pure ~this() {}
}

struct OuterStruct
{
    InnerStruct innerStruct;
    pure this(this) {}
    pure ~this() {}
}

pure void somePureFunc()
{
    OuterStruct s1 = OuterStruct(); // pure nested destructor does not compile
    OuterStruct s2 = s1;
    InnerStruct is1 = InnerStruct(); // pure non-nested destructor seems to compile
    InnerStruct is2 = is1; // pure non-nested postblit does not compile
}

void main()
{
    somePureFunc();
}
pure_postblit.d(18): Error: pure function 'somePureFunc' cannot call impure function '__cpctor'  
pure_postblit.d(20): Error: pure function 'somePureFunc' cannot call impure function '__cpctor'  
pure_postblit.d(18): Error: pure function 'somePureFunc' cannot call impure function '~this'  
pure_postblit.d(17): Error: pure function 'somePureFunc' cannot call impure function '~this'  

1 Ответ

21 голосов
/ 28 апреля 2011

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

  • Все функции, отмеченные pure, слабо чисты. Они могут не иметь доступа к каким-либо глобальным изменяемым состояниям (глобальным переменным, локальным переменным потока, static переменным и т. Д.) Или выполнять ввод / вывод. Однако они могут изменить свои аргументы. Смысл этих функций в том, что они могут вызываться из строго чистых функций (подробно описано ниже) без нарушения гарантий строгой чистоты.

  • Все функции, которые являются слабо чистыми и не имеют аргументов с изменяемой косвенностью, являются строго чистыми. Конструкторы типа const и immutable могут использоваться для гарантии этого. (При работе со структурами и классами указатель this считается параметром.) Сильно чистые функции имеют все приятные свойства, о которых говорят функциональные программисты, даже если они реализованы с использованием изменяемого состояния. Сильно чистая функция всегда возвращает одно и то же значение для любых заданных аргументов и не имеет видимых побочных эффектов. Сильно чистые функции являются ссылочно прозрачными, то есть их возвращаемое значение может быть заменено вызовом с данным набором параметров, не влияя на наблюдаемое поведение. Любая сильно чистая функция может быть безопасно выполнена параллельно с любой другой сильно чистой функцией.

К сожалению, взаимодействие между универсальным кодом и pure (а также const и immutable) довольно слабое. Было несколько предложений, чтобы исправить это, но ни одно еще не было принято.
\ std.algorithm написан настолько универсально, насколько это возможно, поэтому он не может требовать, чтобы его лямбда-функции и диапазоны, которые он принимает, были чистыми. Кроме того, функции системы типов, которые были добавлены в D2, как правило, являются наиболее ошибочными функциями в языке, потому что перед решением соответствующих проблем были расставлены приоритеты для более простых вещей. В настоящее время pure в принципе не может использоваться, за исключением тривиальных случаев, таких как std.math.

...