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

    +5

    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
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    // 600+ lines skipped
    
    int main() {
      window["console"] = console;
      window["Math"] = Math;
      Math["sin"] = Math.sin;
      Math["cos"] = Math.cos;
      Math["PI"] = Math.PI;
     
      // EXAMPLE:
     
      var x = 3;
      var y = x + null;
      var z = "hello, " + y;
      var n = NaN << NaN;
      var f = Function();
     
      console.log("x = " + x + " y = " + y + " z = " + z);
      console.log("x =", x,"y =", y, "z =", z);
      console.log(String("222") + true);
      console.log(String("222") + 3);
      console.log(Number("222") + 3);
      console.log(NaN << NaN, !NaN);
      console.log(undefined + 1);
      console.log(f("hello, ", "world"));
      console.log("sin(pi/4) = ", Math.sin(Math["PI"] / 4));
      console.log("sin(pi/4) = ", window["Math"]["sin"](Math["PI"] / 4));
    }

    Я поехал вслед за gost'ом (см. http://govnokod.ru/23440)
    Читать далее: https://ideone.com/mLM4yN

    Рахитектура:

                  <|- Number
    <|- String
    <|- Boolean
    <|- Function
    Object = var <|- Console <- +
    | |
    | <|- Window - - + ref
    | |ref
    | v
    | <|- Math - - - - -
    | |
    | |
    | |
    | ptr | value
    | |
    | <|- ObjectBody |
    | <|- NumberBody |
    v <|- StringBody |
    BaseBody <|- BoolBody |
    <|- NullBody |
    <|- UndefinedBody |
    v
    <|- FunctionBody <|- SinBody
    <|- CosBody


    Object null, undefined, NaN, Infinity;
    Math Math;
    Window window;
    Console console;

    Запостил: 1024--, 22 Октября 2017

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

    • Я поехал вслед за gost'ом.
      console["log"]("sin(pi/4) = ", window["Math"]["sin"](Math.PI / 4)); // C++

      * Диаграмма классов чуть изменилась, т.к. я канонично переписал console.log, добавив связи Console - - > ConsoleLogBody -|> FunctionBody.
      Ответить
    • Браво, маэстро!
      Ответить
    • Сделал лифт функций от (Object...) в объекты JS https://ideone.com/MEL0Ot, переписал через них Math.sin, Math.cos
      Распечатал семёрку им. Чёрча (как 2*(2+2)-1):
      console.log("7 is", unary([](var n){return unary([n](var f){return unary([n,f](
      var x){return n(unary([f,x](var g){return unary([f,g,x](var h){return h(g(f));}
      );}))(unary([x](var u){return x;}))(unary([](var u){return u;}));});});})(unary
      ([](var m){return unary([m](var n){return unary([m,n](var f){return m(n(f));});
      });})(unary([](var n){return unary([n](var f){return unary([n,f](var x){return
      f(n(f)(x));});});})(unary([](var n){return unary([n](var f){return unary([n,f](
      var x){return f(n(f)(x));});});})(unary([](var f){return unary([f](var x){return
      x;});}))))(unary([](var m){return unary([m](var n){return m(unary([](var n){
      return unary([n](var f){return unary([n,f](var x){return f(n(f)(x));});});}))(n)
      ;});})(unary([](var n){return unary([n](var f){return unary([n,f](var x){return
      f(n(f)(x));});});})(unary([](var n){return unary([n](var f){return unary([n,f]
      (var x){return f(n(f)(x));});});})(unary([](var f){return unary([f](var x){
      return x;});}))))(unary([](var n){return unary([n](var f){return unary([n,f](var
      x){return f(n(f)(x));});});})(unary([](var n){return unary([n](var f){return
      unary([n,f](var x){return f(n(f)(x));});});})(unary([](var f){return unary([f](
      var x){return x;});}))))))(unary([](var x){return x+1;}))(0));


      Кто-нибудь может сказать, как произвольную лямбду скастить в std::function? static_cast<std::function<конкретный тип>>(лямбда) мне помогает только для конкретной лямбды, не могу зашаблонить это.
      Ответить
      • тебе что конкретно надо? Если вывести Type в std::function<Type>, можешь не заморачиваясь писать (с++17) std::function f = [...](...) {...}. С поправкой на то, что тогда в аргументах лямбды нельзя использовать auto.

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

        п.с. ты какой-то херотой маешься. Делай объект через std::variant и обертки, натравливающие визиторов.
        Ответить
        • > тебе что конкретно надо?
          Чтобы конструктор Object работал от лямбд, и все функции и функциональные объекты обрабатывались эквивалентным образом.
          var sum([](var x, var y){ return x + y; });
          var id([](var x){ return x; });
          console.log(sum(id(2), 2));


          > Делай объект через std::variant и обертки, натравливающие визиторов.
          Запишу как план на будущее, когда снова C++ ударит в голову.
          Ответить
          • нехило так тебя накрыло однако. Готовься, ща докину (выкладки, дальше думай сам):
            1. делаем перегрузку конструктора по Callable. Без концептов получим больше шаблонной магии, но тоже можно
            2. преобразуем все функции в any(any) или var(any). Преобразуем таким образом: собираем аргументы функции в std::tuple через std::decay (типа int &a, double &&b) -> tuple<int,double>. Оборачиваем искомую функцию лямбдой, вызывающей родную функцию через std::invoke, и возвращающую var/any.
            3. Соответственно, оператор () нашего callable объекта будет комбинировать агрументы в decay-нутый тапл, и подсовывать в обернутую функцию в виде std::any. При несовпадении сигнатуры будет исключение. И std::forward не забывай, чтоб лишние копирования убрать.
            4. При таком подходе в лоб, будет несовпадение сигнатуры при попытке передать, например, int вместо unsigned. Поэтому можно сделать еще уровень индирекции, засовывающий конвертируемые в var типы в виде var.
            Ответить
        • Нафиг вообще нужен паттерн visitor?
          Ответить
          • Костыль для языков где нету multi dispatch.
            Ответить
            • показать все, что скрытоvanished
              Ответить
              • Кстати для крестов есть предложение для выбора метода по типу нескольких аргументов. Вроде даже довольно эффективное, с построением табличек в компайлтайме. Может быть и затащат году так в 30м...
                Ответить
            • То есть для ситуаций, когда нужно поработать с хрен знает какими типами?
              Ответить
              • Для диспатча по джвум и более аргументам (унылые виртуальные методы осиливают только один).
                Ответить
                • Понятнее не стало, если честно :-) но это, наверное, потому что мне такая шняга не нужна была никогда
                  Ответить
                • Хотя, наверное, допетрил: в ваших же крестах да жабах нельзя существующие классы законформить к новым интерфейсам или к абстрактным классам. То ли дело Свифт
                  Ответить
                  • показать все, что скрытоvanished
                    Ответить
                    • Да, я уже понял.

                      Просто в нормальных™ языках можно написать
                      extension HuiPizda: Dzhigurdable
                      и заиметь нужные типы в нужном месте. Ну ты сам знаешь, в принципе
                      Ответить
                      • Суть не в типах, суть в выборе метода по типу *джвух* аргументов...

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

                        К сожалению большинство языков диспатчит только по типу первого аргумента (аля this/self), вот и приходится городить этих ебучих визиторов.
                        Ответить
                        • показать все, что скрытоvanished
                          Ответить
                          • >> acceptPetuh()
                            >> acceptBird()
                            - один я здесь вижу протёкшие абстракции? Ну, впрочем, мы же говорим про расширение функциональности существующего кода, так что пиздец ожидаем в том или ином виде.

                            NB: В терминах Obj C я не вызываю метод, а отправляю сообщение, с которым потом можно делать всякие штуки типа forwardInvocation.
                            Ответить
                      • З.Ы. Хотя я понял твою мысль. Обмазать нужные классы в Drawable и Savable с соответствующими реализациями. Вроде тоже норм.
                        Ответить
              • показать все, что скрытоvanished
                Ответить
          • показать все, что скрытоvanished
            Ответить
    • лол
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • > Я поехал вслед за gost'ом

      Я давно заметил.
      Ответить

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