1. Java / Говнокод #19136

    −37

    1. 1
    List<Tuple4<Bayes, Bayes, Bayes, Bayes>> bayesResult = new ArrayList<>();

    http://stackoverflow.com/questions/29970164/reuse-results-of-first-computation-in-second-computation

    Запостил: someone, 04 Декабря 2015

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

    • Ехал Байес через Байес.
      Ответить
    • Туплы нинужны. Только запутывают код.
      Ответить
      • ну а зачем пилить велосипед если нужно вернуть 2 значения из функции? (хотя, если честно, все равно хочется запилить или класс/структуру или побочный эффект воткнуть)

        Конечно в данном случае тут пиздец под названием говноархитектура
        Ответить
        • > вернуть 2 значения из функции
          Приведи пример.
          Ответить
          • Да я гипотетически...
            Ответить
          • Это же элементарно: значение и ошибка.

            У нас столько всяких функций вида fgetpos, которые возвращают некоторые свои аргументы через указатели, а можно было бы и явно.

            И ещё любой код, в котором есть распаковка-запаковка
            point = getPoint();
            print('My point: ', point.x, point.y, point.z);
            setPoint(new Point(point.x, point.y, 42));

            -- искусственное говно, которое породили из-за отсутствия возможности вернуть несколько значений.
            (x, y, z) = getPoint();
            print('My point: ', x, y, z);
            setPoint(x, y, 42);
            Ответить
            • в go например есть возможность вернуть несколько значений и то активно используют структуры для возвращаемых значений.
              это искусственное говно point.x, point.y, point.z гораздо удобней чем все x1 y1 z1 вместе взятые.
              Ответить
              • > это искусственное говно point.x, point.y, point.z гораздо удобней чем все x1 y1 z1 вместе взятые.
                Мы рассматриваем только вырожденные случаи. Т.е. я предъявляю пример того, как кто-то активно работает с координатами в векторе, а мой виртуальный оппонент - пример того, как он реализовал алгоритм, использующий линейную алгебру. Мне удобно с множеством значений, ему - с объектами.
                А может понадобиться и то, и другое. Нужна какая-то разворачивалка объектов:
                Point add(Point as (float x, float y, float z)) {
                  return this.x + x, this.y + y, this.z + z;
                }
                
                Point sub(Point p) {
                  return this.add(p.inverse());
                }
                
                r.add(r0);
                r.add(0.0, 0.0, 1.0);
                r.sub(r0);
                r.sub(0.0, 0.0, 1.0);

                (Только как быть с рекурсивными типами?)
                Ответить
                • > Point as (float x, float y, float z)
                  Ты только что изобрёл паттерн-матчинг. В хаскеле и прочей функциональщине он примерно так и работает. Да, для любых ADT (структур), а не только унылых туплов, которые являются всего лишь частным случаем ADT.

                  А с рекурсивными типами расправляются... рекурсией. Один-два слоя снимаешь паттерн-матчингом, а дальше рекурсивный вызов.
                  Ответить
                  • > паттерн-матчинг. В хаскеле и прочей функциональщине
                    Но он там "односторонний" - только в сигнатуре функции же?
                    x0 + (0, 0, z) в хаскеле и товарищах получится сделать? (где (+) :: Point -> Point -> Point)
                    Ответить
                    • > x0 + (0, 0, z)
                      Я не пойму, чем тебя x0 + Point(0, 0, z) не устраивает. Явный конструктор влом написать?
                      Ответить
                      • > Явный конструктор влом написать?
                        Да. Выходит как-то громоздко. Особенно, если структура сложная. Особенно, если ещё и new надо писать.

                        setTransformation((0, 1, 0), (1, 1, 1), (2, 0, 0));
                        
                        setTransformation(new Matrix(
                          new MatrixRow(0, 1, 0),
                          new MatrixRow(1, 1, 1),
                          new MatrixRow(2, 0, 0)
                        ));

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

                        Кстати, в JS new можно не писать, из-за чего можно ещё и ошибиться, описывая все эти new Point.
                        Ответить
                        • > если структура сложная
                          То полагаться на порядок полей в ней как-то страшно.
                          Ответить
                          • Да не структура, а структура!
                            Я про структуру выражения, которое формируется для описания объекта.
                            А для сложных структур поможет наверно только JSON-подобная запись.

                            Кстати, для однородности и простоты парсинга имя класса (опциональное, но иногда нужное для однозначности) можно писать внутри скобок:
                            m + (Matrix: v1, v2, v3) + ((Vector: v1), (0, 0, 2), {Vector: x=3, y=4, z=5})
                            Ответить
                            • Ну тем более. Тут с явными конструкторами то сложно понять, а с неявными - вообще черт ногу сломит, пока разберётся, во что превращается каждый из туплов...
                              Ответить
                    • Интересно, а сработает ли implicit конструктор с std::initializer_list в крестах, если написать p + {0, 0, z}?
                      Ответить
                      • У меня не выходит http://ideone.com/HLvOff - только при явном вызове оператора по имени (хотя, я мог что-то не учесть).

                        Вот бы можно было переопределить скобки и операторы:
                        #define * .operator+
                        #define ( ({
                        #define ) })
                        // тогда почти всё было бы почти красиво:
                        std::cout << p * (1,0) << std::endl;
                        Ответить
            • > значение и ошибка
              optional, maybe, either, исключение в конце-концов. Но никак не тупл, в котором хуй поймёшь, где ошибка, а где значение...
              Ответить
              • > хуй поймёшь, где ошибка, а где значение
                Как будто что-то плохое...
                Зато будет стимул документировать и возвращать какие-то разумные значения при ошибке, которые в некоторых случаях даже можно игнорировать.
                Например, 0/NaN для sqrt(-1) и null для openFile.
                Ответить
            • > искусственное говно
              Угу. Потому что по-хорошему для подобного отладочного вывода у Point'а будет toString() или operator <<. И тебе не понадобится 100500 раз изобретать вывод Point'а.
              Ответить
              • P.S. И даже в сишке с её принтфом можно сделать что-то типа
                #define POINT_FORMAT "Point(%d, %d, %d)"
                #define POINT_EXPAND(p) (p).x, (p).y, (p).z
                
                printf("My point is " POINT_FORMAT "\n", POINT_EXPAND(point));
                если не хочется временные буфера заводить, а точки выводятся в лог 100500 раз.
                Ответить
                • Распечатывание - действие "однородное" (однотипное/одиночное/можно заскриптовать один раз), но мы можем работать на рубеже абстракций (http://govnokod.ru/19136#comment308569), там уже сложно или невозможно найти удобный способ.
                  Это может быть как при создании класса:
                  1.1. a+b = (a.x+b.x, a.y+b.y) -- объект как набор полей при создании "атомарных" методов;
                  1.2. a-b = a + inv(b) -- объект как целое при компоновке существующих методов,
                  так и при использовании:
                  2.1. Point(x, y) -- объект как набор полей при конструировании;
                  2.2. x0 + Point(matrix[0][0], matrix[0][1]) или x + (0, 0, z) -- объект как набор полей при комбинировании разнотипных сущностей (сущностей из разных библиотек);
                  2.3. x + x0 -- объект как целое при работе с однотипными сущностями
                  Ответить
      • нужны хотя бы потому, что для них в Control.Arrow есть комбинаторы на все случаи жизни
        Ответить
        • Имхо, лучше бы дали возможность объявить любую структуру инстансом какого-нибудь тайпкласса Tuple...
          Ответить
          • для этого есть линзы, но они на неподоготовленного человека действуют как J и brainfuck вместе взятые
            Ответить

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