Можно ли это считать чистой функцией (функциональное программирование)?

Я читал о функциональном программировании и его концепциях. Мне ясно, что при работе над большими проектами вам всегда нужно смешивать (на некотором адекватном уровне) несколько парадигм, таких как объектно-ориентированная и функциональная. Теоретически такие понятия, как чистота функций, слишком строги, например

Функция всегда оценивает одно и то же значение результата при одном и том же значении аргумента. Значение результата функции не может зависеть от какой-либо скрытой информации или состояния, которое может измениться во время выполнения программы или между различными выполнениями программы, а также не может зависеть от какого-либо внешнего ввода от устройств ввода-вывода. (https://en.wikipedia.org/wiki/Pure_function)

Тем не менее, является ли этот код (или может считаться) чистой функцией?

const externalVar = 10;

function timesTen(value) {
    return externalVar * value;
}

Я спрашиваю об этом, потому что в этом случае функция timesTen всегда будет возвращать одно и то же значение для ввода, и любой может изменить значение externalVar, поскольку это константа. Однако этот код нарушает правило доступа к области внешней функции.


person thiagoh    schedule 19.07.2017    source источник
comment
Обратите внимание, что чистые функции часто имеют зависимости и от других функций, и пока эти другие функции являются чистыми, зависимые функции также считаются чистыми. Я не понимаю, чем ваш пример отличается от этого. Так что да, timesTen - чистая функция. Однако у вас нет гарантии ссылочной прозрачности в Javascript. Следовательно, вероятно, было бы правильнее сказать, что вы можете быть уверены, что ваша функция чиста.   -  person    schedule 19.07.2017
comment
Полностью согласен с тобой @ftor! А что касается языка, пожалуйста, не обращайте на него внимания. Мой вопрос связан с концепциями, а не с тем, какие концепции я могу достичь с помощью определенного языка.   -  person thiagoh    schedule 19.07.2017
comment
@thiagoh, конечно, функция остается чистой, если все ее зависимости чисты - это суть того, что говорит ftor, и я согласен с ним на 100%.   -  person Mulan    schedule 19.07.2017


Ответы (2)


да. Гарантированно чистый.

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

Однако этот код нарушает правило доступа к области внешней функции.

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

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

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

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

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

function compose(f2, f1) {
  return (...args) => f2(f1(...args));
}

function makeAdder(initialValue) {
  return v => v + initialValue;
}

const add11 = compose(makeAdder(10), makeAdder(1));
add11(5); // ==> 16

Это чисто. Переменная закрытия / свободная переменная f1, f2, initialValue никогда не изменяется для созданных функций. add11 - это чистая функция.

Теперь посмотрим на compose снова. Он выглядит чистым, но может быть испорчен. Если бы обе переданные ему функции не были чистыми, результат тоже не был бы.

OO тоже может быть чисто функциональным!

Их можно легко комбинировать, не видоизменяя создаваемые вами объекты.

class FunctionalNumber {
  constructor(value) {
    this.value = value;
  }
  add(fn) {
    return new FunctionalNumber(this.value + fn.value);
  }
  sub(fn) {
    return new FunctionalNumber(this.value - fn.value);
  }        
}

Этот класс чисто функциональный.

Фактически, вы можете думать о вызове метода, таком как obj.someMethod(arg1, arg2), как о вызове функции с obj в качестве первого аргумента someFunction(obj, arg1, arg2). Это только синтаксические различия, и если someFunction видоизменится obj, вы бы сказали, что это не чисто. То же самое и с someMethod и obj.

Вы можете сделать классы, которые работают с большими структурами данных, функциональными, что означает, что вам никогда не придется копировать их перед изменением при выполнении решения головоломки с возвратом. Простым примером является пара в Haskell и Lisp. Вот один из способов сделать это на JavaScript:

class Cons {
  constructor(car, cdr) {
    this.car = car;
    this.cdr = cdr;
  }
}

const lst = new Cons(1, new Cons(2, new Cons(3, null)));
const lst0 = new Cons(0, lst);

lst0 это lst, но с новым элементом впереди. lst0 повторно использует все в lst. С его помощью можно сделать все, от списков до двоичных деревьев, и вы можете создать множество последовательных структур данных с неизменяемыми двоичными деревьями. Это было примерно с 50-х годов.

person Sylwester    schedule 19.07.2017
comment
Если вы переопределите parseInt на что-то, что не является чистым, или во время выполнения вашей программы, чтобы оно работало по-другому, тогда ни одна вызывающая его функция не будет чистой. именно так я думаю! Я задал этот вопрос здесь после долгого обсуждения с друзьями. Они были ослеплены буквальными словами, гласящими, что чистая функция не может получить доступ ни к чему извне. Принял это как правильный ответ. Спасибо - person thiagoh; 20.07.2017

Я понимаю ваше мнение и полностью согласен с @Sylwester, но есть момент, о котором стоит упомянуть: с помощью отражения можно изменить значения внешних констант, что нарушит чистоту вашей функции. Мы знаем, что все в ИТ может быть взломано, и нам не следует рассматривать это из-за концепций, но на практике мы должны иметь в виду, что в этом случае функциональная чистота является ненадежной.

person Victor Laerte    schedule 21.07.2017