LINUX.ORG.RU

Функциональщина. Что выбрать?


0

0

Решил в свободное время заняться изучением модного нынче функционального программирования. Встал естественный вопрос: что выбрать? Этих всяких лиспов, хацкелей, оцамлей и т.п. вагон и маленькая тележка. Чтобы не распыляться выбрал Scheme, т.к. его используют в SICP, но настораживает его не слишком большая распространённость и «академичность». С другой стороны, лямбды и прочие «вкусности» потихоньку приходят и во всякие там питоны и даже плюсы. Не холивара окаянного ради, а сугубо для просвещения и развития спрашиваю: что изучать, чтобы не лежало оно потом мёртвым грузом? У каких языков какие плюсы, минусы и области применения?

★★★★

Последнее исправление: Gvidon (всего исправлений: 1)

Ответ на: комментарий от Miguel

>Вот почему когда говоришь «система типов» всякие анонимусы слышат «иерархия объектов»?

Ну да, наверняка в хаскелле иерархию тяжело сделать. Ещё один недостаток вместо преимущества от выводы типов?

Ещё раз: в том же Хаскеле, например, многие ошибки становятся (или могут быть сделаны) ошибками типизации.

ещё один звонок другу, какбы. А печать бесконечного списка? Это уже не универсальное деление на ноль, а чисто фича из хаскелла.

Ну дык переделывай систему типов, кто мешает-то?

система типов. Например, в динамике в CL. Пишем по с ГУИ, добавляем в гуи функцию для какого-то объекта, а реализации пока ещё нет. Всё запускается и работает, а при использовании объекта пользователем, вместо сегфолта и аналогов, вызывается кондишн, пользователю выводится уведомление о неготовой функции, и программа продолжает работать в штатном режиме. Динамическая система типов делает ПО безопаснее, устойчивее к некоторым ошибкам. В статике пришлось бы писать свой велосипед, реализующий динамику. И это частный случай, многое потенциально ошибочное может быть вынесено на уровень типов для динамической типизации.

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

при наличии нормальных юнит-тестов - сомневаюсь (всякий низкоуровневый код по работе с железом в расчёт не принимаю, там своя специфика).

Не понял, юнит-тесты помогают ОБНАРУЖИТЬ ошибку - но ИЗБЕЖАТЬ? Вы изобрели какие-то новые юнит-тесты.

А то я никак не могу от наших «адептов Haskell» какого-нибудь значимого кода, который они написали, добиться

Блин. http://hackage.haskell.org/packages/archive/pkg-list.html - изучайте до посинения.

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

> В стеке не видно.

Кого? Объект? Ну обычно видно, а значит можно запустить инспектор и посмотреть что с ним не так. Но если всё таки не видно, то можно сделать так, что бы было видно. Чуть хлопотнее, но не на много.

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

> Например, в динамике в CL. Пишем по с ГУИ, добавляем в гуи функцию для какого-то объекта, а реализации пока ещё нет. Всё запускается и работает, а при использовании объекта пользователем, вместо сегфолта и аналогов, вызывается кондишн, пользователю выводится уведомление о неготовой функции, и программа продолжает работать в штатном режиме.

Примерчик просто убойный. А написать обычную заглушку что мешает? Она ничуть не хуже выведет уведомление и вернет управление в цикл обработки событий.

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

> юнит-тесты помогают ОБНАРУЖИТЬ ошибку - но ИЗБЕЖАТЬ?

Какая разница, если ошибка уже обнаружена, то её уже нет.

Блин. http://hackage.haskell.org/packages/archive/pkg-list.html -

изучайте до посинения.



Это всё ваш код? Я говорю про личный опыт работы над большими проектами. Насколько я понял по

Понятно, серьёзных программ вы не писали.


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

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

>А написать обычную заглушку что мешает?

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

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

Ну да, наверняка в хаскелле иерархию тяжело сделать.

Тьфу, ёкарный бабай. Иерархия делается элементарно, вопрос в другом - нахрена? В подавляющем большинстве случаев иерархию делают либо если язык слабенький (отсюда, скажем, плюсовый паттерн «Команда», который по нормальному делается замыканием без всякой иерархии), либо по незнанию (когда ту же «Команду» тянут, скажем, в CL).

А печать бесконечного списка? Это уже не универсальное деление на ноль, а чисто фича из хаскелла.

Я написал «многие», с какого перепою ты увидел «все»?

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

Пишем по с ГУИ, добавляем в гуи функцию для какого-то объекта, а реализации пока ещё нет.

Как раз для таких вещей в Хаскеле есть тип Maybe.

Динамическая система типов делает ПО безопаснее, устойчивее к некоторым ошибкам.

То есть, позволяет отгрузить пользователю неработающую систему, что он заметит не сразу. Поня-а-атно.

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

В стеке не видно.

Кого? Объект?

Той функции, которая записала фигню.

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

>> А написать обычную заглушку что мешает?

Да то, что ещё неизвестно какие заглушки нужны,

void stub(const char *)

что конкретно изменить, какие типы ещё добавятся и т.д.

Это уже будут не заглушки.

Можно было бы хотя бы прочесть для какой ситуации пример был приведён.

Я прочитал. И кстати, это был вопрос не тебе (если тот анонимус - не ты).

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

Какая разница, если ошибка уже обнаружена, то её уже нет.

Большая. Выше было утверждение, что ошибки бывают редко и беспокоиться о них не надо. Теперь говорится, что ошибки, которые не обнаруживаются юнит-тестами бывают редко. Согласен, но почему не переложить часть (значительную) работы на компилятор, вместо того, чтобы проверять руками (сиречь юнит-тестами)?

Это всё ваш код?

Вас слишком волнует моя персона. Я скромный.

Понятно, серьёзных программ вы не писали.

В данном случае, мне не так интересно, на каком языке. Стек не даёт ответов, какой бы язык ни использовался.

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

Стек не даёт ответов, какой бы язык ни использовался.

Если это не Бейсик.

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

> Стек не даёт ответов, какой бы язык ни использовался.

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

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

> Вас слишком волнует моя персона. Я скромный.

Ну вы же берёте на себя ответственность что-то утверждать? И при этом на что-то ссылаетесь... Я вот хочу понять, что это, реальный опыт или просто теоретические измышления. За последние полтора год я написал на Common Lisp около 20 000 строк кода (попутно писал и на других языках) и вот проблема ошибок меня совершенно не беспокоит. Не то, что бы их нет, просто они обычны тривиальны и решаются практически без проблем, назвать их устранение важной или большой частью проекта я не могу. И я не понимаю, почему вы придаете этому такого большого значения, что у вас за опыт такой?

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

>либо по незнанию (когда ту же «Команду» тянут, скажем, в CL).

там объекты другие. паттерны не нужны.

то это как раз мелочь (тот вид ошибки, который быстро замечают).

С чего это? Ну тогда вообще статическая проверка не нужна, все ошибки заметны сразу. О чем же тогда спорить?

Как раз для таких вещей в Хаскеле есть тип Maybe.

Нету, пока его не поставят явно. И будут доп. расходы на согласование типов.

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

Не отгрузить, а посмотреть сразу самому. И ещё раз, некоторые ошибки типов могут быть нормой, как часть нормальной работы ПО.

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

>>>А написать обычную заглушку что мешает?

Да то, что ещё неизвестно какие заглушки нужны, что конкретно изменить, какие типы ещё добавятся и т.д.

Это уже будут не заглушки.

Вот это и мешает написать заглушку.

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

>И ещё раз, некоторые ошибки типов могут быть нормой, как часть нормальной работы ПО.

некоторые ошибки типов могут быть нормой

ошибки ... нормой

мне одному кажется, что кагебы нет?

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

>Я прочитал. И кстати, это был вопрос не тебе (если тот анонимус - не ты).

мы все я.

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

>мне одному кажется, что кагебы нет?

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

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

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

Ты понимаешь, что ошибка природы не может быть нормой. Ошибка типов тоже не может быть нормой.

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

а как быть с инвариантами классов при динамической типизации?

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

похоже, что ты вообще ничего формально не верифицировал

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

вот пример кода:

public class InvariantTest
{
  public static class Array2
  {
    public Array2(int nn) { n=nn; a=new int[n]; b=new int[n]; }
    public int[] get_a() { return a; }
    public int[] get_b() { return b; }
    public int   get_n() { return n; }
    public void set_n(int nn)
    {
      int[] aa=new int[nn];
      int[] bb=new int[nn];
      for(int i=0; i<n && i<nn; i++)
      {
        aa[i]=a[i];
        bb[i]=b[i];
      }
      a=aa;
      b=bb;
      n=nn;
    }
    private int n;
    private int[] a;
    private int[] b;
  }
  public static void main(String[] args)
  {
    System.out.print("всегда будет get_a().length == get_b().length == get_n()");
    Array2 x = new Array2(5);
    int[] xx = new int[100];
    // x.get_a()=xx; // не проходит
    // x.a=xx;       // не проходит
  }
}

/// и плюс к этому еще 10 мегабайт исходников

Чтобы формально верифицировать get_a().length == get_b().length == get_n(), мне достаточно запретить доступ к приватным через рефлексию и проанализировать только 20 строк кода Array2 — таким образом я докажу этот инвариант класса.

Как ты будешь доказывать этот инвариант в случае с динамической типизацией языка, не просматривая 10 МБ исходников? Приведи пример кода и идею доказательства.

www_linux_org_ru ★★★★★
()

>Как ты будешь доказывать этот инвариант в случае с динамической типизацией языка, не просматривая 10 МБ исходников?

Никак, это никому не нужно. Тем более там какая-то лажа в примере написана.

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

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

P.S. Верификацией не занимался.

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

>Ошибка типов тоже не может быть нормой.

смотря что под ними понимать.

Ты понимаешь, что ошибка природы не может быть нормой.

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

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

>> Как ты будешь доказывать этот инвариант в случае с динамической типизацией языка, не просматривая 10 МБ исходников?

Никак, это никому не нужно. Тем более там какая-то лажа в примере написана.

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

И где там лажа?

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

>За последние полтора год я написал на Common Lisp около 20 000 строк кода (попутно писал и на других языках) и вот проблема ошибок меня совершенно не беспокоит.

Нет программ - нет ошибок. Хитро...

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

>тем самым информацию( её проверку) о типе как мы о нём думаем, размываем частично на ручную и автоматическую проверку.

Хех... значитс юнит тесты покрывают лишь какой-то процент ошибок. Проверка статической типизацией покрывает какой-то другой процент ошибок абсолютно независимо от юнит тестов, но при этом без нашего участия(автоматически). Как-бы напрашивается вывод, что статическая типизация уменьшает количество ошибок в конечном сщете и главное уменьшает наши усилия по поиску ошибок. ?????. ПРОФИТ.

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

>Программ нет, а системы есть

Система есть, а кода нет.

За последние полтора год я написал на Common Lisp около 20 000 строк кода



Теперь понятно почему ошибок нет :)

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

>Раскрой тему подробнее

Зачем? Это не нужно никому кроме тебя. Изначально речь была о том что формальные критерии не связаны с типами языка. Их выбирают исходя из задачи, а не из типов языка.

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

> Проверка статической типизацией покрывает

какой-то другой процент ошибок


Какой ещё другой? Если юнит-тесты проходят, то ошибок типизации нет, либо тесты ну очень не полны.

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

>Как-бы напрашивается вывод, что статическая типизация уменьшает количество

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

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

>Проверка статической типизацией покрывает какой-то другой процент ошибок абсолютно независимо от юнит тестов

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

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

Зачем? Это не нужно никому кроме тебя. Изначально речь была о том что формальные критерии не связаны с типами языка.

В опровержение этого твоего бреда утверждения я привел кусок кода, где типы языка существенно помогают проверять формальные критерии корректности программы.

Их выбирают исходя из задачи, а не из типов языка.

выходи из анабиоза, уже лет 10 типы соответствуют задаче

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

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

«хочу вычисляю, хочу нет» мне тоже не нравится

операторы типа && из плюсов нужны, и должны иметь прототип вроде такого:

bool operator && ( bool a, bool b() );

www_linux_org_ru ★★★★★
()

[quote] Решил в свободное время заняться изучением модного нынче функционального программирования. Встал естественный вопрос: что выбрать? Этих всяких лиспов, хацкелей, оцамлей и т.п. вагон и маленькая тележка. Чтобы не распыляться выбрал Scheme, т.к. его используют в SICP, но настораживает его не слишком большая распространённость и «академичность». С другой стороны, лямбды и прочие «вкусности» потихоньку приходят и во всякие там питоны и даже плюсы. Не холивара окаянного ради, а сугубо для просвещения и развития спрашиваю: что изучать, чтобы не лежало оно потом мёртвым грузом? У каких языков какие плюсы, минусы и области применения? [/quote]

Ты хочешь «выучить» один из модных функциональных языков или всё-таки заняться ФП? Если первое - бери F#, он очень модный

Если второе - читай книжки и разные статейки и не ограничивайся одним из языков. Часто встречаются примеры на ML/Haskell/Scheme. Желательно уметь читать исходники на этих языках.

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

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

Каким образом? В данном типе не определено значение 1/0, если в выражении 1/In In может принимать значение 0 компилятор выведет ошибку.

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

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

Да? Я думал, что пока мы не вычислим 1/0, то ошибки не будет. Будь то Хаскель или Си. Если в Си мы не дойдём до вычисления 1/0, то всё будет хорошо.

так что у хаскелла проблемы с юнит тестированием тоже возможны, и наверняка их много

Как это? Не вижу связи между. Можешь обьяснить?

suzuki
()

Не слушай никого. Возьми VB.NET или C#, там функциональщина есть. Поиграй с лямбдами немного, пока не надоест, и больше к этим глупостям не возвращайся. Есть гораздо более полезные и интересные вещи, те же generics или например LINQ.

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

> в реальном мире программы на CL занимаются обработкой ошибок, связанных с типами

Obvious fix

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

> Если юнит-тесты проходят, то ошибок типизации нет, либо тесты ну очень не полны.

Даже при 100% покрытии юнит-тесты не гарантируют отсуствие ошибок типизации (а 100% покрытия на практике не бывает :)). А вот компилятор Хаскеля отсуствие ошибок типизации гарантирует.

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

не бери на свой счёт - многим совершенно без разницы под каким столбом^W^W^W в каком топике гадить

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

где-то видел вот эту гениальную фразу:
На ЛОР чтобы обсудить перспективы Ocaml
нужно открыть ветку о возможностях Tcl.

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

> Вот нифига себе я спросил...

Тебе еще на первой странице ответили :)

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

Вот нифига себе я спросил...

Да кому какая разница, чего ты там спросил.

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

>Какой ещё другой? Если юнит-тесты проходят, то ошибок типизации нет, либо тесты ну очень не полны.

Это не правда.

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

Этот случай ленивости абсолютно эквивалентн ветвлению(if then else, while) в других языках.

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

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

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

Конкретно на цацкеле статическая типизация, вывод типов и полиморфизм позволяет достаточно generic programming без макросов, т. е. средствами языка и без необходимости таскать словари функций руками. Получается очень компактно и достаточно читабельно, в отличии от.

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