LINUX.ORG.RU

стоит ли изучать функциональные языки программирования?


0

0

Здравствуйте.

Вот, думаю, изучать функциональные языки программирования или нет? В данный момент умею программировать на C (в том числе и кернел-спейс). Кто чего скажет?

Кто может объяснить, чем они лучше/хуже императивных языков программирования?

anonymous

Обязательно. Они не лучше, они другие.

stassats ★★★★
()

Вопрос из серии стоит ли вообще изучать программирование.

marsijanin ★★
()

Если есть желание и свободное время - конечно изучай.

> чем они лучше/хуже императивных языков программирования?

Некоторые задачи на них решаются проще, чем на императивных языках программирования.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> Если есть желание и свободное время - конечно изучай.

Желание есть.

> Некоторые задачи на них решаются проще, чем на императивных языках программирования.

Например?

anonymous
()
Ответ на: комментарий от anonymous

Например многие математические алгоритмы на хаскелле записываются практически как формулы. Например:
fac 0 = 1
fac n | n > 0 = n * fac (n-1)

quicksort:
quicksort [] = []
quicksort (s:xs) = quicksort [x|x <- xs,x < s] ++ [s] ++ quicksort [x|x <- xs,x >= s]

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

Ещё обычно очень удобно работать с рекурсивными структурами данных.

Legioner ★★★★★
()
Ответ на: комментарий от tailgunner

> Вообще-то стОит. Стоит ли тебе - вопрос.

Вот-вот, учитывая количество информации на данную тему (в том числе и флеймов на ЛОРе) вопрошающему такое так и хочется сказать "Не уверен..." :)

yyk ★★★★★
()

>Вот, думаю, изучать функциональные языки программирования или нет?

Насчет языков не знаю, а ФП изучать стоит. Обещаю, на многие вещи будешь смотреть по другому.

>Кто может объяснить, чем они лучше/хуже императивных языков программирования?

Чтобы пользоваться приемами ФП совершенно необязательно использовать декларативные языки, например на том же питоне можно можно писать в функциональном стиле... Да и на С++ тоже...

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

Самое непривычное в таких языках это комбинаторная логика. Мой простой пример что это такое:

Комбинаторная логика: cat file | grep "regexp" | sort > aaa.txt, где "|" и ">" - комбинаторы.

Не комбинаторная логика: file_cont = cat file; grep_val = grep file_cont; ... ; write(sort_val,"aaa.txt")

Очень много вещей в хаскеле построены на комбинаторной логике, а поскольку понятие переменная там отсутствует напрочь, ничего другого ты использовать не сможешь. И вместо pull, push и query моделей данных тебе придется использовать комбинаторную.

Другой пробелмой с которой я столкнулся - понимание рекурсивных структур данных. Т.е. понять, вроде бы простую вещь, что дерево, список и S-выражение это _одно и то же_. А затем полюбить и научиться использовать рекурсивные структуры данных.

Третья проблема - понять что в ФП мире нет разделения на "функции" и "данные".

Наиболее известные языки Lisp, Haskell, Ocaml. В принципе, смтореть нужно их все. Scheme можешь не смотреть - тот же лисп, только имена другие. ML - предок хаскеля.

Macil ★★★★★
()
Ответ на: комментарий от stassats

>Подразумевается Common Lisp?

Да, конечно.

>Еще нонче модно Erlang.

Ах да, как же это про него? Заставляет задуматься над очень интересной идеей, что объект это нить, которая помимо всего прочего физически может находиться черт знает где ;)

Macil ★★★★★
()
Ответ на: комментарий от Macil

> Третья проблема - понять что в ФП мире нет разделения на "функции" и "данные".

Ээ.. не понял :) Как это нет? Не лиспом единым ведь.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

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

krum
()
Ответ на: комментарий от Legioner

>Как это нет? Не лиспом единым ведь.

А список от 1 до бесконечности это что такое? Функция иди данные?

Macil ★★★★★
()
Ответ на: комментарий от krum

> Имеется в виду функции высшего порядка

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

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

>> А список от 1 до бесконечности это что такое? Функция иди данные?

>данные А каков Ваш критерий? Данный объект - список от 1 до бесконечности - отображает множество целых чисел в множество целых чисел. И чем не функция не понятно.

krum
()
Ответ на: комментарий от krum

> А каков Ваш критерий? Данный объект - список от 1 до бесконечности - отображает множество целых чисел в множество целых чисел. И чем не функция не понятно.

список ничего не отображает, это вы с ним связали функцию "f(i) = list[i]".

Legioner ★★★★★
()
Ответ на: комментарий от Macil

> ???? И на чем ты такой список собрался хранить? На торсионном накопителе?

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

Legioner ★★★★★
()

В общем предмета спора, как такогого нет, скорее здесь дело сведётся к определениям, и претензиям к ним. Мысль о единстве данных и кода я понял.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Не математик ты, не любишь точные понятия.А это и есть __суть__ вопроса. Итак, что такое по-твоему данные, и как ты их отличаешь от функций?

krum
()
Ответ на: комментарий от krum

ох уж эти сказочки, ох уж эти сказочники и
теоретики от программирования ...

Valeriy_Onuchin ★★
()

не знаю как Лисп, но насчет Хаскеля могу вставить 5 копеек. Скажем так, приведенный тут пример для факториалов и сортировки, реализованный на Хаскеле интересен с чисто академической точки зрения, т.к. сам язык не позволяет менять значение тех или иных данных in-place, то реализация указанных алгоритмов на Хаскеле, да еще и с применением рекурсии не интересна для практических целей. Грубо говоря жрется много памяти и делается уйма вызвов функций в рекурсии, что серъезно сказывается на производительности. Т.к. такие простые конструкции как например циклы в Хаскеле отсутствуют, и заменяется цикл рекурсией, то производительность программ на Хаскеле без соответсвующей оптимизации исполнеймого кода или работы интерпретатора (чего сейчас нет ни в HUGS ни в GHC) просто ниже плинтуса.

Сама концепция конечно интересна, но мне честно говоря непонятно чем она лучше императивной, тем более, что ООП по сути включил в себя некоторые концепции ФП (например декларативное программирование). Изучить Хаскель полезно для кругозора, практической же пользы очень мало. Конечно ИМХО.

cathode
()
Ответ на: комментарий от dilmah

> функциональные языки нужны для того чтобы генерировать императивный код

Веско. Авторитетно. Жаль только, что непнятно :D

tailgunner ★★★★★
()
Ответ на: комментарий от Macil

> Наиболее известные языки Lisp

Строго говоря, Common Lisp - не ЯФП.

1. В стиле чистого ФП на нем писать не рекомендуется, т.к. оптимизации хвостовой рекурсии нет в стандарте и в некоторых реализациях (например, в clisp в режиме интерпретации).

2. С чисто синтаксической т.з., функции несколько отличаются от остальных значений. Например, (let ((f (lambda (x) (+ x x)))) (f 2)) -- неправильно.

Кстати, именно в этом плане Scheme приятнее, чем Common Lisp, т.к. ФП заложено в нее изначально.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от Legioner

> Ээ.. не понял :) Как это нет? Не лиспом единым ведь.

Ну, в лямбда-исчислении данных нет вообще :)

Например, в Хаскеле:

foo :: a -> a -> a

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

let x = foo

Это явно функция, ее можно вызвать: let x' = x 1 2

let y = foo 1

Это уже функция от одного аргумента: let y' = y 2

let z = foo 1 2

А вот это что? :) 0-арная функция или данные? Особенно учитывая ленивость хаскелльных вычислений. Синтаксически, "вызов" является очевидным логическим продолжением предыдущих: let z' = z

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от Legioner

> Можно хранить текущий элемент и функцию, вычисляющую следующий. Можно ещё как нибудь.

Фактически, это императивное решение, жутко кривое с т.з. ФП. В ФП используется гораздо более простой, но общий принцип. В ФП-стиле нет никакой разницы между конечным списком [1..10] и бесконечным [1..], поэтому не приходится "еще как-нибудь" решать задачу хранения бесконечного списка.

watashiwa_daredeska ★★★★
()
Ответ на: комментарий от cathode

>Сама концепция конечно интересна, но мне честно говоря непонятно чем она лучше императивной...

Ты путаешь парадигмы, ФП отлично существует как в императивных, так и в декларативных языках.

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

Намного более удачным примером будет работа с какой-то рекурсивной структурой данных, например парсинг XML или обработка какого-нибудь хитрого S-выражения. К сожалению, такой пример будет достаточно громоздким и непонятным.

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

Macil ★★★★★
()
Ответ на: комментарий от watashiwa_daredeska

>Строго говоря, Common Lisp - не ЯФП.

Скажем так, он и ЯФ, и нет. Многопарадигменный язык. И это считаю, что в реальных применениях --- это большое добро.

>1. В стиле чистого ФП на нем писать не рекомендуется, т.к. оптимизации хвостовой рекурсии нет в стандарте и в некоторых реализациях (например, в clisp в режиме интерпретации).

Тут дело в опредленеиях. Стандарт Scheme требует наличия этой оптимизации в компиляторе, а CL не требует. Отсутсвие или присутсвие этой оптимизации с CL всецело оставлено на долю реализации компилятора.

Zubok ★★★★★
()
Ответ на: комментарий от tailgunner

> > функциональные языки нужны для того чтобы генерировать императивный код

> Веско. Авторитетно. Жаль только, что непнятно :D

Настоящие Человеки пишут не код. Они пишут компиляторы которые генерируют код. И эти компиляторы они пишут в том числе и с применением идей ФП.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> Настоящие Человеки пишут не код. Они пишут компиляторы которые генерируют код.

/me с горечью отнес себя в кучу Ненастоящих Человеков. Или Настоящих Нечеловеков?

tailgunner ★★★★★
()
Ответ на: комментарий от dilmah

> Настоящие Человеки пишут не код. Они пишут компиляторы

Вспомнилось: "Основное применение SML - это написание компиляторов SML" 8)

tailgunner ★★★★★
()
Ответ на: комментарий от Legioner

>Ну функции высшего порядка, это даже в сях есть..

А можно, пожалуйста, пример функции высшего порядка на сях?

Laz ★★★★★
()
Ответ на: комментарий от Laz

>А можно, пожалуйста, пример функции высшего порядка на сях?

В C через указатели на функуию, в С++ через идиому Functor.

Macil ★★★★★
()
Ответ на: комментарий от Macil

Ну вот самый простой пример (define (inc-n n) (lambda (x) (+ x n))) Как сделать функцию на сях, принимающую один аргумент n и возвращающую функцию, прибавляющую свой аргумент к n ?

Laz ★★★★★
()
Ответ на: комментарий от krum

>> Чудо с копейкам, посмотри на это http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=ghc только потом низвергай свои заключения.

Получил удовольствие от твоего хамства, спасибо. Кушай: http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=gcc&...

cathode
()
Ответ на: комментарий от cathode

Чудо, ты опять обосрался, сравни уровни языков С и Haskell. Haskell нужно, как минимум сравнивать с GC. Ты бы ещё его с ассемблером сравнил.

krum
()
Ответ на: комментарий от krum

krum ты вырос вместе со стаей бомжей? откуда столько хамства? Фигли ты его с жабой тогда сравнивал, они че, одного уровня с хаскелем или С не язык программрования?

cathode
()
Ответ на: комментарий от Laz

> (define (inc-n n) (lambda (x) (+ x n)))

И тем не менее :)

struct closure
{
  int n;
  int (*lambda)(struct closure *c, int x);
};

int lambda(struct closure *c, int x)
{
  return c->n + x;
}

struct closure *inc-n(int n)
{
  struct closure *c = malloc(sizeof(struct closure));
  c->n              = n;
  c->lambda         = lambda;

  return c;
}

int main(void)
{
  struct closure *c = inc-n(10);
  printf("Result: %d\n", c->lambda(c, 7)); /* Result: 17 */
  free(c);
  return 1;
}

swizard
()
Ответ на: комментарий от Macil

>> Ты путаешь парадигмы, ФП отлично существует как в императивных, так и в декларативных языках.

>> Намного более удачным примером будет работа с какой-то рекурсивной структурой данных, например парсинг XML или обработка какого-нибудь хитрого S-выражения. К сожалению, такой пример будет достаточно громоздким и непонятным.

Естественно, что элементы ФП используются в ИП и наоборот. Речь немного не об этом. Сам язык целиком и полностью определяется своим синтаксисом, практически он может быть любым. В том числе и приближенным к математике как хаскель. И по большей части выбор синтаксиса - дело привычки. Но есть еще уровень абстракции, который определяется как синтаксисом, так и реализацией тех или иных библиотек. Так вот, когда приводятся примеры типа сортировки в хаскеле (2 строки) против сортировки например в С++ (строк 20) справшивается, а что мешает абстрагироваться от реализации в 20 строк в С++ посмотреть на STL, где это есть. Получим теже 2 строки. И что мы сравниваем тогда? Про парсинг XML - тоже самое, если абстракция реализуется синтаксисом и обвеской из библиотек, что лучше: когда XML можно распарсить без привлечения сторонней библиотеки или с оной?

cathode
()
Ответ на: комментарий от cathode

> Получим теже 2 строки. И что мы сравниваем тогда?

Ты, случайно, не для J2EE бизнес-правила на хмле пишешь? :) Обычно, с помощью библиотек всего не сделать, иначе б программеров уже давно упразднили

swizard
()
Ответ на: комментарий от cathode

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

krum
()
Ответ на: комментарий от swizard

>> (define (inc-n n) (lambda (x) (+ x n)))

>И тем не менее :)

Рыспект, как грицца, и уважуха =)). Хотя на лиспе, конечно, выглядит покрасивше.

Laz ★★★★★
()
Ответ на: комментарий от swizard

>> Ты, случайно, не для J2EE бизнес-правила на хмле пишешь? :) Обычно, с помощью библиотек всего не сделать, иначе б программеров уже давно упразднили

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

cathode
()
Ответ на: комментарий от cathode

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

Там ведь там руководствуются размером кода и понятностью, примеры же для новичков приводятся.

swizard
()
Ответ на: комментарий от krum

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

При чем здесь разница между языком и библиотекой? Я вообще-то говорил об уровне абстракции, который достигается при помощи тех или иных средств. То что в хаскеле не надо думать о типах - это громко сказано. Они там есть и думать о них надо. Пожалста, конструкция из приведенного тобой сравнения производительности:

depth :: Int -> Int -> [(Int,Int,Int)]

depth d m

| d <= m = (2*n,d,sumT d n 0) : depth (d+2) m

| otherwise = []

where n = 1 `shiftL` (m - d + minN)

Первая строка есть ничто иное как определение типа выражения (и откуда там собственно Int? Нет типов, говоришь?)

Не думать о памяти - вредно, чревато необычными сюрпризами. Да и потом, сборка мусора - не нововведение хаскеля.

cathode
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.