На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (11) « Первая ... 6 7 [8] 9 10 ... Последняя » все  ( Перейти к последнему сообщению )  
> Что делать с жунами , Что делать с жунами
    Цитата sergioK @
    хватит тут теории разводить,с умным видом, JVM тут ыообще не причем, он и в STL есть,

    И вот это поизучай:

    ExpandedWrap disabled
      ❯❯❯ g++ -O2 -std=c++17 -o lists main.cpp
       
      ❯❯❯ time ./lists 100000000 stdlist
      Result: 3749999975000000
      ./lists 100000000 stdlist  14.97s user 0.91s system 99% cpu 15.892 total
       
      ❯❯❯ time ./lists 100000000 stdvector
      Result: 3749999975000000
      ./lists 100000000 stdvector  0.61s user 0.42s system 99% cpu 1.040 total


    src

    ExpandedWrap disabled
      #include <iostream>
      #include <list>
      #include <string>
      #include <vector>
       
      void usage(std::string, std::string);
      int64_t std_list(int64_t);
      int64_t std_vector(int64_t);
       
      int main(int argc, char** argv)
      {
          if (argc != 3)
          {
              usage(std::string(argv[0]), "invalid arguments");
              return 1;
          }
       
          const int64_t n = std::stoi(std::string(argv[1]));
          if (n < 1)
          {
              usage(std::string(argv[0]), "invalid nitems");
              return 2;
          }
       
          std::string type(argv[2]);
       
          int64_t result;
          if (type == "stdlist")
          {
              result = std_list(n);
          }
          else if (type == "stdvector")
          {
              result = std_vector(n);
          }
          else
          {
              usage(std::string(argv[0]), "unsupported type");
              return 3;
          }
       
          std::cout << "Result: " << result << std::endl;
      }
       
      void usage(std::string app, std::string err)
      {
          std::cerr << err << std::endl;
          std::cerr << "Usage: " << app << " <nitems> <type>" << std::endl;
          std::cerr << "nitems: positive integer" << std::endl;
          std::cerr << "type:" << std::endl;
          std::cerr << "\tstdlist" << std::endl;
          std::cerr << "\tstdvector" << std::endl;
      }
       
      int64_t std_list(int64_t n)
      {
          std::list<int64_t> xs;
       
          for (auto i = 0; i < n; ++i)
          {
              xs.push_back(i);
          }
       
          xs.remove_if([n](int x) {
              return x < n/2;
          });
       
          int64_t sum = 0;
          for (auto x : xs)
          {
              sum += x;
          }
       
          return sum;
      }
       
      int64_t std_vector(int64_t n)
      {
          std::vector<int64_t> xs;
       
          for (auto i = 0; i < n; ++i)
          {
              xs.push_back(i);
          }
       
          auto filter = std::remove_if(xs.begin(), xs.end(), [n](int x) {
              return x < n/2;
          });
       
          xs.erase(filter, xs.end());
       
          int64_t sum = 0;
          for (auto x : xs)
          {
              sum += x;
          }
       
          return sum;
      }



    Так что там с загрузкой неизвестного большого количества данных в linked list?
      Цитата korvin @
      Цитата sergioK @
      хватит тут теории разводить,с умным видом, JVM тут ыообще не причем, он и в STL есть,

      И вот это поизучай:

      ExpandedWrap disabled
        ❯❯❯ g++ -O2 -std=c++17 -o lists main.cpp
         
        ❯❯❯ time ./lists 100000000 stdlist
        Result: 3749999975000000
        ./lists 100000000 stdlist  14.97s user 0.91s system 99% cpu 15.892 total
         
        ❯❯❯ time ./lists 100000000 stdvector
        Result: 3749999975000000
        ./lists 100000000 stdvector  0.61s user 0.42s system 99% cpu 1.040 total


      src

      ExpandedWrap disabled
        #include <iostream>
        #include <list>
        #include <string>
        #include <vector>
         
        void usage(std::string, std::string);
        int64_t std_list(int64_t);
        int64_t std_vector(int64_t);
         
        int main(int argc, char** argv)
        {
            if (argc != 3)
            {
                usage(std::string(argv[0]), "invalid arguments");
                return 1;
            }
         
            const int64_t n = std::stoi(std::string(argv[1]));
            if (n < 1)
            {
                usage(std::string(argv[0]), "invalid nitems");
                return 2;
            }
         
            std::string type(argv[2]);
         
            int64_t result;
            if (type == "stdlist")
            {
                result = std_list(n);
            }
            else if (type == "stdvector")
            {
                result = std_vector(n);
            }
            else
            {
                usage(std::string(argv[0]), "unsupported type");
                return 3;
            }
         
            std::cout << "Result: " << result << std::endl;
        }
         
        void usage(std::string app, std::string err)
        {
            std::cerr << err << std::endl;
            std::cerr << "Usage: " << app << " <nitems> <type>" << std::endl;
            std::cerr << "nitems: positive integer" << std::endl;
            std::cerr << "type:" << std::endl;
            std::cerr << "\tstdlist" << std::endl;
            std::cerr << "\tstdvector" << std::endl;
        }
         
        int64_t std_list(int64_t n)
        {
            std::list<int64_t> xs;
         
            for (auto i = 0; i < n; ++i)
            {
                xs.push_back(i);
            }
         
            xs.remove_if([n](int x) {
                return x < n/2;
            });
         
            int64_t sum = 0;
            for (auto x : xs)
            {
                sum += x;
            }
         
            return sum;
        }
         
        int64_t std_vector(int64_t n)
        {
            std::vector<int64_t> xs;
         
            for (auto i = 0; i < n; ++i)
            {
                xs.push_back(i);
            }
         
            auto filter = std::remove_if(xs.begin(), xs.end(), [n](int x) {
                return x < n/2;
            });
         
            xs.erase(filter, xs.end());
         
            int64_t sum = 0;
            for (auto x : xs)
            {
                sum += x;
            }
         
            return sum;
        }



      Так что там с загрузкой неизвестного большого количества данных в linked list?

      Ты применяешь std_list не по месту, https://www.geeksforgeeks.org/advantages-an...of-linked-list/
      больше я бесплатно обьяснять не буду ,
      Сообщение отредактировано: sergioK -
        Цитата sergioK @
        Ты применяешь std_list не по месту

        Цитата sergioK @
        А LinkedList нужен когда ды ты считываешь данные неопередельной длины, особенно большие обьемы,

        :facepalm:

        а свои джуновские статейки лучше забудь.
          Цитата D_KEY @
          Так я к тому, что не ответ
          Ну какой был вопрос такой и ответ. Я не знаю чего ты ожидал.
          Цитата D_KEY @
          Аргументации чего? Ты выкинул из конвенционально принятого определения ИП половину, а аргументы какие-то должен приводить я?
          Скажем так. Спор сводится фактически к одному моему утверждению: Можно ли писать императивно не используя мутабельных переменных?.
          Причем не синтетические примеры, а реальный полезный код.
          Можно, конечно скатываться в терминологическую демагогию, как это делаешь ты: ну типа раз в определении ИП написано "мутабельный", значит ответ очевиден: низзя. А на остальное насрать. В таком случае можешь просто не участвовать в данном споре, потому что мне интересна оправданность необходимости мутабельности в ИП. Действительно ли иммутабельность кардинально меняет парадигму и код, внезапно, превращается в функциональный?
          Рассуждения о пользе этого спора вообще смехотворны, мы тут не поиском истины занимаемся, а делимся мыслями и точками зрения. Ведь вне зависимости от того согласитесь ли вы со мной или нет, ничего не поменяется вообще :)
          Беседа, по-сути, философская. Хотя некоторые аспекты диалога с korvin, уже ближе к реальности.
          Цитата D_KEY @
          Смотри, это зависит от определения императивности. Ты же пытаешься наоборот , из примера вывести определение. Или я тебя не понимаю.
          Я рассуждаю так. Вот код, в нем есть последовательность инструкций, но нет мутабельности. Получается, что код не подходит под "конвенционально принятое" определение ФП (не должно быть последовательности инструкций). И не подходит под "конвенционально принятое" определение ИП (должна быть мутабельность).
          Подумав я решил, что иммутабельность в ФП - это не какая-то самоцель, а следствие из самой сущности ФП. Нет необходимости где-то держать промежуточные результаты, потому что их попросту не существует, а что тогда мутировать? Получается, что иммутабельность не должна входить в определение ФП вообще, она автоматически следует из отсутствия промежуточных результатов.
          Далее, рассматривая ИП, я пришел к выводу, что промежуточные результаты совсем не обязательно должны быть мутабельными. Что мешает на очередном шаге создавать новую иммутабельную переменную, вместо мутации старой? Ничего не мешает, более того, я постоянно так делаю, и при этом код не превращается в функциональный, так как последовательность иструкций никуда не девается. Получается, что обязательность мутабельности как бы "искусственно" прицеплена к определению, без каких либо логических причин. А как же эта мутабельность вообще попала в определение ИП? Ведь вряд ли кто-то действительно беспричинно ее туда запихал. Но это можно объяснить просто историей императивного программирования.
          Отсюда делаю. вывод: "конвенционально принятое" определение ИП устарело. Ключевое - это последовательность инструкций. А, если подняться еще выше по уровню абстракции, то ИП тесно связано с течением времени. Время - это не просто очередная координата пространства, а фундаментальная особая составляющая ИП. В отличие от ФП.
          Цитата korvin @
          А если б у бабушки...
          Ну так не выводи в консоль, а просто возвращай результат и получится чистое ФП. Не понимаю, что ты хотел сказать этим примером.
          Цитата korvin @
          Так как бы языки перестают быть "монопарадигмальными". А популярные языки никогда такими и не были. Иммутабельность была в Си, Паскале и практически любом другом языке с самого начала, не понимаю, что эта твоя фраза должна означать.
          Ты ошибаешься, возможно путаешь иммутабельность и возможность объявлять константы. const в том же Си появилась, внезапно, в C89, благодаря тому самому Страуструпу, который добавил его сначала в свой Си с классами. Я помню времена, когда строковые литералы в сяшке имели тип char*. В школьном бейсике вообще не было никаких константных переменных. В php нормальной иммутабельности не было ни в 4-ой, ни в 5-ой версии, сейчсас не знаю. В JS const появился в ES6. Интересно, что даже сейчас const ни в C, ни в C++, ни в JS не является полноценной поддержкой иммутабельности, так как const не гарантирует иммутабельность (в отличие от immutable в D). Короче, о иммутабельности в прикладном программировании серъезно начали задумываться сравнительно недавно. ФП, конечно, возникло давно, но оно едва-едва начало выползать из академических кругов.
          Цитата korvin @
          Есть и она точно такая же: очередной элемент будет проверен после предыдущего.
          Вообще-то нет. Этож одна из фишек этого вашего ФП, типа смотрите, компилятор может все нафиг распараллелить. Представь, что операция сравнения очень тяжелая. В ФП можно раздербанить список на элементы и запустить кучу потоков, которые будут параллельно выполнять сравнение. При этом твой код никак не изменится.
          Цитата korvin @
          Присутствует: нельзя вычислить значение функции, не вычислив её аргумента.
          Нет не присутствует. Сравни императивную версию:
          ExpandedWrap disabled
            a = foo(x)
            bar(a)

          с функциональной
          ExpandedWrap disabled
            bar(foo(x))

          На первый взгляд кажется, что разницы нет, но на самом деле есть. В императивном варианте функция foo будет выполнена до начала выполнения функции bar. В функциональной же версии foo может быть выполнена уже после начала выполнения bar (например в середине или даже паралелльно), да и вообще пофиг когда она выполнится. Мысли абстрактней, в ФП композиция функций - это просто новая функция, а не последовательность вызовов функций.
          В реальности, конечно, последовательность будет, потому что исполнитель любой ФП-программы императивен и любая задача все равно так или иначе будет разбитна на шаги компилятором/интерпретатором. Этот эффект используется в Haskell, там, где нужна императивность, например в некоторых монадах. Но это не относится к самой парадигме ФП, это несовершенство реализации.
          Сообщение отредактировано: applegame -
            Цитата applegame @
            Отсюда делаю. вывод: "конвенционально принятое" определение ИП устарело.

            Я бы сделал другой вывод. Применение термина ИП к практике современного программирования потеряло актуальность. Ну и подходов-то не два ;) Да и в чистом виде мало кто применяет только какой-то один.
              Цитата korvin @
              а свои джуновские статейки лучше забудь.
              Да не, там отличные, на мой взгляд, статейки. Там прекрасно описаны достоинства и недостатки связных списков в том числе по сравнению с массивам. И вообще, рассмотрена туева хуча всяких видов списков, включая xor и unrolled варианты, на доступном английском языке с картинками. Даже дебил осилит. Инфа представленная там никак не противоречит твоим бенчам, скорее наоборот, объясняет почему так может происходить.
                Цитата applegame @
                Ты ошибаешься, возможно путаешь иммутабельность и возможность объявлять константы. const в том же Си появилась, внезапно, в C89, благодаря тому самому Страуструпу, который добавил его сначала в свой Си с классами. Я помню времена, когда строковые литералы в сяшке имели тип char*. В школьном бейсике вообще не было никаких константных переменных.

                Нет, не ошибаюсь. Но раз ты не понял, о чём я, то подскажу: opaque struct + функции чтения.

                Цитата applegame @
                Вообще-то нет.

                Вообще-то да.

                Цитата applegame @
                Этож одна из фишек этого вашего ФП, типа смотрите, компилятор может все нафиг распараллелить.

                Параллельность к этому примеру вообще не в тему.

                Цитата applegame @
                В ФП можно раздербанить список на элементы и запустить кучу потоков, которые будут параллельно выполнять сравнение. При этом твой код никак не изменится.

                В моём примере нет списка.

                Цитата applegame @
                ExpandedWrap disabled
                  a = foo(x)
                  bar(a)


                ExpandedWrap disabled
                  bar(foo(x))


                На первый взгляд кажется, что разницы нет, но на самом деле есть. В императивном варианте функция foo будет выполнена до начала выполнения функции bar. В функциональной же версии foo может быть выполнена уже после начала выполнения bar (например в середине или даже паралелльно), да и вообще пофиг когда она выполнится. Мысли абстрактней, в ФП композиция функций - это просто новая функция, а не последовательность вызовов функций.


                И вот ты снова путаешь синтаксис и семантику.
                Чисто функциональный код на Хаскелле:
                ExpandedWrap disabled
                  do
                    a <- foo x
                    bar a

                do-нотация является ни чем иным, как синтаксическим сахаром для монадной функции bind (оператор '>>=' и '>>' ):
                ExpandedWrap disabled
                  foo x >>= \a -> bar a

                который в свою очередь является просто композицией функций, определённой в используемой монаде:
                ExpandedWrap disabled
                  (\a -> bar a) (unwrap (foo x))


                При этом
                ExpandedWrap disabled
                  bar(foo(x))

                foo вычислится гарантировано до вызова bar при аппликативном порядке вычислений (а это все неленивые ФП языки, F#, Ocaml, Clojure и т.д.)

                а
                ExpandedWrap disabled
                  a = foo(x)
                  bar(a)

                может вычислиться в другом порядке при нормальном порядке вычислений или просто отложенных вычислениях, например, в Си/Паскале foo может вернуть какой-то объект Promise.

                Цитата applegame @
                Да не, там отличные, на мой взгляд, статейки. Там прекрасно описаны достоинства и недостатки связных списков в том числе по сравнению с массивам. И вообще, рассмотрена туева хуча всяких видов списков, включая xor и unrolled варианты, на доступном английском языке с картинками. Даже дебил осилит. Инфа представленная там никак не противоречит твоим бенчам, скорее наоборот, объясняет почему так может происходить.

                Значит, sergioK и вправду джун, раз не понимает даже статей, на которые сам ссылается. )
                Сообщение отредактировано: korvin -
                  Цитата korvin @
                  Нет, не ошибаюсь. Но раз ты не понял, о чём я, то подскажу: opaque struct + функции чтения.
                  Это ты называешь поддержкой иммутабельности в языке? Я вообще никогда не встречал, чтобы кто-то использовал opaque типы ради иммутабельности. Это же трешовый костыль вроде immutable.js. Ты бы еще просто запрет программисту менять объект назвал поддержкой иммутабельности в языке.
                  Цитата korvin @
                  В моём примере нет списка.
                  Тут нет списка?
                  Цитата korvin @
                  ExpandedWrap disabled
                    contains []     e = False
                    contains (x:xs) e = x == e || contains xs e
                  Что касается оператора ||, то хотя в конкретной реализации (например GHC) сначала действительно будет вычислено значение левого операнда, надо понимать, что это просто деталь реализации. || - это ведь просто функция двух аргументов и ты сам совершенно правильно говорил, что порядок вычисления этих аргументов не имеет значения в ФП:
                  Цитата korvin @
                  Странный вопрос. Для чистого ФП разницы нет (разве что одна из функций bar, baz значительно дольше вычисляется, чем другая).
                  Судя по тому, что я нашел в интернетах, Haskell не запрещает реализации вычисляющие операнды в любом порядке.
                  Цитата korvin @
                  И вот ты снова путаешь синтаксис и семантику.
                  То что do-нотация является сахаром к монаде - это не семантика, это детали реализации. Семантика же заключается в последовательном выполнении. И do-нотация, кмк, отходит от ФП в сторону ИП.
                  Цитата korvin @
                  foo вычислится гарантировано до вызова bar при аппликативном порядке вычислений (а это все неленивые ФП языки, F#, Ocaml, Clojure и т.д.)
                  Это опять же деталь реализации. Мы же не о конкретном языке говорим. ФП подразумевает нестрогую модель вычислений: порядок выполнения функций неважен.
                  Цитата korvin @
                  может вычислиться в другом порядке при нормальном порядке вычислений или просто отложенных вычислениях, например, в Си/Паскале foo может вернуть какой-то объект Promise.
                  Пример с Promise неудачен, функция foo-то все равно выполнена до начала выполнения функции bar. Что касается нормального порядка вычислений, то это опять же деталь реализации. Компилятор может сделать редукцию, свертку констант и так далее, а может и не сделать. Результат гарантированно будет таким же как и при реально последовательном выполнении, иначе это неправильный компилятор.
                  В общем, ты везде ссылаешься на конкретные реализации, причем разные в разных ФП-языках.
                  Сообщение отредактировано: applegame -
                    Цитата korvin @
                    Значит, sergioK и вправду джун, раз не понимает даже статей, на которые сам ссылается. )

                    Не не понимаю, я ничего кроме hello world никогда не писал ;)
                      Цитата applegame @
                      Я вообще никогда не встречал, чтобы кто-то использовал opaque типы ради иммутабельности.

                      Мало ли что ты не встречал.

                      Цитата applegame @
                      Это же трешовый костыль

                      В чём тут трешевость и костыльность?

                      Цитата applegame @
                      Ты бы еще просто запрет программисту менять объект назвал поддержкой иммутабельности в языке.

                      WUT?

                      Цитата applegame @
                      надо понимать, что это просто деталь реализации

                      И что, что это деталь реализации? Порядок задан? Задан.

                      Цитата applegame @
                      Судя по тому, что я нашел в интернетах, Haskell не запрещает реализации вычисляющие операнды в любом порядке.

                      И что? Calling conventions тоже разные бывают.

                      Цитата applegame @
                      То что do-нотация является сахаром к монаде - это не семантика, это детали реализации

                      Нет, это то, чем она является.

                      Цитата applegame @
                      Семантика же заключается в последовательном выполнении

                      Нет, не заключается.

                      Цитата applegame @
                      И do-нотация, кмк, отходит от ФП в сторону ИП.

                      Не отходит.

                      Что, по-твоему, означает эта запись:

                      ExpandedWrap disabled
                        do
                            a <- foo x
                            b <- bar y
                            return $ gee a b

                      ?

                      Цитата applegame @
                      Пример с Promise неудачен, функция foo-то все равно выполнена до начала выполнения функции bar.

                      И что, что она выполнена до? Что будет, если поменять их местами? Чем по-твоему это отличается от Хаскелла, например? Чем это отличается от ФП, если реальное вычисление может быть выполнено в любом порядке?

                      Цитата applegame @
                      Результат гарантированно будет таким же как и при реально последовательном выполнении, иначе это неправильный компилятор.
                      В общем, ты везде ссылаешься на конкретные реализации, причем разные в разных ФП-языках.

                      Что ты вообще несёшь?

                      Ответь лучше на вопрос: почему в ИП порядок имеет значение? Что будет, если в
                      ExpandedWrap disabled
                        a = foo(x)
                        b = bar(y)
                        gee(a, b)

                      поменять местами вызовы foo и bar:
                      ExpandedWrap disabled
                        b = bar(y)
                        a = foo(x)
                        gee(a, b)

                      ?

                      Добавлено
                      И ещё вопрос: для ФПшной композиции порядок важен?

                      ExpandedWrap disabled
                        foo x = x + x
                        bar x = (x, x)


                      ExpandedWrap disabled
                        foo . bar

                      и
                      ExpandedWrap disabled
                        bar . foo

                      — одно и то же или нет?

                      А тут:
                      ExpandedWrap disabled
                        foo x = x + 1
                        bar x = x * 2
                         
                        foo . bar
                        bar . foo

                      ?
                      Сообщение отредактировано: korvin -
                        И кроме всего прочего, как компилятор, так и процессор могут переставлять инструкции при необходимости, если это не нарушает связи между данными и не изменяет наблюдаемый результат, поэтому порядок инструкций языка может не везде совпадать с реальным порядком выполнения.

                        Например http://csg.csail.mit.edu/pubs/memos/Memo-493/memo-493.pdf
                        Сообщение отредактировано: korvin -
                          Цитата Qraizer @
                          Использовались ли математические методы доказательства правильности разработанных алгоритмов?
                          На закуску: приходилось ли проектировать системы с учётом возможных неизвестных аппаратных багов в процессорах?

                          Математически доказано, что невозможно проверить зависнет программа или нет. На этом можно остановиться.
                          Программа должна работать на компьютере, который не умеет считать?
                            Цитата korvin @
                            Мало ли что ты не встречал.
                            А ты встречал чтобы кто-нибудь в C/С++ задействовал opaque типы ради иммутабельности? Пруфы пожалуйста.
                            Цитата korvin @
                            В чём тут трешевость и костыльность?
                            В том, что гарантиии иммутабельности дает не язык, а код, то бишь программист. Например те же функции чтения могут из-за ошибки программиста изменить opaque данные, и компилятор возражать не будет.
                            Цитата korvin @
                            И что, что это деталь реализации? Порядок задан? Задан.
                            В GHC задан, в другом компиляторе может быть не задан. Ты же надеюсь понимаешь, что мы обсуждаем не конкретные реализации, а ФП в целом? Ты же сам признал, что порядок вычисления аргументов функции в ФП не имеет значения.
                            Цитата korvin @
                            Нет, это то, чем она является.
                            Ну тогда она является императивными машинными кодами, а реального ФП не существует.
                            Цитата korvin @
                            Что, по-твоему, означает эта запись:
                            Как минимум она означает, что foo будет выполнена раньше чем bar. Вся эта ваша монада IO для этого и предназначена: дать возможность в Haskell выполнять код последовательно, потому что IO - это связь с внешним миром, который императивен.
                            Цитата korvin @
                            И что, что она выполнена до? Что будет, если поменять их местами? Чем по-твоему это отличается от Хаскелла, например? Чем это отличается от ФП, если реальное вычисление может быть выполнено в любом порядке?
                            Если поменять местами строчки, оно просто не скомпилируется. Тем что во всякой императивщине отложенность прописывается явно, то есть программист сам решает в каком порядке делать вычисления, а в Хаскелле програмисту пофиг (до тех пор пока не столкнется с императивной реальностью) в каком порядке оно будет считаться. От ФП отличается тем, что в ИП программист точно знает, что конечный результат будет как при последовательном выполнении. А в ФП наплевать на порядок выполнения вообще, компилятор может выполнять функции в любом нужном ему порядке.
                            Цитата korvin @
                            Ответь лучше на вопрос: почему в ИП порядок имеет значение? Что будет, если в
                            ExpandedWrap disabled
                              a = foo(x)
                              b = bar(y)
                              gee(a, b)
                            поменять местами вызовы foo и bar:
                            ExpandedWrap disabled
                              b = bar(y)
                              a = foo(x)
                              gee(a, b)
                            ?
                            Результат может измениться. А вот в чистом ФП (например Хаскеле) ничего измениться не может.
                            Цитата korvin @
                            И ещё вопрос: для ФПшной композиции порядок важен?
                            Порядок чего? Порядок записи конечно важен, могут же получиться в итоге разные функции. Примерно как спросить, поменяется ли что-нибудь если в числе 42 поменять местами 2 и 4.
                            Цитата korvin @
                            И кроме всего прочего, как компилятор, так и процессор могут переставлять инструкции при необходимости, если это не нарушает связи между данными и не изменяет наблюдаемый результат, поэтому порядок инструкций языка может не везде совпадать с реальным порядком выполнения.
                            Ключевое тут "не изменяет наблюдаемый результат". Более того, наблюдаемый результат обязан быть таким же как при последовательном выполнении инструкций. То есть компилятор может делать все что угодно (детали реализации), но выглядеть все должно так, как будто инструкции выполняются одна за другой.
                              Цитата applegame @
                              А ты встречал чтобы кто-нибудь в C/С++ задействовал opaque типы ради иммутабельности? Пруфы пожалуйста.

                              А если не встречал, то что это доказывает? Я так-то на Си не пишу.

                              Цитата applegame @
                              В GHC задан, в другом компиляторе может быть не задан. Ты же надеюсь понимаешь, что мы обсуждаем не конкретные реализации, а ФП в целом? Ты же сам признал, что порядок вычисления аргументов функции в ФП не имеет значения.

                              "Не имеет значения" и "отсутствует" --- не одно и то же

                              Цитата applegame @
                              Как минимум она означает, что foo будет выполнена раньше чем bar. Вся эта ваша монада IO для этого и предназначена: дать возможность в Haskell выполнять код последовательно, потому что IO - это связь с внешним миром, который императивен.

                              Не обязательно. И do-нотация не завязана на монаду IO, она работает с любой монадой, например монадой списков:
                              ExpandedWrap disabled
                                import Data.Char
                                 
                                foo = map chr . map (+ ord 'a')
                                bar = filter even
                                gee x y = (x, y)
                                 
                                main =
                                    let x = [1,2,3]
                                        y = [4,5,6]
                                    in print $ do
                                        a <- foo x
                                        b <- bar y
                                        return $ gee a b

                              https://ideone.com/0wW9IY
                              ExpandedWrap disabled
                                [('b',4),('b',6),('c',4),('c',6),('d',4),('d',6)]

                              Порядок определяется реализацией монады для конкретного типа, а не do-выражением.

                              Цитата applegame @
                              Результат может измениться. А вот в чистом ФП (например Хаскеле) ничего измениться не может.

                              За счёт чего же результат может измениться? )

                              Цитата applegame @
                              Ключевое тут "не изменяет наблюдаемый результат"

                              А за счёт чего наблюдаемый результат может измениться?

                              Цитата applegame @
                              Если поменять местами строчки, оно просто не скомпилируется.

                              Это в первом случае, где у функций разные типы. А во втором? Там всё прекрасно скомпилируется. А результат поменяется?
                              Сообщение отредактировано: korvin -
                                Цитата korvin @
                                А если не встречал, то что это доказывает? Я так-то на Си не пишу.
                                Я писал много и на Си и на C++. Никто на парится иммутабельностью вообще. Раньше даже const-ом не заморачивались, сейчас юзают const, который тоже не является полноценной заменой иммутабельности. В общем никакой поддержки иммутабельности в самих языках C/С++/JS/PHP и многих других нет. Есть только попытки эмулировать ее теми или иными способами, и эти эмуляции мало кого интересуют. В Rust есть полноценная иммутабельность, в D тоже есть.
                                Цитата korvin @
                                "Не имеет значения" и "отсутствует" --- не одно и то же
                                А ты не противопоставляй эти тезисы. Последовательность отсутствует в ФП-коде, потому что не она не имеет значения. То бишь сам ФП-код не задает никакой последовательности действий. Это уже реализация имеет какую-то последовательность, которая тоже может быть любой.
                                Цитата korvin @
                                Не обязательно. И do-нотация не завязана на монаду IO, она работает с любой монадой, например монадой списков:
                                Честно говоря лень уже дальше разбираться. Мое знание Хаскеля достаточно базовое и довольно тяжело копаться даже в несложных кусках.
                                Погуглив по словам "haskell do imperative" обнаружил кучу упоминаний о том, что на хаскеле можно (но не нужно) писать имеративно, применяя монады, что do-нотация является псевдоимперативной или imperative style и так далее.
                                Цитата korvin @
                                За счёт чего же результат может измениться? )
                                Цитата korvin @
                                А за счёт чего наблюдаемый результат может измениться?
                                За счет побочных эффектов, очевидно. Причем побочных эффектов в реальности может и не быть, но если компилятор об этом не знает, то он не будет переставлять местами инструкции.
                                Цитата korvin @
                                Это в первом случае, где у функций разные типы. А во втором? Там всё прекрасно скомпилируется. А результат поменяется?
                                Ты похоже потерял нить, проследи эту ветку немного назад. Речь вроде шла об этом куске:
                                ExpandedWrap disabled
                                  a = foo(x)
                                  bar(a)
                                А ты о каком?
                                Сообщение отредактировано: applegame -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0881 ]   [ 15 queries used ]   [ Generated: 28.05.24, 01:34 GMT ]