2016-08-24 4 views
2

Предположим, у меня есть следующие нечистые функции:Составление нечистые функции

// Mounts a foo instance into the given dom node 
// (this is an implementation detail of the Foo library), 
// then returns the foo instance. 
const createFoo = (FooConstructor, domNode, options) => { 
    return new FooConstructor(domNode, options); 
}; 

const outlineFoo = foo => { 
    foo.getCanvas().outline = true; 
    return foo; 
} 

Если бы я хотел использовать R.compose создать экземпляр Foo и выделить его, я мог бы написать функцию, которая делает:

const createFooWithHighlights = (FooConstructor, domNode, options) => { 
    return R.compose(
    outlineFoo, 
    createFoo 
)(FooConstructor, domNode, options) 
} 

Если бы я хотел использовать императивное программирование для достижения того же, я бы сделал:

const createFooWithHighlights = (FooConstructor, domNode, options) => { 
    const foo = createFoo(FooConstructor, domNode, options); 
    outlineFoo(foo); 
    return foo; 
} 

Какой бы ни один мы выбрали, она будет вызвана тем же:

const highlightedFooInDOM = createFooWithHighlights(Foo, document.body, {}) 

Поскольку все эти функции вызывают побочные эффекты, следует избегать использования R.compose? Существуют ли правила, регулирующие чистоту и функциональный состав?

+2

Вы должны прочитать о IO monad – naomik

ответ

2

Во-первых, одно упрощение. Вы должны быть в состоянии написать createFooWithHighlights более просто:

const createFooWithHighlights = R.compose(outlineFoo, createFoo); 

Теперь к реальному вопросу:

Поскольку все эти функции вызывают побочные эффекты, следует избегать использования R.compose? Существуют ли правила, регулирующие чистоту и функциональный состав?

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

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

Рамда (отказ от ответственности: я один из авторов) строго избегает побочных эффектов. Но так оно и должно быть. Это функциональная библиотека утилиты; вы не принимаете решения о том, как ваша программа взаимодействует с остальным миром. Или, по крайней мере, у нас в команде Рамды нет. Поэтому функции Рамды чисты. Кроме того, Ramda спроектирован таким образом, чтобы вам было удобно работать в чисто функциональном режиме, где это возможно.

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

Итак, что вы хотите сделать, это прекрасно соответствует нормальному использованию Ramda.

+0

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

+0

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