В результате обсуждения комментариев здесь , я задаюсь вопросом, можете ли вы изучить функциональное программирование на C?
В результате обсуждения комментариев здесь , я задаюсь вопросом, можете ли вы изучить функциональное программирование на C?
Ответы:
Очевидно, что вы можете заниматься функциональным программированием на C. Теоретически, вы также можете изучать принципы функционального программирования на C, но язык не облегчает этого.
Я предполагаю, что у вас есть хотя бы немного опыта в ООП; если вы это сделаете, вы должны знать, что ООП может быть сделано в C, включая полиморфизм, методы получения / установки, правила видимости и т. д. и т. д., но это довольно болезненно, и вам нужно знать как ООП, так и C внутри- чтобы снять это. То же самое с FP.
Что вы должны сделать, это сначала выучить функциональный язык программирования (у большинства из них есть удивительно простые правила синтаксиса; это не тот синтаксис, который делает их трудными для изучения), а затем позвольте вашей недавно приобретенной мудрости влиять на то, как вы пишете C.
В соответствии с запросом, некоторые вещи можно узнать из FP, а затем применить, скажем, в C, C ++ или Java:
C может быть взломан, чтобы предложить некоторые функциональные концепции:
Этот вопрос StackOverflow расскажет вам больше. Но хотя кажется возможным заняться функциональным программированием (или большим подмножеством) в C, хаки и расширения компилятора и все, что не является лучшим способом изучения концепции.
Чтобы по-настоящему изучить функциональное программирование, лучше всего выбрать один из известных языков функционального программирования, таких как Лисп и его диалекты ( Clojure , Scheme ), Erlang и Haskell . Любой из них является идеальным инструментом, который работает в рамках мышления функционального программирования. F # также является хорошим кандидатом, если у вас есть .Net опыт работы, но это мульти парадигмальный язык, а не строго функциональный язык программирования.
Как отмечает тдаммерс в комментариях:
На самом деле, LISP, clojure и схема также являются мультипарадигмой; Haskell, будучи чистым и ленивым по умолчанию, также допускает императивное программирование, находясь в монадическом контексте, и имеет обширную поддержку параллельной обработки. Все они имеют механизмы, которые реализуют большую часть мудрости, собранной в мире ООП - инкапсуляцию, наследование, единоличную ответственность, композицию и т. Д. Вопрос не в том, ПОЗВОЛЯЕТ ли язык РАЗРЕШИТЬ другие парадигмы; это о том, какая парадигма формирует отправную точку языка.
Насколько я знаю, Lisp и его диалекты, а также Erlang являются лучшими кандидатами, чем F #, потому что они поощряют функциональное программирование над другими парадигмами, что красиво говорит tdammers как отправная точка языка . F # охватывает функциональное программирование, но не поощряет его по сравнению с другими поддерживаемыми парадигмами, императивным и oo программированием.
Вы не можете изучить все аспекты функционального программирования на языке C. Но, безусловно, вы можете начать программирование функционального стиля с любого императивного языка. Эти стартовые биты - «Как сохранить чистоту во время программирования». И это может быть сделано C также. Проверьте это сообщение в блоге для деталей-
http://www.johndcook.com/blog/2011/07/24/get-started-functional-programming/
Функциональное программирование - это замыкания и их применение. Если кто-то не сможет показать вам библиотеку закрытия спуска для C, забудьте об использовании C для изучения функционального программирования.
Кардинальным понятием функционального программирования является понятие замыканий, которое, грубо говоря, охватывает функцию вместе с привязками переменных. Помимо повсеместного использования замыканий, в функциональном программировании есть несколько других отличительных черт, таких как использование рекурсивных функций и неизменяемых значений (оба хорошо взаимодействуют). Эти черты являются культурной проблемой больше, чем что-либо еще, и нет никаких технических препятствий для их использования практически на любом языке, поэтому в своем ответе я остановлюсь на замыканиях: не каждый язык позволяет легко создавать замыкания.
Типичное использование замыканий - реализация механизмов конфиденциальности. Например, код Javascript - в примерах я выбрал Javascript, потому что это функциональный язык с так называемым «C-подобным синтаксисом», и ваш вопрос предполагает, что вы знакомы с C:
create_counter = function()
{
var x = 0;
var counter = function()
{
++x;
return x;
};
return counter;
}
Затем с
a = create_counter();
b = create_counter();
у нас есть две функции a
и b
подсчет непересекающихся коллекций. Суть примера в том, что переменные x
захватываются замыканием, определяющим counter
замыкание, и каждый раз, когда возникает новое counter
замыкание is instantiated by the function, it gets its fresh own idea of what
x`.
Другим типичным использованием замыканий является определение частичного применения функций. Предположим, что у нас есть средство отчетности, аналогичное syslog
реализации функции
var log = function(priority, message) {
…
};
где аргументы priority
и , message
как ожидается, будут строки, первый из которых один из "debug"
, "info"
и так далее. Мы можем определить фабрику журналов следующим образом:
var logWithPriority = function(priority) {
return function(message) {
log(priority, message);
};
};
и использовать его для определения специализированных версий нашего средства ведения журнала:
var debug = logWithPriority("debug");
var info = logWithPriority("info");
…
Это очень полезно, потому что вместо написания подверженных ошибкам for
циклов вроде этого
for(i = 0; i < journal.length; ++i) {
log("info", journal[i]);
}
мы можем написать чище, короче и намного проще (нет i
, это намного лучше):
journal.forEach(logWithPriority("info"));
Третья важная область применения замыканий - реализация отложенной оценки - обратите внимание, что специальная языковая поддержка может обеспечить лучшую реализацию.
Ленивая функция вместо прямого вычисления возвращает замыкание, которое может быть вызвано (или «вынуждено» на жаргоне лени) для выполнения вопроса. Мотивация для этого состоит в том, что он разделяет подготовку вычисления и выполнение вычисления. Практическим примером этого является компиляция регулярных выражений: если программа компилирует много регулярных выражений во время запуска, для запуска потребуется много времени. Если вместо этого мы лениво скомпилируем регулярные выражения и заставим их работать так, как нам нужно, тогда наша программа может быстро запуститься. Конечно, регулярные выражения здесь можно заменить любой структурой, требующей значительного времени инициализации.
Вот как реализовать отложенную оценку с замыканиями. Рассмотрим классическую реализацию функции arrayMax, возвращающей максимум в массиве:
function arrayMax(array) {
return array.reduce(function(a, b) {
return Math.min(a, b);
};
}
Ленивый вариант будет:
function arrayMax(array) {
var memo = null;
function actuallyCompute() {
if(memo === null) {
memo = array.reduce(function(a, b) {
return Math.min(a, b);
});
}
return memo;
}
return actuallyCompute;
}
Возвращаемое значение является замыканием, которое можно использовать для вычисления значения или получения его в другой раз, если оно уже было вычислено.
Используя эти три примера, мы должны быть уверены, что замыкания и их приложения являются ядром функционального программирования.
Изучение функционального программирования означает обучение программированию с замыканиями. Как следствие, языки, позволяющие легко манипулировать замыканиями, и особенно частичное применение функций, должны учитываться при поиске языка для изучения функционального программирования. И наоборот, языки, в которых закрытие нельзя легко манипулировать, были бы плохим выбором.
Я думаю, что инструменты, которые вы используете, сильно влияют на ваше обучение. Практически невозможно выучить концепции программирования, для которых используемый вами язык программирования не предоставляет средств для использования. Конечно, вы всегда можете выучить несколько вещей, но вы не можете выучить это правильно.
Но в любом случае это академично, потому что, как говорит Мартиньо в своем комментарии , даже если бы вы могли изучать функциональное программирование, вы не должны пытаться это делать, потому что есть языки, где это намного проще.
Вы не должны изучать функциональное программирование на C, но на строгом функциональном языке (Haskell, Caml, Erlang и т. Д.).
Если вы новичок в функционале, вы никогда не получите его с не функциональным языком. Скорее всего, вы научитесь делать то, что вы считаете функциональным программированием, и учиться неправильно. И всегда труднее «переучивать» вещи правильным образом, чем поначалу учить их правильно.
В любом случае, я думаю, что функционирование в C - это хорошее упражнение для тех, кто уже знает функционал. Потому что этот человек узнает, что происходит за укрытием - что на самом деле делает компьютер.