На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (31) 1 [2] 3 4 ...  30 31  ( Перейти к последнему сообщению )  
> идеальный язык программирования , каким он должен быть?
    Цитата Relan @
    def simple = and . @ % . distl . <id, tl . iota . dec . id>

    Расшифруй, плз...

    Добавлено
    Цитата Relan @
    Чувствуете разницу? На FP мы сказали "что делать" (т. е. просто сформулировали задачу), а на С -- "как делать" (расписали по шагам).

    Спорный вопрос - что лучше.
      Цитата wormball @
      Кстати, на Форте это будет выглядеть так
      А он поддерживает списки?
      Цитата wormball @
      а на ФП я не очень понял запись.
      ОК, попытаюсь поподробнее.
      ExpandedWrap disabled
        def pifagor = sqrt . + . @ sqr
        pifagor : <3, 5> # пример использования
      Этой функции передается список из двух значений длин катетов (которые называются объектами). К каждому из них применяется функция sqr (к каждому благодаря аппликации "@", иначе бы она применялась к списку), затем они складываются (функция "+" принимает список значений и возвращает атом, т. е. скаляр) и из полученного значения извлекается корень. Всё просто. :)
      Цитата wormball @
      Что в интернете можно почитать про функциональное и декларативное программирование?
      Лучше книжки читать. Теория -- это аппликативная вычислительная модель, лямбда-исчисление (особенно важда редукция лямбда-термов), комбинаторы, теория вычислимых функций (это уже не обязательно, хоть и интересно). Если серьезно заинтересуешься этой темой, могу скинуть список литературы и сами книги.
      Цитата wormball @
      Если я ничего не путаю, функциональное и декларативное программирование - две большие разницы?
      Да. Если на пальцах, декларативное программирование -- это общая концепция, когда ты говоришь системе "что делать", а она уже сама решает задачу, в противоположность императивному программированию, где программы являются последовательностью инструкций, модифицирующих память. Функциональное программирование -- подмножество декларативного, основано на аппликативной вычислительной модели. Существует еще логическое программирование (например Пролог).
      Цитата wormball @
      Кстати, если кто-то ещё не понял. Я не являюсь фанатичным поклонником Форта и затеял этот разговор не с целью заставить всех перейти на Форт, а именно выяснить, каким должен быть идеальный язык и какие языки больше всего претендуют на это звание.
      Да ладно, вполне нормальное обсуждение. :)

      Добавлено
      Цитата Flex Ferrum @
      Расшифруй, плз...
      ExpandedWrap disabled
        def simple = and . @ % . distl . <id, tl . iota . dec . id>
      Объявлена функция simple (с помощью ключевого слова def), после знака равенства идет ее тело. Очень важно: это НЕ присваивание! это равенство по определению. Точка означает композицию. Вычисление идет справа налево. Угловые скобки означают список, его элементы разделяются запятой. Функция id -- identity -- тождественная функция, которая возвращает свой аргумент, который будет передан функции simple при ее вызове. dec -- уменьшение значения, которое вернула id на единицу. iota создает список из чисел от 1 до значения аргумента. tl "откусывает" от этого списка первый элемент. distl формирует список пар элементов, где на первом месте будет первый аргумент, на втором -- каждый из остальных (поясню ниже). Форма "@ %" означает применение функции % (деление по модулю) к каждому элементу списка. and -- логическое И.

      В данном случае при вызове функции "simple : 5" (5 -- объект, к которому применяется функция) происходит следующее (опишу последовательно редукцию):
      ExpandedWrap disabled
        and . @ % . distl . <5, tl . iota . dec . 5>
        and . @ % . distl . <5, tl . iota . 4>
        and . @ % . distl . <5, tl . <1, 2, 3, 4>>
        and . @ % . distl . <5, <2, 3, 4>>
        and . @ % . <<5, 2>, <5, 3>, <5, 4>> # так работает distl
        and . <% . <5, 2>, % . <5, 3>, % . <5, 4>>
        and . <1, 2, 1>
        T # вычисление закончено, T означает true, F -- false
      Цитата Flex Ferrum @
      Спорный вопрос - что лучше.
      Ну, программы на функциональных языках обычно в 4-10 раз короче, чем на императивных, что ведет к улучшению качества кода и упрощению сопровождения. При этом они зачастую более понятны (если конечно уметь программировать в функ. стиле). В функциональном программировании нет понятия переменной (программы прозрачны по ссылкам), нет понятия поток управления. Соответственно, исключаются многие виды ошибок. К этому остается добавить, что функ. языки отлично распараллеливаются. Но есть конечно и проблемы.

      Добавлено
      Наверное многим это паказалось программированием через одно место, но это всегда так поначалу кажется. :) После нескольких лет императивного программирования научиться думать на функциональном языке ОЧЕНЬ сложно. Почти также сложно, как бросить курить (императивный стиль -- это вредная привычка). :)
      Сообщение отредактировано: Relan -
        Цитата Relan @
        Объявлена функция simple (с помощью ключевого слова def), после знака равенства идет ее тело. Очень важно: это НЕ присваивание! это равенство по определению. Точка означает композицию. Вычисление идет справа налево. Угловые скобки означают список, его элементы разделяются запятой. Функция id -- identity -- тождественная функция, которая возвращает свой аргумент, который будет передан функции simple при ее вызове. dec -- уменьшение значения, которое вернула id на единицу. iota создает список из чисел от 1 до значения аргумента. tl "откусывает" от этого списка первый элемент. distl формирует список пар элементов, где на первом месте будет первый аргумент, на втором -- все остальные (поясню ниже). Форма "@ %" означает применение функции % (деление по модулю) к каждому элементу списка. and -- логическое И.

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

        Цитата Relan @
        Ну, программы на функциональных языках обычно в 4-10 раз короче, чем на императивных, что ведет к улучшению качества кода и упрощению сопровождения. При этом они зачастую более понятны (если конечно уметь программировать в функ. стиле). В функциональном программировании нет понятия переменной (программы прозрачны по ссылкам), нет понятия поток управления. Соответственно, исключаются многие виды ошибок. К этому остается добавить, что функ. языки отлично распараллеливаются. Но есть конечно и проблемы.

        Я потому и говорю - спорный вопрос. По идее (запасясь достаточным объемом терпения и времени) я могу написать для С++ библиотеку, которая будет работать схожим образом. В конце концов - императивный/декларативный/функциональный - это лишь способы формализации задачи. Ведь могу же я в С++ написать:
        ExpandedWrap disabled
          #include <boost/lambda.hpp>
          using namespace boost;
           
          //...
          std::list<int> some_list;
           
          std::for_each(some_list.begin(), some_list.end(), std::cout << _1);
          //...

        Чем не лямбда-функция?
          Цитата Flex Ferrum @
          Но тут получается, что у функционального языка должен быть достаточно объемный набор встроенных функций/операторов.
          Ну да. Нужны библиотеки, как и для всякого языка.
          Цитата Flex Ferrum @
          Я к тому, что для того же С/С++ есть правило, что частью языка становится только то, что не может быть (или может, но очень сложно) реализовано посредством уже имеющегося набора.
          В моей реализации есть пародия на стандартную библиотеку, которая подключается автоматически и где определены многие функции (написанные на самом FP естественно, например dec и and). А в интерпретаторе остался лишь необходимый минимум. Впрочем, это уже детали реализации. Ничто не мешает следовать принципу минимализма, сформулированному тобой.
          Цитата Flex Ferrum @
          По идее (запасясь достаточным объемом терпения и времени) я могу написать для С++ библиотеку, которая будет работать схожим образом.
          Ну, можно и на С писать в объектно-ориентированном стиле. Но вот удобно ли?
          Цитата Flex Ferrum @
          Чем не лямбда-функция?
          Тем, что 1) объявлена переменная, 2) происходит изменение среды 3) явно описан поток управления. Как ни извращайся, а на С++ писать в истинно функциональном стиле не получится.
            Цитата Relan @
            Тем, что 1) объявлена переменная, 2) происходит изменение среды 3) явно описан поток управления.

            1) Как тебе такой вариант:
            ExpandedWrap disabled
              template<typename C, typename F> void for_each(const C& c, F f)
              {
                  std::for_each(c.begin(), c.end(), f);
              }
               
               
              int main(int, char**)
              {
                  for_each(boost::assign::list_of(1)(2)(3)(4)(5)(6)(7), std::cout << boost::lambda::_1 << "\n");
               
               
                  return 0;
              }


            Добавлено
            Проверено - работает. Выдает честные
            ExpandedWrap disabled
              1
              2
              3
              4
              5
              6
              7
              Press any key to continue

            2) Что понимается под "изменением среды"?
            3) Каким образом я описал поток управления?
              Цитата Flex Ferrum @
              1) Как тебе такой вариант
              Прикольно. Даже догадываюсь как это сделано. :)
              Цитата Flex Ferrum @
              2) Что понимается под "изменением среды"?
              Любая модификация памяти. Например, в for_each происходит инкремент итератора.
              Цитата Flex Ferrum @
              3) Каким образом я описал поток управления?
              В Стандарте ведь определена ассоциативность операторов, в частности "<<"? ;) В функциональном языке таких жестких ограничений быть не должно, они там будут просто бессмысленны.
                Цитата Relan @
                Любая модификация памяти. Например, в for_each происходит инкремент итератора.

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

                Цитата Relan @
                В Стандарте ведь определена ассоциативность операторов, в частности "<<"?

                Да. Определена. Согласен.

                Цитата Relan @
                В функциональном языке таких жестких ограничений быть не должно, они там будут просто бессмысленны.

                Это как? Т. е. ты не можешь точно сказать - какой из операндов операции будет вычеслен в первую очередь? Так? А как же твоя фраза:
                Цитата Relan @
                Вычисление идет справа налево.


                Добавлено
                Кстати, вот что написано в стандарте про for_each:
                Цитата
                Applies f to the result of dereferencing every iterator in the range [first, last), starting
                fromfirstand proceeding tolast - 1.

                Т. е. стандарт не специфицирует - как именно функтор будет применен к каждому элементу диапазона. По этому инкремент итератора - это (можно считать) детали и особенность конкретной реализации.

                Добавлено
                Цитата Relan @
                Прикольно. Даже догадываюсь как это сделано.

                Вот еще вариантик:
                ExpandedWrap disabled
                  template<typename C, typename F> void for_each(const C& c, F f)
                  {
                      std::for_each(c.begin(), c.end(), f);
                  }
                   
                  template<typename T> class ContWrapper : public T
                  {
                  public:
                      ContWrapper<T>& operator ,(const typename T::value_type& v)
                      {
                          insert(end(), v);
                          return *this;
                      }
                  };
                   
                  template<typename T> ContWrapper<T> seq() {return ContWrapper<T>();}
                   
                  int main(int, char**)
                  {
                      for_each((seq<std::list<int> >(), 5, 2, 3, 1, 9, 20, -10, 8), std::cout << boost::lambda::_1 << "\n");
                      std::cout << std::endl;
                      for_each((seq<std::set<int> >(), 5, 2, 3, 1, 9, 20, -10, 8), std::cout << boost::lambda::_1 << "\n");
                   
                   
                      return 0;
                  }

                Выдает, опять же:
                ExpandedWrap disabled
                  5
                  2
                  3
                  1
                  9
                  20
                  -10
                  8
                   
                  -10
                  1
                  2
                  3
                  5
                  8
                  9
                  20
                  Цитата Relan @
                  Если серьезно заинтересуешься этой темой, могу скинуть список литературы и сами книги.

                  Давай.
                  Цитата Relan @
                  Ну, программы на функциональных языках обычно в 4-10 раз короче

                  А как насчёт скорости исполнения?

                  Добавлено
                  Цитата Relan @
                  После нескольких лет императивного программирования научиться думать на функциональном языке ОЧЕНЬ сложно. Почти также сложно, как бросить курить

                  Напоминило древнюю поговорку - "Легче бросит курить, чем Фортран 77"
                    Цитата Flex Ferrum @
                    Т. е. ты хочешь сказать, что при интерпретации твоей программы, написанной на функциональном языке, среда исполнения никак не меняется? Не модифицируются списки (пусть и временные), промежуточные результаты никак не сохраняются?
                    Я наверное неправильно выразился. В функ. языке объект однажды получает значение и больше никогда не изменяется вплоть до разрушения.
                    Цитата Flex Ferrum @
                    Т. е. ты не можешь точно сказать - какой из операндов операции будет вычеслен в первую очередь? Так? А как же твоя фраза
                    Да. Просто нет необходимости знать порядок вычислений операндов, т. к. побочные эффекты в чистых функ. языках отсутствуют. По поводу моей форазы -- имелась в виду функциональная форма композиции, ее нотация. Проводя аналогию с математикой: в выражении f(g(x)) мы ведь не можем начать вычисления ф-ции f до того, как будет вычислена g. Однако в выражении f(g(x), h(x)) мы можем вычислять g и h в любом порядке, т. к. математические функции не модифицируют х. Так же и в функ. программе.
                    Цитата Flex Ferrum @
                    Т. е. стандарт не специфицирует - как именно функтор будет применен к каждому элементу диапазона. По этому инкремент итератора - это (можно считать) детали и особенность конкретной реализации.
                    Ну, в принципе, можно переписать for_each так, чтобы использовалась рекурсия. Тогда это будет функ. стиль. Но for_each обычно используется либо для модификации последовательности, либо ради какого-то побочного эффекта. И то, и другое не вписывается в чистое функ. программирование.

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

                    Добавлено
                    Цитата Flex Ferrum @
                    Выдает, опять же
                    Всё это, конечно, замечательная гимнастика для ума, но на том же FP это делается так:
                    ExpandedWrap disabled
                      @ print : <5, 2, 3, 1, 9, 20, -10, 8>
                      @ print . sort : <5, 2, 3, 1, 9, 20, -10, 8>
                    Объем кода намного меньше и читается гораздо легче.
                    Цитата antigen @
                    Давай.
                    ОК, чуть попозжа доберусь до своей библиотеки и сделаю подборку.
                    Цитата antigen @
                    А как насчёт скорости исполнения?
                    Скорость исполнения программ на функ. языках обычно ниже, чем на императивных, т. к. последние по своей природе ближе к архитектуре машины. Хотя сейчас уже есть неплохие компиляторы Лиспа, не очень сильно отстающие в этом плане от С и С++.
                      Цитата Relan @
                      Я наверное неправильно выразился. В функ. языке объект однажды получает значение и больше никогда не изменяется вплоть до разрушения.

                      Ага. Вот так понятнее.

                      Цитата Relan @
                      Да. Просто нет необходимости знать порядок вычислений операндов, т. к. побочные эффекты в чистых функ. языках отсутствуют. По поводу моей форазы -- имелась в виду функциональная форма композиции, ее нотация. Проводя аналогию с математикой: в выражении f(g(x)) мы ведь не можем начать вычисления ф-ции f до того, как будет вычислена g. Однако в выражении f(g(x), h(x)) мы можем вычислять g и h в любом порядке, т. к. математические функции не модифицируют х. Так же и в функ. программе.

                      Ты можешь мне не верить, но в выражении вида f(g(x), h(x)), записанном на языке С++, порядок вычисления операндов не определен. Точно также, как и в приведенных примерах. Если бы я написал:

                      Цитата Flex Ferrum @
                      seq<std::set<int> >(), f(5), f(2), f(3), f(1), f(9), f(20), f(-10), f(8))

                      То порядок вызова функций f я наперед не знаю. Я лишь знаю, что операторы ',' будут вызваны последовательно один за другим и им в определенном порядке будут переданы результаты вычисления. Но не больше. :):
                      Цитата
                      The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations
                      take effect before the function is entered. The order of evaluation of the postfix expression and the argu-
                      ment expression list is unspecified.

                      (5.2.2, clause 8). А потому строчка
                      ExpandedWrap disabled
                            int i = 1;
                            for_each((seq<std::list<int> >(), ++ i, ++ i, ++ i, ++ i, ++ i, ++ i, ++ i, ++ i), std::cout << boost::lambda::_1 << "\n");

                      Выводит...
                      ExpandedWrap disabled
                        9
                        9
                        9
                        9
                        9
                        9
                        9
                        9


                      а
                      ExpandedWrap disabled
                        int ff(int volatile& i)
                        {
                            return i ++;
                        }
                         
                        int main(int, char**)
                        {
                            int volatile i = 1;
                            for_each((seq<std::list<int> >(), ff(i), ff(i), ff(i), ff(i), ff(i), ff(i), ff(i), ff(i)), std::cout << boost::lambda::_1 << "\n");

                      ExpandedWrap disabled
                        8
                        7
                        6
                        5
                        4
                        3
                        2
                        1

                      Вот такие вот "чудеса". :)

                      Цитата Relan @
                      Ну, в принципе, можно переписать for_each так, чтобы использовалась рекурсия. Тогда это будет функ. стиль. Но for_each обычно используется либо для модификации последовательности, либо ради какого-то побочного эффекта. И то, и другое не вписывается в чистое функ. программирование.

                      :no: for_each - это немодифицирующий алгоритм. Т. е., конечно, если ты захочешь, то функтор будет модифицировать элементы последовательности. Но обычно для этого есть другие - модифицирующие алгоритмы. А идея "один раз установленная переменная" в С++ отражена в метапрограммировании на шаблонах.

                      Добавлено
                      Цитата Relan @
                      Всё это, конечно, замечательная гимнастика для ума, но на том же FP это делается так:
                      @ print : <5, 2, 3, 1, 9, 20, -10, 8>
                      @ print . sort : <5, 2, 3, 1, 9, 20, -10, 8>

                      Первый - соглашусь. Второй - не эквивалентен, т. к. std::set != отсортированная последовательность, т. к. std::set - отсортированная последовательность уникальных элементов.
                      Ок. Ну а если я хочу вывести на консоль последовательность, каждый элемент который увеличен на некоторую константу?

                      Добавлено
                      Да и кто мне мешает написать алгортм print:
                      ExpandedWrap disabled
                        template<typename C> void print(const C& c)
                        {
                           std::for_each(c.begin(), c.end(), std::cout << _1 << "\n");
                        }

                      который сделает мне тоже самое, но короче?
                        Цитата Flex Ferrum @
                        Ага. Вот так понятнее.
                        Прошу прощения, если я где-то неясно излагаю, просто стараюсь не углубляться без необходимости. Блин, как-то аж неудобно читать лекции по программированию самому Flex Ferrum'у. :D
                        Цитата Flex Ferrum @
                        Ты можешь мне не верить, но в выражении вида f(g(x), h(x)), записанном на языке С++, порядок вычисления операндов не определен.
                        Знаю-знаю, что в С++ в данном случае запятая является разделителем аргументов, а не оператором "," (в котором ассоциативность определена). Я лишь привел пример, не надо его понимать буквально. Ну, пусть будет f(g(x) + h(x)), если это принципиально.
                        Цитата Flex Ferrum @
                        for_each - это немодифицирующий алгоритм. Т. е., конечно, если ты захочешь, то функтор будет модифицировать элементы последовательности.
                        Это я и имел в виду. В функ. языках "функтор" не может модифицировать сами элементы.
                        Цитата Flex Ferrum @
                        Первый - соглашусь. Второй - не эквивалентен, т. к. std::set != отсортированная последовательность, т. к. std::set - отсортированная последовательность уникальных элементов.
                        Конечно, просто в данном случае вывод будет таким же.
                        Цитата Flex Ferrum @
                        Ну а если я хочу вывести на консоль последовательность, каждый элемент который увеличен на некоторую константу?
                        Функция
                        ExpandedWrap disabled
                          print . @ (+ . <id, `10>) : <8, 3, 7, 1>
                        выведет <18, 13, 17, 11>.
                          Цитата Relan @
                          Блин, как-то аж неудобно читать лекции по программированию самому Flex Ferrum'у.

                          Ну, функциональное программирование прошло несколько в стороне от меня... :)

                          Цитата Relan @
                          Ну, пусть будет f(g(x) + h(x)), если это принципиально.

                          И в этом случае не определено - в каком порядке будут вычеслины g(x) и h(x). Т. е. это определено, если используется встроенный оператор +. А если перегруженный - то не определено. Тоже самое с оператором ','.

                          Цитата Relan @
                          Это я и имел в виду. В функ. языках "функтор" не может модифицировать сами элементы.

                          Так я же об этом дальше написал:
                          Цитата Flex Ferrum @
                          Но обычно для этого есть другие - модифицирующие алгоритмы.

                          например, std::transform.

                          Цитата Relan @
                          Конечно, просто в данном случае вывод будет таким же.

                          А как он будет выглядеть, если надо сохранить требование уникальности элементов?

                          Цитата Relan @
                          print . @ (+ . <id, `10>) : <8, 3, 7, 1>


                          Цитата Flex Ferrum @
                          ExpandedWrap disabled
                            for_each((seq<std::list<int> >(), 5, 2, 3, 1, 9, 20, -10, 8), std::cout << _1 + 10 << "\n");
                            std::cout << std::endl;
                            for_each((seq<std::set<int> >(), 5, 2, 3, 1, 9, 20, -10, 8), std::cout << _1 + 10 << "\n");


                          :whistle: :P
                            Цитата n0rd @
                            И чем более описание будет похожим на человеческий язык, тем идеальнее он будет :)

                            Конечно же нет. Человеческий язык "ужасно" не однозначен. И такого счастья как вы предлагаете никому не надо.
                              Flex Ferrum, назревает новый холивар "Функциональные языки против императивных"? :)
                                Цитата Relan @
                                Flex Ferrum, назревает новый холивар "Функциональные языки против императивных"?

                                :no: С чего ты взял? Но (с другой стороны) я пока не понял явного приемущества функционального подхода над императивным. И попытался продемонстрировать, что при определенной сноровке и в императивном языке можно использовать элементы функционального подхода.

                                Добавлено
                                Вот если реализуется одна моя идейка - то можно будет попробовать С++ в качестве декларативного языка...
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (31) 1 [2] 3 4 ...  30 31


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1009 ]   [ 14 queries used ]   [ Generated: 18.07.25, 01:25 GMT ]