1. C++ / Говнокод #25292

    −1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    std::optional<int64_t> readNumber(const wchar_t *&str)
    {
        const wchar_t *origStr = str;
    
        if (*str == L'-' || *str == L'+') {
            str++;
            if (!std::iswdigit(*str)) {
                str--;
                return {};
            }
        } else {
            if (!std::iswdigit(*str)) {
                return {};
            }
        }
    
        while (std::iswdigit(*str)) {
            str++;
        }
    
        return wcstoll(origStr, NULL, 10);
    }

    А всё потому, что доки по «wcstoll» надо читать!

    Запостил: gost, 07 Января 2019

    Комментарии (115) RSS

    • Тут по заданию нужно было отфильтровать хитрые варианты (когда строка начинается с пробелов, когда в строке записано число в шестнадцатеричной или в восьмеричной форме и т. п.) или можно было обойтись одним вызовом «wcstoll»?
      Ответить
      • Предполагается, что в &str[0] лежит десятичное целое число, за которым, возможно, идут другие символы. Функция должна прочитать это число и сдвинуть str к первому не-числовому символу, а если в строке числа нет — вернуть nullopt и ничего не двигать. Именно это (за исключением формата взаимодействия с аргументами) и делает «wcstoll», если ей передать валидный указатель на указатель на указатель на строку.
        Ответить
        • интересно через 100 лет с++ тупой копилятор до сих пор не сможет референсные перменные передавать по имени :) без указания "копировать" или "передать" :)
          Ответить
          • > не сможет референсные перменные передавать по имени
            Поясните мысль.

            > без указания "копировать" или "передать"
            void f(const string& s); // "передать"
            void f(string& s); // "передать" и разрешить нагадить в строку
            void f(string s); // "копировать"

            Что тут должен угадывать "умный" компилятор и зачем? Где компилятор "умный"?
            Ответить
            • показать все, что скрытоНе пытайся своим молчанием отвести от себя анальную кару.
              В таких случаях можно даже нарисовать график. Кривая долгое время идёт по фазе плато, затем наступает компенсаторный крах.
              Ответить
            • Ну это же указания вручную. Прошлый век.
              Всякие T, T*, T&, const, std::move, std::foward, std::shared_ptr, std::uniqie_ptr, стек, кучу, раскладку структур по байтам, паддинги, раскладку аргументов в стеке надо знать.
              Передать массив, вернуть массив? Сразу надо продумывать, два массива это или один, где их хранить. Даже простой fmap не реализуешь.
              Ответить
              • показать все, что скрытоНельзя передать массив, мой анальный друг. В любом случае передастся указатель.
                Ответить
                • А если мосив сунуть в структуру, он скопируется?
                  Ответить
                  • Да, внутри структуры он скопируется. Какая консистентность.
                    Ответить
                    • Кококококой багор )))

                      Я теперь понял, почему Dummy против тайпдефов и почему он так любит явно каждый раз писа́ть слово «struct».
                      Ответить
                      • показать все, что скрытоЯ не люблю
                        Распевы петуха
                        И говорю,
                        Что если был бы в силе,
                        То всем бы петухам
                        Я выдрал потроха,
                        Чтобы они
                        Ночьми не голосили.

                        Но я забыл,
                        Что сам я петухом
                        Орал вовсю
                        Перед рассветом края,
                        Отцовские заветы попирая,
                        Волнуясь сердцем
                        И стихом.
                        Ответить
                    • Скопируется, только если массив статический. Иначе один хуй копирует указатель. Лови дизлайк, бро.
                      Ответить
              • То ли дело «Python».
                То ли дело «Java».
                То ли дело «PHP».
                То ли дело «
                Ответить
              • > Передать массив, вернуть массив?
                > простой fmap не реализуешь

                возьмём для примера fmap для std::vector
                // не проверял, но вроде должно работать
                template <class T, class U>
                std::vector<U> map(std::function<U(T)> f, const std::vector<T>& in) {
                  std::vector<U> out;
                  for (const auto& x : in) out.push_back(f(x));
                  return out;
                }
                ЧЯДНТ?
                Ответить
                • А сложно ли будет реализовать еще две перегрузки для коллбека, как в javascript?
                  f(elem)
                  f(elem, index)
                  f(array, index, array)
                  Ответить
                  • Да в общем-то нет:
                    template <class T, class U>
                    std::vector<U> map(const std::function<U(T, size_t)> & f, const std::vector<T>& in)
                    {
                        std::vector<U> out;
                        for (size_t i = 0; i < in.size(); i++) {
                            out.push_back(f(in[i], i));
                        }
                        return out;
                    }
                    
                    template <class T, class U>
                    std::vector<U> map(const std::function<U(T, size_t, const std::vector<T> &)> & f, const std::vector<T>& in)
                    {
                        std::vector<U> out;
                        for (size_t i = 0; i < in.size(); i++) {
                            out.push_back(f(in[i], i, in));
                        }
                        return out;
                    }
                    Ответить
                    • Как-то скучно. Я думал, тут будет какая-то ебля с итераторами, шаблонами, вот этим вот всем.
                      А написать чтобы оно принимало все возможные итерируемые контейнеры сложно?
                      Ответить
                      • > А написать чтобы оно принимало все возможные итерируемые контейнеры сложно?

                        Чтобы принимало — легко, сложно возвращать контейнер того же типа. Если возвращать всегда вектор, то тривиально, только это уже не настоящий fmap будет.
                        template <class Seq, class Callable>
                        auto map(Callable f, const Seq& in) -> std::vector<decltype(f(*std::begin(in)))> {
                          std::vector<decltype(f(*std::begin(in)))> out;
                          for (const auto& x : in) out.emplace_back(f(x));
                          return out;
                        }
                        Тут пример gost снова не компилится, но по другой причине — компилятор не осиливает вывести тип Seq. Вот так вроде работает:
                        std::vector<int> xs = { 1, 2, 3, 4, 5 };
                        for (auto && x : map([](int x) { return x * x; }, xs)) {
                          std::cout << x << " ";
                        }

                        Если можно добавить перегрузки для f, если хочется, но так с выводом типов для лямбд проблемы начнутся.
                        Ответить
                        • Больше ебанутости!

                          namespace Pitushnya
                          {
                              template<class Container, class = void>
                              struct HasPushBack : std::false_type {};
                           
                              template<class Container>
                              struct HasPushBack<
                                  Container,
                                  decltype((void)std::declval<Container>().push_back(*std::declval<Container>().begin()))
                              > : std::true_type {};
                           
                           
                              template<class Container, class = void>
                              struct HasInsert : std::false_type {};
                           
                              template<class Container>
                              struct HasInsert<
                                  Container,
                                  decltype((void)std::declval<Container>().insert(*std::declval<Container>().begin()))
                              > : std::true_type {};
                          }
                           
                          template <class InContainerType, class OutContainerType>
                          std::enable_if_t<
                                  Pitushnya::HasPushBack<OutContainerType>::value
                                      && !Pitushnya::HasInsert<OutContainerType>::value,
                                  OutContainerType
                              >
                              map(
                                  std::function<
                                      std::remove_reference_t<
                                          decltype(*std::declval<OutContainerType>().begin())
                                      >
                                      (std::remove_reference_t<
                                          decltype(*std::declval<InContainerType>().begin())
                                      >)
                                  > f,
                                  const InContainerType & in
                              )
                          {
                              OutContainerType out;
                              for (const auto& x : in) out.push_back(f(x));
                              return out;
                          }
                           
                           
                          template <class InContainerType, class OutContainerType>
                          std::enable_if_t<
                              !Pitushnya::HasPushBack<OutContainerType>::value
                                  && Pitushnya::HasInsert<OutContainerType>::value,
                              OutContainerType
                          >
                          map(
                              std::function<
                                  std::remove_reference_t<
                                      decltype(*std::declval<OutContainerType>().begin())
                                  >
                                  (std::remove_reference_t<
                                      decltype(*std::declval<InContainerType>().begin())
                                  >)
                              > f,
                              const InContainerType & in
                          )
                          {
                              OutContainerType out;
                              for (const auto& x : in) out.insert(f(x));
                              return out;
                          }


                          https://ideone.com/OXbnXL
                          Ответить
                        • Можно и чтобы возвращало переданный, только придётся ебаться с шаблонами шаблонов и опять явно указывать типа. А ещё с конпеляторами — VS и новый GCC это нормально кушают, а вот старый GCC на «Ideone» — давится.
                          template <template<class> class ContainerType, class ElementType, class RetType>
                          std::enable_if_t<
                              Pitushnya::HasPushBack<ContainerType<RetType>>::value
                              && !Pitushnya::HasInsert<ContainerType<RetType>>::value,
                              ContainerType<RetType>>
                          map(
                              const std::function<RetType(ElementType)> &f,
                              const ContainerType<ElementType> & in
                          )
                          {
                              ContainerType<RetType> out;
                              for (const auto& x : in) out.push_back(f(x));
                              return out;
                          }
                           
                          template <template<class> class ContainerType, class ElementType, class RetType>
                          std::enable_if_t<
                              !Pitushnya::HasPushBack<ContainerType<RetType>>::value
                              && Pitushnya::HasInsert<ContainerType<RetType>>::value,
                              ContainerType<RetType>>
                          map(
                              const std::function<RetType(ElementType)> &f,
                              const ContainerType<ElementType> & in
                          )
                          {
                              ContainerType<RetType> out;
                              for (const auto& x : in) out.insert(f(x));
                              return out;
                          }
                           
                          int main()
                          {
                              for (auto && x : map<std::vector, int>(
                                      (std::function<float(int)>)[](int x) {return (float)x / 2.0f; },
                                      { 1, 2, 3, 4, 5 })) {
                                  std::cout << x << " ";
                              }
                              std::cout << std::endl;
                          
                              for (auto && x : map<std::list, int>(
                                      (std::function<float(int)>)[](int x) {return (float)x / 2.0f; },
                                      { 1, 2, 3, 4, 5 })) {
                                  std::cout << x << " ";
                              }
                              std::cout << std::endl;
                          
                              for (auto && x : map<std::set, int>(
                                      (std::function<float(int)>)[](int x) {return (float)x / 2.0f; },
                                      { 1, 2, 3, 4, 5 })) {
                                  std::cout << x << " ";
                              }
                              std::cout << std::endl;
                          
                              return EXIT_SUCCESS;
                          }

                          https://wandbox.org/permlink/LzoO6uc9s4p06erE
                          Ответить
                          • На ideone прокатило так (где map - из https://ideone.com/OXbnXL):
                            template <template <typename...> class Container, typename T, typename U>
                            Container<U> fmap (std::function<U(T)> f, const Container<T>& in) {
                            	return map<Container<T>, Container<U>>(f, in);
                            }

                            https://ideone.com/tbe7wk
                            Только не прокатит с контейнерами с кастомными аллокаторами. *

                            Зато вывод типов - почти тот же, что и был:
                            for (auto && x : fmap<std::vector, int, float> (
                                    [](int x) {return (float)x / 2.0f; },
                                    { 1,2,3,4,5 })) {
                                std::cout << x << " ";
                            }


                            P.S. * Хотя, с точки зрения функтора из ФП это не требуется. С точки зрения функтора пользователь сам пердолится с дополнительными параметрами, а нам отдаёт контейнер как однопараметрический тип.
                            Ответить
                            • Перевёл на «генераторы»:
                              template <template <typename...> class Container, typename T, typename U>
                              struct Generator {
                                  struct Iterator {
                                      Iterator(const std::function<U(T)> & f,
                                               const Container<T> & arr,
                                               decltype(std::begin(std::declval<Container<T>>())) it) :
                                          f(f),
                                          arr(arr),
                                          it(it)
                                      {}
                               
                                      U operator*()
                                      {
                                          return f(*it);
                                      }
                               
                                      Iterator & operator++()
                                      {
                                          ++it;
                                          return *this;
                                      }
                               
                                      Iterator & operator++(int)
                                      {
                                          ++it;
                                          return *this;
                                      }
                               
                                      bool operator==(const Iterator & other)
                                      {
                                          return it == other.it;
                                      }
                               
                                      bool operator!=(const Iterator & other)
                                      {
                                          return !this->operator==(other);
                                      }
                               
                                  private:
                                      std::remove_reference_t<decltype(std::begin(std::declval<Container<T>>()))> it;
                                      const std::function<U(T)> & f;
                                      const Container<T> & arr;
                                  };
                               
                                  Generator(const std::function<U(T)> & f,
                                            const Container<T> & arr) :
                                      f(f),
                                      arr(arr)
                                  {
                                  }
                               
                                  Iterator begin()
                                  {
                                      return Iterator(f, arr, std::begin(arr));
                                  }
                               
                                  Iterator end()
                                  {
                                      return Iterator(f, arr, std::end(arr));
                                  }
                               
                              private:
                                  std::function<U(T)> f;
                                  Container<T> arr;
                              };
                               
                              template <template <typename...> class Container, typename T, typename U>
                              Generator<Container, T, U> gmap(std::function<U(T)> f, const Container<T>& in)
                              {
                                  return Generator<Container, T, U>(f, in);
                              }

                              https://ideone.com/UIa7Kw

                              Правда, получилось дерьмо, которое копирует входную последовательность целиком. Можно, конечно, в Generator хранить константную ссылку, но тогда получается ещё большее дерьмо, и в gmap не получается передать временные объекты вроде «{1, 2, 3}».
                              Ответить
                              • Уже, тля, книжку можно выпускать: «Крестовые говноэтюды».
                                Ответить
                            • Улучшил генератор, теперь он копирует, только если ему передать временный объект (хуй проссышь, как это будет на крестовом языке «lrxprglvalue»):

                              template<template <typename...> class Container, typename T, bool IsTemp, typename E = void>
                              struct GeneratorBase;
                              
                              template<template <typename...> class Container, typename T, bool IsTemp>
                              struct GeneratorBase<Container, T, IsTemp, std::enable_if_t<IsTemp>> {
                              protected:
                                  GeneratorBase(const Container<T> & arr) : arr(arr) {}
                                  Container<T> arr;
                              };
                              
                              template<template <typename...> class Container, typename T, bool IsTemp>
                              struct GeneratorBase<Container, T, IsTemp, std::enable_if_t<!IsTemp>> {
                              protected:
                                  GeneratorBase(const Container<T> & arr) : arr(arr) {}
                                  const Container<T> & arr;
                              };
                              
                              
                              template<template <typename...> class Container, typename T, typename U, bool IsTemp>
                              struct Generator : GeneratorBase<Container, T, IsTemp> {
                                  /* Как в предыдущем примере с незначительными изменениями */
                              };
                              
                              template <template <typename...> class Container, typename T, typename U>
                              Generator<Container, T, U, true> gmap(std::function<U(T)> f, Container<T> && in)
                              {
                                  return Generator<Container, T, U, true>(f, in);
                              }
                              
                              template <template <typename...> class Container, typename T, typename U>
                              Generator<Container, T, U, false> gmap(std::function<U(T)> f, const Container<T> & in)
                              {
                                  return Generator<Container, T, U, false>(f, in);
                              }


                              «Ideone» не поддерживает божественный «C++17»: https://wandbox.org/permlink/B0Cebyx4ORrq7YB2 (хотя можно убрать «if constexpr» и получить то же самое на «C++14»).
                              Ответить
                              • Ой бля, только что обнаружил, что таким образом изобрёл собственный std::conditional.
                                Ответить
                                • Убрал велосипед, добавил кэширование, получилось почти понятно:
                                  template<template <typename...> class Container, typename T, typename U, bool IsTemp>
                                  struct Generator {
                                      struct Iterator {
                                          Iterator(const std::function<U(T)> & f,
                                                   const Container<T> & arr,
                                                   decltype(std::begin(std::declval<Container<T>>())) it) :
                                              it(it),
                                              f(f),
                                              arr(arr),
                                              cache()
                                          {
                                          }
                                  
                                          U operator*()
                                          {
                                              if (!cache) {
                                                  cache = f(*it);
                                              }
                                              return *cache;
                                          }
                                  
                                          Iterator & operator++()
                                          {
                                              cache = {};
                                              ++it;
                                              return *this;
                                          }
                                  
                                          Iterator & operator++(int)
                                          {
                                              cache = {};
                                              ++it;
                                              return *this;
                                          }
                                  
                                          bool operator==(const Iterator & other)
                                          {
                                              return it == other.it;
                                          }
                                  
                                          bool operator!=(const Iterator & other)
                                          {
                                              return !this->operator==(other);
                                          }
                                  
                                      private:
                                          std::remove_reference_t<decltype(std::begin(std::declval<Container<T>>()))> it;
                                          const std::function<U(T)> & f;
                                          const Container<T> & arr;
                                          std::optional<U> cache;
                                      };
                                  
                                      Generator(const std::function<U(T)> & f,
                                                const Container<T> & arr) :
                                          f(f),
                                          arr(arr)
                                      {
                                          if constexpr (std::is_reference_v<decltype(this->arr)>) {
                                              std::cout << "No copy" << std::endl;
                                          } else {
                                              std::cout << "Copy" << std::endl;
                                          }
                                      }
                                  
                                      Iterator begin()
                                      {
                                          return Iterator(f, arr, std::begin(arr));
                                      }
                                  
                                      Iterator end()
                                      {
                                          return Iterator(f, arr, std::end(arr));
                                      }
                                  
                                  private:
                                      std::function<U(T)> f;
                                      std::conditional_t<IsTemp, Container<T>, const Container<T> &> arr;
                                  };

                                  https://wandbox.org/permlink/jvCQLPgFM34d03Yd
                                  Ответить
                          • специализацию для std::unique_ptr<T[]> написать не забудь
                            Ответить
                • Дерьмо какое-то, а не вывод типов.
                  int main()
                  {
                      // OK, "1 4 9 16 25 "
                      for (auto && x : map<int, int>([](int x) { return x * x; }, { 1, 2, 3, 4, 5 })) {
                          std::cout << x << " ";
                      }
                      std::cout << std::endl;
                  
                      return EXIT_SUCCESS;
                  }


                  Стоит убрать это уёбищное <int, int> — и получаем:
                  prog.cpp:17:22: error: no matching function for call to 'map'
                      for (auto && x : map([](int x) { return x * x; }, { 1, 2, 3, 4, 5 })) {
                                       ^~~
                  prog.cpp:8:16: note: candidate template ignored: could not match 'function
                      <type-parameter-0-1 (type-parameter-0-0)>' against '(lambda at prog.cpp:17:26)'
                  std::vector<U> map(const std::function<U(T)> & f, const std::vector<T>& in)
                                 ^
                  1 error generated.

                  https://ideone.com/t1E4yA
                  Ответить
                  • Можно попробовать более конкретную функцию передавать:
                    (std::function<int(int)>)[](int x) { return x * x; }
                    Ответить
                    • Я, конечно, не специалист, но это выглядит ещё дерьмовее.
                      Ответить
                • Красота, работает даже питушня вида
                  for(const auto& x : map((std::function <double(float)>)[](auto x){ return x * 1.5; }, map((std::function <float(int)>)[](auto x){ return x * 2; }, std::vector<int>({1, 2, 3}))))
                  	std::cout << x << std::endl;


                  Только внутри какие-то копирования странные, число которых варьируется чёрт знает по какой логике: https://ideone.com/XwiHUb.
                  Неясно, что будет с монадическими значениями питухами, чувствительными к этому (хранящими ресурсы и т.п.).
                  Ответить
                  • ахринеть читабельность....

                    а как насчет такой читабельности и почему нормальные компайлеры могут это скомпилисть :)?

                    ```
                    for(const x of [1, 2, 3].all(x => x * 1.5).all(x => x * 2))
                    // print (x)
                    ```
                    Ответить
                    • С точки зрения читабельности - относительно какого-нибудь haskell это на одном уровне с c++.
                      Ответить
                      • В общем-то, для этой конкретной строки что так, что так питушня выходит:
                        for(const x of [1, 2, 3].map(x => x * 1.5).map(x => x * 2))
                          print (x)


                        forM_ (map (*2) . map (*1.5) $ [1..3]) $ \x -> do
                          print x

                        Хотя, в Haskell есть синонимы покороче:
                        forM_ [x*2*1.5 |x <- [1..3]] print
                        Ответить
                        • Нужен Роман, который сократит всю эту вербозную питушню до десятка символов, понятных даже багру.
                          Ответить
                          • 2×1.5×⍳3
                            Ответить

                            • > ⍳
                              Я знаю, я знаю! Это std::iota йота, которая генерирует натуральные числа с единицы! Спасибо крестам за широту кругозора!
                              Ответить
                    • Ну, это всё же сравнение тёплого с мягким. Кресты нам дают полный (в теории) контроль над типами и размещением объектов в памяти. В этом примере с точки зрения языка с такой задачей неясны, например, следующие моменты:
                      1) Что такое «[1, 2, 3]», где оно хранится, какой размер имеет и когда будет уничтожено?
                      2) Где хранятся, какой размер имеют и когда будут уничтожены элементы из списка (если, к примеру, мы хотим так проитерировать по списку строк)?
                      3) Что принимает «all()», где хранится, какой контекст захватывает?
                      4) Что возвращает «all()», где этот объект хранится и когда будет уничтожен?
                      5) Что «возвращает» оператор «of» и где хранится x?

                      Все эти вопросы, кажущиеся несколько надуманными, приобретают смысл тогда, когда нам надо сделать что-то чуть менее тривиальное:
                      1) Сохранить для дальнейшего использования результат вызова «all()» или какой-нибудь из x;
                      2) Получить модифицированную коллекцию и куда-нибудь сохранить;
                      3) Использовать кастомный аллокатор (для тестов памяти, например);
                      4) Не использовать динамическую память вообще, только стек;
                      5) И так далее.

                      Язык с более простой моделью памяти и меньшим контролем над ней самостоятельно решает эти вопросы, при этом:
                      1) Тратит такты на разруливание этих вопросов в рантайме;
                      2) Позволяет изменять стандартное поведение размещения объектов только в жёстких и узких рамках.


                      Короче говоря, все эти конструкции — последствия ебли с памятью. Другое дело, что синтаксис и инструменты крестов для этого — дерьмо, да.
                      Ответить
                      • но все вопросы которые вы написали, могут решать оптимизаторы на стадии начальной прогонки кода до выпуска этого когда в свет и ответить на все ваши вопросы автоматически без участия "кожанных ублюдков". и не тратить лишних "циклов" в рантайме.
                        Ответить
                        • До изобретения сильного ИИ — увы, не могут.
                          Ответить
                          • Да ну, никакого ИИ не надо.

                            1) [1, 2, 3] - компилятор видит что это массив констант численного типа и все они не больше 8 бит (16 или 32). значит он знает что это "const int[]"

                            2) далее компилятор видит что размер масива не такой уж большой и можно его хранить к стэке

                            3) далее компилятор видит что это итерационный тип данных

                            4) далее компилятор видит что Х в лямбдах это типа целого числа

                            а вот и все... никакого ИИ не надо
                            Ответить
                            • А теперь случай посложнее: 255 + 255. Конпелятор видит, что они все не больше 8 бит, значит они uint8_t, а результат будет... Ну ты понял. И здесь пока нет циклов, рекурсии, ссылок и т.п.
                              Ответить
                              • Мне здесь нравится подход жидов (по крайней мере, жсных): скомпилировать, чтобы было быстро, а затем, если вдруг предположения не выполнились - откатиться назад. Хороший инженерный подход. Работает на практике, пока питушки кукарекают про проблемы останова.
                                Ответить
                                • > если вдруг предположения не выполнились
                                  Привет ветвлениям прямо посреди горячего кода. Предсказатель всё-таки не резиновый.
                                  Ответить
                            • …а потом оказывается, что на целевой платформе размер стека сильно ограничен, и в результате рекурсивных вызовов такой «оптимизированной» процедуры у нас раъёбывает стек. Браво, умный компилятор!

                              Нет, это не надуманная проблема: http://www.osronline.com/article.cfm?article=347. Спойлер: за 15 лет ничего не изменилось.

                              И да, «соптимизировать» тривиальный пример можно и на крестах:
                              cout << "3.0\n6.0\n9.000000000003\n";
                              Ответить
                          • У нас есть шанс.
                            Не надо оптимизировать произвольные программы, нам надо оптимизировать только те программы, которые реально написаны и важны. Программы пишутся людьми, которые либо в молодости пишут всякую неважную фигню, которую не надо оптимизировать, либо в старости пишут важный софт, но уже мыслят шаблонами. Человек учится порядка 50 лет, набор его шаблонов ограничен.
                            Соответственно, знатно попердолившись, можно наковырять шаблонов под текущие мышление и моду и создать такие оптимизаторы.

                            Здесь ситуация аналогична парсингу регулярками и управлению АЭС. Людям кажется, что регулярка сама по себе не распарсит грамматику выше регулярной, а АЭС сама по себе сдохнет без ИИ, поэтому не надо их использовать. Но регулярка может запускаться произвольное количество раз программой под машину Тьюринга, а за АЭС постоянно следит несколько живых людей, которые принимают решения.
                            Так и тут, можно не мечтать о сильном ИИ, который будет оптимизировать программы, а посадить лучшие умы, чтобы следили за разработкой оптимизатора.

                            Любителей низкого уровня у нас достаточно, и они будут обеспечены пожизненно почётной и интересной работой метапрограммистов. С появлением нового паттерна мышления или новой моды программирования они будут добавлять их в оптимизатор, который будет всегда работать хорошо, но чуть хуже работы самых передовых умов, что на практике достаточно.
                            Ответить
                        • > показывает код для транспайлера в Js, который держит всё в куче и работает с боксед типами
                          > рассуждает о перфомансе

                          Какие же вы лалки.

                          Самый умный компилятор из тех, что я видел — GHC. Но даже его заставить генерить быстрый код — чёрная магия, передающаяся из уст в уста и сопровождающаяся долгим и томным чтением Коры. А самое смешное, что следующая версия компилятора легко может сломать все твои намёки компилятору, даже если ты сам Брайен О'Салливан.

                          И вот, после долгих ночей ручной настройки прагм, написания рулов оптимизации и тонкой ручной параллелизации ты будешь награждён программой, которая весит всего 2 гигабайта (ИНЛАЙН, детка!) и работает всего лишь в 4 раза медленнее простой крестовой версии.

                          Умные компиляторы — это сильно текущая абстракция. Если хочется предсказать пирфоманс, нужно детально понимать, как они работают, а это зачастую сложнее, чем просто наговнявкать на C++ за полдня.

                          Все ваши рассуждения окончатся тем же, чем когда-то закончилась "автоматическая параллелизация программ". Только наивные простачки верят в эти сказки.

                          >> синтаксис и инструменты крестов для этого

                          синтаксис какой-нибудь растишки не сильно лучше, скорее наоборот.
                          Ответить
                          • >Умные компиляторы — это сильно текущая абстракция
                            По-моему, отличная абстракция. Вся информация, которая нужна для оптимизации, уже есть - исходный код.
                            Другой вопрос - что, конечно, на данном этапе это нереализуемо, но в долгосрочной перспективе веб-макаки, пишушие тормозной говнокод, вносят в развитие этой идеи гораздо больший вклад, чем разработчики с++, которые подсказывают компилятору как компилировать огромным количеством конструкций, отношения к самой логике программы не имеющим. А это - как минимум хороший повод для словоблудия, времени-то у веб-макак за счет быстрого вываливания говна полно.
                            Ответить
                            • > подсказывают компилятору как компилировать огромным количеством конструкций, отношения к самой логике программы не имеющим.

                              У нас наверно 90% программирования в этом стиле.
                              Решить задачу? Нет.
                              * Перевести задачу с человеческого на программистский
                              * Изучить компиляторный язык, библиотеку, фреймворк
                              * Перевести с программистского на компиляторный, объяснить всякую питушню
                              * Смёрджить то, что насрали коллеги.
                              * Написать коммент к коммиту в VCS, отчитаться в баг-трекере и на совещании
                              * Написать документацию (хотя хороший интерфейс - отсутствие интерфейса, хорошая программа - самодокумментирующаяся)
                              * Переписать код, чтобы его лучше поняли коллеги
                              * Переписать документацию, поскольку код изменился
                              * Проверить почту на уведомления от начальства, VCS, баг-трекера
                              * Искать очередной баг
                              Ответить
                              • > хорошая программа - самодокумментирующаяся

                                НЕТ. Документация описывает не ЧТО происходит, она описывает контекст, ПОЧЕМУ это происходит.
                                Ответить
                                • Я бы даже сказал: "НАХУЯ это происходит".
                                  Ответить
                              • Не вижу ничего противоречивого. Деньги люди платят не за код, а за решение их проблем. Если для решения задачи нужно 10 часов совещаний и час кода - то пусть будет так.
                                Другой вопрос - что когда ты садишься за компьютер и начинаешь программировать, ты думаешь не о совещании и интерфейсах, а о том как бы чего лишнего не скопировалось и не просадило тебе performance, ведь уже точно никто не оптимизирует.
                                Ответить
                                • Совещания, интерфейсы, перфоманс напрямую не решают проблему клиента. Решает проблему создание программы.
                                  Совещания, интерфейсы, перфоманс - только палки, которые жизнь вставляет в колёса программостроительной машины. Соответственно, чем быстрее с ними разобраться, тем лучше поедет машина.
                                  Ответить
                                  • > Решает проблему создание программы.
                                    А вот нихуя подобного.
                                    Ответить
                                    • Хорошо, проблему решает запуск программы. Но для этого её надо написать.
                                      Ответить
                                      • > для этого её надо написать
                                        Всё ясно, необратимая деформация сознания.

                                        Написание программы может быть одним из элементов решения (а может и вообще не быть).
                                        Ответить
                                        • Вы так говорите, как будто являетесь хозяином фирмы "муж на час", где решением проблемы может быть как написание программы и прибитие полки, так и написание финансового плана и фрезеровка.

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

                                          Если же в контору, занимающуюся написанием программ приходят затем, чтобы решить проблемы нехватки офисной мебели и компьютеров, то это просто увольняющийся сотрудник под шумок своенравно продаёт казённое имущество.
                                          Ответить
                                          • > конторой, занимающейся созданием программ
                                            А, ты о галере. Ну ок.
                                            Ответить
                                            • Если у нас есть контора общего назначения, то её в каждый момент времени можно разделить на составные части, среди которых будет отдел программистов (быть может с дробным количеством работников), у которого с определённого момента будет стоять задача написать или поддержать программу. В остальное время отдел программистов будет либо отдыхать, либо расформирован (люди будут заниматься другим делом).

                                              И здесь, когда задача программирования уже поставлена, будут совещания, интерфейсы, возня в перфомансом - вынужденная нефункциональная питушня.
                                              Ответить
                                          • Решение о необходимости новой программы в таком случае принимает заказчик у себя, и роль уже целой компании деградирует до простого исполнителя уже решенной проблемы[принятого решения].
                                            Ответить
                                          • Программа в вакууме нахуй никому не нужна. Ей нужно на чём-то работать (обычные компы, смартфоны, микроконтроллеры, серверные стойки, облака и т.п.). Ещё ей может понадобиться интерфейс пользователя (привет дизайнерам и художникам) и протоколы для взаимодействия с другим софтом. Также часто нужны внедрение и техподдержка.

                                            Вся эта хуета в комплексе и будет решать проблему юзера. Да, согласен, многое из этого будут делать другие люди. И многое уже сделано и можно заюзать готовое. Но как минимум подумать об этом всём стоит.
                                            Ответить
                                  • >Совещания, интерфейсы, перфоманс напрямую не решают проблему клиента. Решает проблему создание программы.
                                    Проблему клиента решают манагеры и сейлзы. Роль программиста в этом празднике жизни настолько малозначительна, что его можно выбросить и выкинуть разработку на аутсорс каким-то индусам.
                                    Ответить
                                    • > Проблему клиента решают манагеры и сейлзы.
                                      https://www.youtube.com/watch?v=Y7uKmQS__jc

                                      Я, конечно, согласен, что программисты (как и писари в своё время) получают деньги только за то, что остальной люд тупо не может осуществлять элементарные действия.
                                      Но называть прокладку между клиентом и разработчиком решателем проблем - это сильно.
                                      Я бы отдал звание решателя проблем архитектору. Этот человек действительно делает самое важное, и его хрен заменишь в отличие от заедушных манагеров.
                                      Ответить
                                      • > архитектору
                                        В тред призывается девочка-волшебница архитектор.
                                        Ответить
                                      • У тебя очень, так сказать, разработчикоцентрированная картина мира. С точки зрения бизнеса ценны те кто приносят прибыль. Программист сам по себе прибыль не приносит. Прибыль принесет тот кто впарит (хоть ненаписанный) продукт. В этом плане труд программиста - лишь строчка в расходах, которую бы неплохо оптимизировать.
                                        Сейлз не является прокладкой между клиентом и программистом. Програмист является прокладкой между ненаписанным и готовым продуктом.
                                        Ответить
                                        • У меня материальная картина мира.

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

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

                                          Если будет 90% честных контор и 10% лохотронов, которые делают упор на рекламу, не имеют разработчиков и продают воздух, то отрасль выдержит.
                                          Если будет 10% честных контор и 90% лохотронов, которые делают упор на рекламу, не имеют разработчиков и продают воздух, то никто не будет покупать программы, которые с вероятностью 9/10 представляют собой чистый DVD-R в яркой коробочке.
                                          Просто пока процент честных контор и процент честности велик, и некоторые могут сэкономить на разработке.

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

                                          Основную прибыль приносит не кассир, которому клиент принёс деньги, а те, кто работал над созданием программы напрямую - архитекторы и разработчики.
                                          Все остальные (кассир, техничка, менеджеры, сисадмины, охранники, юристы) - обслуживающий персонал, без которого контора будет работать нестабильно.
                                          Ответить
                                          • Тогда вам, батенька, на броневик.
                                            Чтобы каждый отдавал по способностям и получал по потребностям, и чтобы платили за заебанность.
                                            Ответить
                                            • > на броневик
                                              > чтобы платили за заебанность
                                              Это на загнивающий запад. Вроде там рабочему человеку достойно платят.

                                              Капиталист вполне себе хорошо разруливает подобные ситуации. В долгосрочной перспективе (а) без программистов новые программы не будут продаваться, (б) сложно вырастить новое поколение программистов. Соответственно, ценные программисты вполне могут дать отрасли почувствовать, кто тут приносит деньги и выровнять зарплату за счёт незаменимости.
                                              Правда, для капитализма нужно ещё мыслящее население, которое умеет голосовать рублём и не покупает тонкие стеклянные смартфоны без 3.5мм разъёма и сырые недописанные программы.
                                              Ответить
                                              • >Вроде там рабочему человеку достойно платят
                                                На загнивающем западе благодаря товаrищам платят достойно даже безработным. К капитализму, как понимаешь, это имеет опосредованное отношение
                                                >Капиталист вполне себе хорошо разруливает подобные ситуации
                                                Да капиталист вообще отлично разруливает такие ситуации - выкинет выебщиков и найдет того кто напишет.
                                                То что ты пишешь, конечно, замечательно, но несколько утопично, может даже нереализуемо. Давай лучше остановимся на практике, а на практике вещи сложились таким образом, что место среднего прикладного программиста - у параши.
                                                Ответить
                                                • > платят достойно даже безработным
                                                  > К капитализму, как понимаешь, это имеет опосредованное отношение
                                                  Вообще-то, у каждого молодого капиталиста автоматически обнаруживается соответствующая часть материальных ресурсов страны, которые он автоматически инвестировал и получает дивиденды.
                                                  Если этих дивидендов нет, то значит, что орудуют не капиталисты, а шулеры.

                                                  > Да капиталист вообще отлично разруливает такие ситуации - выкинет выебщиков и найдет того кто напишет.
                                                  Согласен. Заказчик найдёт контору, в которой руководят те, кто разбирается в вопросе. Окажется, что без дармоедов-менеджеров программа будет написана быстрее, качественнее и дешевле.
                                                  Ответить
                            • > По-моему, отличная абстракция. Вся информация, которая нужна для оптимизации, уже есть - исходный код.
                              Это далеко не вся информация. Конпелятору надо как минимум знать:
                              1) Рахитектуру и конфигурацию машины, на которой будет выполняться код (нет, вариант «оптимизируем под то, на чём компилируем» — плохой);
                              2) С какими данными будет работать код: обработка десятимегабайтного файла и, скажем, терабайтного — принципиально разные вещи, различить которые без подсказок компилятор не сможет никак;
                              3) Примерные лимиты использования ресурсов, в первую очередь — памяти (связано с первым пунктом).

                              А ещё у нас есть библиотеки, которые далеко не всегда доступны для включения в проект в виде исходных кодов. А оптимизировать крупную библиотеку для общего случая — так это вообще нереализуемая задача, потому что у компилятора не будет даже всего кода итогового приложения.
                              Ответить
                              • Почему бы все эти проблемы не поручить рантайму? Это в любом случае сводится к вызовам нужных процедур, которые с точки зрения логики программы незначительны, и с которыми умный компилятор не должен ничего делать.
                                Ответить
                                • Потому что без полного знания о предметной области никакой рантайм в общем случае не превратит N^2 в N. Да, он может это сделать для каких-то частных случаев; да, эти частные случаи могут укладываться хоть в 90% вообще всех. Но пока есть шанс, что рантайм проебётся и всё зависнет к херам (а если программист не занимается оптимизацией вообще, даже алгоритмической — как предлагает уважаемый 1024-- — именно так и будет в случае фейла рантайма), я предпочту в меру своих сил оптимизировать код самому.

                                  Впрочем, тут возникает вопрос, кто «умнее» — программист, (обычно) не обладающий высокой теоретической квалификацией, но имеющий представление о предметной области, либо же оптимизатор, с которым всё ровно наоборот. Без подробных статистических исследований вопрос этот — по большей части философский.
                                  Ответить
                                  • Давай еще раз:
                                    N^2 в N - сложность исключительно алгоритмическая, она интересует разработчика.
                                    Допустим в рамках этого N нам надо получать элемент из списка. Можно получать из односвязного списка, а можно из массива. Это вроде как сложность алгоритмическая, но к алгоритму отношения не имеющая, ее вполне решит компилятор.
                                    А архитектура, нужная процедура для обработки терабайтного файла, размер стека - вещи, которые вообще к программе отношения не имеют - их поручим рантайму.
                                    Ответить
                                    • > N^2 в N - сложность исключительно алгоритмическая
                                      Если бы. С точки зрения чистой математики — да, исключительно алгоритмическая. А в реальных компьютерах абстракции текут, и вроде бы линейные алгоритмы совершенно незаметно раздуваются (https://www.joelonsoftware.com/2001/12/11/back-to-basics/ — статье больше 18 лет, а актуальность никуда не делась). Ну вот, к примеру:
                                      function leftpad_1 (str, len, ch) {
                                        var i = -1;
                                        ch || (ch = ' ');
                                        len = len - str.length;
                                        while (++i < len) {
                                          str = ch + str;
                                        }
                                        return str;
                                      }


                                      Добавляем к строке N символов. Абстрактный O(N) алгоритм, превращающийся из-за потёкших абстракций в O(N^2), а потом — как рандом на душу положит. Последняя версия Хромиума, к примеру, успешно сводит его обратно к линейному:
                                      ╔═══════╦═══════════╦═══════════╗
                                      ║       ║ leftpad_1 ║ leftpad_2 ║
                                      ╠═══════╬═══════════╬═══════════╣
                                      ║   100 ║      14.5 ║       1.8 ║
                                      ║ 10000 ║       756 ║       3.4 ║
                                      ╚═══════╩═══════════╩═══════════╝

                                      Это время выполнения одного вызова с 100 и 10000 символами соответственно. Вторая версия взята из текущей версии: https://github.com/stevemao/left-pad/blob/master/index.js.
                                      Да, не квадрат, оптимизатор работает. Только вот всё равно сосёт у ручной оптимизации аж на два порядка — потому что при всей своей крутости (превратил «Шлёмелевские» O(N^2) в O(N)) оптимизатор ниасилил превратить O(N) в O(log2(N)).

                                      А если он не осиливает даже такой максимально тривиальный пример — то как можно говорить о каких-то супероптимизациях массива в бинарное дерево и прочей магии?

                                      Что касается терабайтных файлов — увы, отдать это на откуп рантайму нельзя, потому что они требуют совершенно другого подхода. Магическое автораспараллеливание как было, так и осталось сказкой, а программисты продолжают пердолиться с MapReduce.
                                      Ответить
                                      • Пример нечестный: функция выражена на недостаточно высоком уровне чтобы можно было всю ответственность передать на компилятор.
                                        Да и я оговаривался в начале: все эти рассуждения исключительно умозрительны, можно о них поговорить как о светлом будущем.
                                        >Что касается терабайтных файлов — увы, отдать это на откуп рантайму нельзя, потому что они требуют совершенно другого подхода.
                                        Почему же нельзя? простейшая эвристика: если размер файла превышает столько-то, "подсунуть" под вызов из программы другую процедуру.
                                        Ответить
                                        • > "подсунуть" под вызов из программы другую процедуру

                                          Которая построит датацентр, купит железа, настроит сеть оптимальным образом, а всё расходы оплатит с кредитки разработчика.
                                          Ответить
                                          • У меня на microsoft azure все как-то так и происходит.
                                            Ответить
                                            • > У меня на microsoft azure все как-то так и происходит.

                                              И решение о том, будете вы выполнятся в браузере пользователя/Azure/GCP/AWS принимает V8 в рантайме исходя из результата вызова stat(). Понятно.
                                              Ответить
                                              • Ну да, а в чем сложность-то? С точки зрения рантайма все остается так же: вызвать локальный обработчик или сделать запрос на azure и выдать результат.
                                                Ответить
                                          • > настроит сеть оптимальным образом
                                            А вот эта графовая питушня с весами из подавленности проводов дверьми, глюкавости оборудования, меняющейся со временем загрузки и т.п. уже и правда плохо поддаётся расчётам живыми людьми, пусть её софт оптимизирует.
                                            Ответить
                                        • > Пример нечестный: функция выражена на недостаточно высоком уровне чтобы можно было всю ответственность передать на компилятор.

                                          Тогда можно программирование закрывать. Везде, кроме НИИ и подобных мест, где заказчики сами пишут код, будет нечестный пример.

                                          ТЗ всегда будет выражено на недостаточно высоком уровне чтобы можно было всю ответственность передать на программиста.

                                          Компилятор должен быть телепатом, как и программист.
                                          Ответить
                                          • Речь идет не о ТЗ а об адекватном выражении предметной области. Если стоит задача приклеить пару символов к строке - непонятно причем там какие-то счетчики и циклы.
                                            Ответить
                                        • Тем не менее, весь исходный текст программы у оптимизатора имеется.
                                          Ну а в контексте умозрительных рассуждений так и подавно это всё питушня. ЯП — нинужная прослойка между мешком с мясом (и деньгами) и компьютером. Даёшь ИИ-программиста!

                                          > Почему же нельзя? простейшая эвристика: если размер файла превышает столько-то, "подсунуть" под вызов из программы другую процедуру.
                                          Потому что чтобы «подсунуть» процедуру — эту процедуру кто-то должен напейсать. Если это должен делать программист — то непонятно, зачем вообще городить рантайм, когда можно обойтись банальным «if file.size > 1000000 { drugaya_procedura(); }». А если она должна генерироваться автоматически — то мы возвращаемся к компиляторам и умным оптимизаторам, которые должны будут предусмотреть все возможные варианты файлов — и маленькие, и большие, и зожатые, и sparse, и с высокой энтропией, и лежащие на дискетах, и на удалённых дисках… Почему все возможные варианты? А потому что компилятор имеет доступ только к исходному коду. Он не знает, зачем этот код нужен. А программист знает, что обработка зожатых удалённых файлов ему по ТЗ не нужна — и может оптимизировать только те кейсы, которые ему по этому ТЗ нужны.
                                          Ответить
                                      • > оптимизатор ниасилил превратить O(N) в O(log2(N))
                                        O(log2(N)) - какая-то питушня. Если строка - массив символов, лежащих в одном куске памяти, то даже программист не может сделать O(log2(N)), т.к. самый простой алгоритм будет либо дописывать N нулей, либо двигать len(str) символов.

                                        O(log2(N)) достигается только сменой контейнера. Бинарное дерево, хранящее ветви по ссылке, может с этим справиться, делая что-то вида
                                        p2 = pair(' ', ' ')
                                        p4 = pair(p2, p2)
                                        p8 = pair(p4, p4)
                                        p16 = pair(p8, p8)
                                        p21 = pair(p16, pair(p4, ' '))
                                        return pair(p21, string);


                                        Но это на стороне программистов означает либо смену контейнера, либо смену языка, а на стороне оптимизатора - подстановку этого контейнера. Странно, если бы программист в рамках недеревянного JS String добился бы O(log2(N)) сам.
                                        Ответить
                                        • Точно, это я ёбу дал. Но с leftpad2 всё равно получается какая-то питушня:
                                          var times = []
                                          for (let chars = 1000; chars <= 100000; chars += 100) {
                                              var t0 = performance.now();
                                              for (let i = 0; i < 100000; i++) {
                                                  leftpad_2('hello', chars, '*');
                                              }
                                              var t1 = performance.now();
                                              times.push(t1 - t0);
                                          }

                                          …даёт в итоге [25, 20, 20, 16, 16, 18, 17, 18, 15, 17, 17, 17, 17, 20, 18, 18, 16, 19, 20, …, 19, 20, 21, 21, 20, 20, 21, 22, 19, 20, 20, 22, 21, 21, 22] (округлено до целого). Видимо, оптимизатор как раз во что-то такое древоподобное и оптимизировал.
                                          Но в любом случае, вручную оптимизированный пример наивной реализации даёт пососать.
                                          Ответить
                                          • А это оптимизатор увидел, что Вы монаду IO забросили, результат не используете. Вот и сделал то, что смог. Хотя, довольно таки странно, что эта питушня растёт логарифмически. Это оптимизатор обосрался и не смог вытянуть константу.

                                            Потому, что с точки зрения математики любой невыведенный результат считается за O(1).

                                            Попробуйте, константа USE_IO_MONAD_FOR_RESULT переключает сложность алгоритма с O(logN) до O(N):
                                            const {performance} = require('perf_hooks');
                                            const leftpad = require('left-pad');
                                            
                                            var times = [];
                                            var word = '';
                                            
                                            const USE_IO_MONAD_FOR_RESULT = false;
                                            
                                            for(let chars = 1; chars < 1e8; chars *= 2) {
                                              let t = 0, t2 = 0, N=10, N1 = USE_IO_MONAD_FOR_RESULT ? 10 : 10000;
                                              for(let n=0; n<N; n++) {
                                                var t0 = performance.now();
                                                for (let i = 0; i < N1; i++) {
                                                    if(USE_IO_MONAD_FOR_RESULT) {
                                                      word += leftpad('hello', chars, '*')[0];
                                                    } else {
                                                      word += ' '; leftpad('hello', chars, '*');
                                                    }
                                                }
                                                var dt = (performance.now() - t0) / N1;
                                                
                                                t += dt;
                                                t2 += dt * dt;
                                              }
                                              // console.log(chars, t/N);
                                              console.log(chars, t/N, Math.sqrt(t2/N - t*t/N/N)); // вывод с оценкой ошибки
                                            }
                                            
                                            console.log(word.split('').reduce((x,y)=>x+y.charCodeAt(0), 0));


                                            Если константу включить, из строки сохраняется один символ для последующего использования (я хотел брать случайный, но оптимизатор в Node.js 11.6.0 не настолько хорош, поэтому уже с нулевым начинает тормозить). Если выключить - сохраняется пробел - чисто для симметрии, чтобы никто не говорил, что это += тормозит.

                                            Для случая с взведённой константой я уменьшил количество вызовов leftpad, но это компенсируется тем, что печатается результат для одного вызова.
                                            Ответить
                                            • P.S. Последнюю строчку с монадой IO можно и убрать. Оптимизатор в Node.js 11.6.0 считает взятие нулевого символа достаточным для линейности алгоритма!
                                              Ответить
                                            • Хм, меня смущает то, что в случае с неоптимизированным leftpad_1 там всё же получается что-то вроде линейного роста (даже скорее N*log(N), но шума много, трудно понять):
                                              var times = []
                                              for (let chars = 100; chars <= 10000; chars += 100) {
                                                  var t0 = performance.now();
                                                  for (let i = 0; i < 10000; i++) {
                                                      leftpad_1('hello', chars, '*');
                                                  }
                                                  var t1 = performance.now();
                                                  times.push(t1 - t0);
                                              }

                                              [18, 17, 24, 24, 26, 31, 37, 39, 44, 52, 60, 64, 72, 77, 70, 82, 88, 91, 87, 93, 96, 100, 106, 107, 113, 118, 119, 134, 131, 144, 144, 165, 188, 179, 183, 180, 185, 194, 178, 193, 221, 210, 187, 204, 222, 209, 227, 224, 224, 237, 231, 235, 242, 263, 265, 262, 271, 296, 313, 311, 322, 289, 328, 317, 335, 292, 311, 375, 362, 352, 349, 351, 372, 391, 408, 392, 394, 423, 421, 394, 439, 477, 405, 451, 437, 485, 493, 506, 503, 460, 482, 431, 473, 495, 494, 553, 498, 504, 486, 573]
                                              Ответить
                                              • Интересно. И оптимизатор не меняет трудоёмкость, не важно, используем мы результат или нет.
                                                Хотя, у меня leftpad_1 даёт результат, который больше на O(N) похож.
                                                Ответить
                                                • А существуют ли инструменты, позволяющие просмотреть, во что там движок наJITил наш код? Это бы многое прояснило.
                                                  Ответить
                                                  • Дам я тебе такой инструмент. Он напоминает телескоп: складывается-удлиняется, и глазок есть.
                                                    Ответить
                                                  • Кстати, кто-то раньше тоже об этом спрашивал и рекламировал питон, где это есть. А я с тех пор так ответ и не узнал.
                                                    Ответить
                                                  • > инструменты
                                                    Пишут, что D8 должен уметь.
                                                    Ответить
                                              • > даже скорее N*log(N)

                                                Ну так строки в ЖС вроде как раз как деревья местами реализованы. Мы это как-то обсуждали уже почти 3 года назад

                                                http://govnokod.ru/19692
                                                Ответить
                                                • Да уж, как время-то быстро летит…
                                                  Ответить
                                    • …и ещё: такой умный рантайм в условиях ограниченности ресурсов (я выше привёл ссылку) просто не заведётся.
                                      Ответить
                                      • Будем надеяться, что в светлом будущем даже открывалка ворот на удаленном управлении будет иметь достаточно мощное железо под минимально небоходимый для ее нужд рантайм.
                                        Ответить
                                        • Открывалка будет, а драйвер — вряд ли.
                                          Ответить
                                          • Чайники точно будут. Тогда можно сэкономить на нагревательном элементе.
                                            Ответить
                          • > Только наивные простачки верят в эти сказки.
                            Мне кажется, программы, оптимизированные JSными движками, работают быстрей, чем программы на языках с ручной памятью, оптимизированные веб-программистами. И стоят дешевле, и писать их легче.

                            > И вот, после долгих ночей ручной настройки прагм, написания рулов оптимизации и тонкой ручной параллелизации ты будешь награждён программой, которая весит всего 2 гигабайта (ИНЛАЙН, детка!) и работает всего лишь в 4 раза медленнее простой крестовой версии.
                            Мясные программисты тоже ошибаются.

                            Чукче не надо бежать быстрее медведя, чукче надо бежать быстрее геолога.
                            Ответить
                            • > И стоят дешевле, и писать их легче.
                              А самое главное - они работают. В отличие от "программ на языках с ручной памятью, оптимизированных веб-программистами".
                              Ответить
                            • Все существующие ЯП — говно.

                              «Компьютерная программа» сейчас — это по сути руководство, по которому компьютер проводит какие-то вычисления и получает какой-то результат. Императивные, декларативные, функциональные, объектно-ориентированные программы — все они в конечном дают процессору какие-то указания, которые он должен выполнить. Проблема же состоит в том, что для божественной оптимизации недостаточно сказать «возьми вот этот массив и сделай с ним вон ту операцию». Чтобы оптимизировать код, компилятор должен понимать, для чего этот код нужен, и что он в конечном будет делать. Не «обрабатывать массив чисел с плавающей точкой», а «подсчитывать медиану цен на акции Apple». Не «рисовать окошко с красным цветом», а «информировать пользователя, что он неправильно ввёл пароль».

                              Никакие современные языки программирования общего назначения не дают возможности указать компилятору, что хочет заказчик. Даже в супер-мега-овер-высокоуровневом «JS» программисты всё равно сношаются с какими-то текущими абстракциями — числами, строками, массивами, хэш-таблицами, списками, функциями, коллбэками, промисами, запросами и прочей хренью. В «PHP» ничего из этого нет, поэтому я за «PHP». Современные ЯП общего назначения не имеют возможностей выражения задачи в терминах предметной области. Поэтому «идеального компилятора» нет и не будет — пока не сменится сам подход к написанию программ (и, разумеется, языки).

                              Собственно, решений это проблемы — целых три:
                              1) Развивать DSL'и (гораздо глубже, чем есть сейчас). В результате получим очень много компиляторов разных языков, которые божественно компилируют крайне простые и многофункциональные программы — но только в своей, крайне узкой области.
                              2) Налегать на ИИ и развивать язык программирования, на котором можно будет действительно объяснить компьютеру, что мы хотим сделать.
                              Ответить
                            • 3) Ничего не делать. Будем продолжать пердолиться с указателями, раздражаться от аппетитов «Электрона» и холиварить о необходимости пердолинга с указателями.
                              Ответить
                              • Отличная статья. Всё чётко и по делу.
                                Хотя, вместо (1) и (2) я бы предложил развивать ИИ, который будет понимать естественный язык, поскольку у нас уже сейчас происходит минимум один перевод с языка на язык до процесса программирования - в момент, когда заказчик объясняет задачу исполнителю. Если же заказчик и исполнитель комплексные (группы людей), дополнительные переводы возникают внутри заказчика и исполнителя. Если ещё всё происходит в межнациональных конторах, то перевод осуществляется не на уровне описания идей, но и с формального языка на формальный, а то и два раза - со своего на английский и обратно.
                                Формальный программистский язык для ИИ - такое же говно, как и формальный английский язык для межнационального сообщества - вынужденное говно, на котором сливается лишняя доля смысла.
                                Ответить
                                • Да, пожалуй, предельный случай (2) — это ИИ, понимающий естественный язык. Собственно, подразумевал я как раз разработку естественного языка для ИИ, но, пожалуй, такая прослойка таки не нужна.
                                  Ответить
                          • > синтаксис какой-нибудь растишки не сильно лучше, скорее наоборот.
                            Есть божественный «Си» с божественным синтаксисом (кроме синтаксиса указателей на указатели на подпрограммы, принимающие указатели, это всё первородный грех). Все остальные попытки создать «Си, только чтобы модно-стильно-молодёжно» пока что закончились либо пшиком, либо крестами (синтаксис Ржавого входит в последнюю категорию).
                            Ответить
                            • > пшиком

                              У меня были большие надежды на http://claylabs.com/clay/
                              Жаль, что он сдулся.
                              Ответить
    • https://ru.wikipedia.org/wiki/Обыкновенный_крестовик
      Кхм.
      Ответить
      • Не следует путать с обыкновенным крестовником — видом растений.
        Ответить

    Добавить комментарий