1. PHP / Говнокод #23894

    −1

    1. 1
    2. 2
    - $pending = $this->$tag['callback']($open['data'], $open['option']);
    + $pending = $this->{$tag['callback']}($open['data'], $open['option']);

    Копаюсь в сорцах говнокода.
    В PHP 7 поменяли приоритет, пол часа не мог понять что за хуйня.

    Запостил: inho, 08 Марта 2018

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

    • Какой же всё таки пиздопротивный синтаксис у пыха.
      Ку вот зачем тут стрелочка? this может быть не указателем? Точечка вообще существует?
      Зачем тут ДВА доллара: $this->$tag ?

      Почему все юзают дикты? Потому что нет лёгкого способа описать объект как в JS (где хеш есть объект) или как OpenStruct в Ruby?
      Тогда почему не разрешить нормальный синтаксис через точку?

      Семантический мусор же.
      //говно
      $this->$tag['callback']($open['data'], $open['option']);
      
      //менее говно
      this.tag.callback(open.data, open.option)
      Ответить
      • // менее говно
        this[tag.callback](open.data, open.option)

        /fixed
        Ответить
        • почему?
          Ответить
          • почему - вопрос к создателям пыхи

            PHP7 -> JS:
            $a->$b['c']
            a.b.c


            PHP5 -> JS:
            $a->$b['c']
            a[b.c]


            (ЕМНИП)
            Ответить
            • пзц, в своем-же синтаксисе запуталисб
              Ответить
              • С учётом этого и сказанного вистефаном ниже, значит, в PHP есть возможность писать что-то вида
                $a->$b['c']
                $a->${b['c']}
                $a->{$b}['c']
                $a->{$b['c']}
                {$a->$b}['c']

                А потом пердолить этим людей не хуже, чем сишным int *a[10] vs int (*p)[].
                Ответить
            • А вот давайте обсудим, кстати.

              Я считаю что разделять структуры/записи (ну классы без методов) и дикты (они же мэпы они же хеши они же ассоциативные массивы) в ЯПах без обязательной стат типизации смысла нет, то-есть в JS сделано правильно.

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

              В результате получается и так и сяк.

              Q: что лучше: $petushok['age'] или $petushok->age?
              A: ахуйегознает
              Ответить
              • >Старый жабист говорит:
                >в рантайме узнаешь если ошибся

                Не-не-не, жабисты так точно не говорят.Только те что на спринг expression-language пишут.

                > то-есть в JS сделано правильно

                Вот. Но не совсем.
                1024-- как-то говорил что еще кошернее и в духе доброго похуистичного js, было бы сделать чтоб цепочки свойств не падали.
                user['pituh']['age'] //undefined, если питуха нет
                Ответить
                • ну жабист скажет что упасть в рантайме лучше, чем получить ничего:) а еще будет комплишен в IDE

                  в ObjC (и думаю что в swift) вызов метода у nil (посылка месседжа nil) всегда приводит к возвращению nil, так что можно делать длиные цепочки первый вызов из которых вернет nil, и все будет ок

                  В котлине тоже так можно.
                  Жаба:

                  Petuh p = user.getPetuh();
                  if (p != null) {
                  Kurochka k = p.kurochka;
                  if (k != null){..}
                  }

                  котлин

                  val k = user?.petuh?.kurochka
                  Ответить
                  • порт на хачкель
                    k = user >>= petuh >>= kurochka
                    Ответить
                  • В Swift это называется Optional chaining
                    Ответить
                    • Они сделали Maybe частью синтаксиса. \~////
                      Ответить
                      • и котлин тоже, только вместо Maybe там вопросик
                        Ответить
                  • Знаю-знаю, про то что в котлине такой сахарок есть.

                    С одной стороны достаточно полезно было бы иметь, с другой в мерзком ECMA-2015 можно запилить
                    Думаю и в js можно через proxy добиться такого поведения.

                    function npe(t){
                        var empty=wow({   });
                        function wow(x) {
                    		return new Proxy(x, { get: function(target, name) {
                    			return (x[name]!=null) ?
                    				x[name] : name=='toString' ?()=> {333}
                    				:empty;
                    			}
                    		});
                        }
                    
                        return wow(t);
                    }
                    //
                    x=npe({a:1,b:22})
                    
                    console.log(x.a) // 1
                    console.log(x.b) // 22
                    console.log(x.user.petuh.kurochka) //внезапно ошибки нет!
                    Ответить
              • > Я считаю что разделять структуры/записи (ну классы без методов) и дикты (они же мэпы они же хеши они же ассоциативные массивы) в ЯПах без обязательной стат типизации смысла нет, то-есть в JS сделано правильно.

                ты походу не дебажил случаи, когда у тебя один из этих параметров в конце длинной цепочки преобразований почему-то undefined, а посередине сплошное жонглирование с Object.keys и прочим весельем
                Ответить
                • Дык классы в таких языках один фиг не фиксируют список полей. В любой момент какая-нибудь макака может досыпать новых, если ей это хочется. Или засунуть в поле что-то левое. В итоге ситуация не особо отличается от хешмапы. Если всё и так держится на неявных контрактах — зачем усложнять язык?

                  Так что я тут согласен с SemaReal.
                  Ответить
              • > Q: что лучше: $petushok['age'] или $petushok->age?
                A: (:age petushok)
                Ответить
              • > Я считаю что разделять структуры/записи (ну классы без методов) и дикты (они же мэпы они же хеши они же ассоциативные массивы) в ЯПах без обязательной стат типизации смысла нет, то-есть в JS сделано правильно.

                В JS сделано отчасти хорошо (читай: плохо).
                Хорошо сделано в Lua, где есть метатаблицы, из-за которых можно отличить, где у тебя в ассоциативном массиве лежит ключ (данные), а где - его поле или метод.

                Иначе общение с ассоциативным массивом превращается в пердолинг. Если кто-то добавил в Object.prototype что-то полезное (те же полифиллы), in для всех ассоциотивных питухов уже будет срабатывать на это полезное. На hasOwnProperty рассчитывать нельзя, т.к. его могли добавить как ключ. Брать hasOwnProperty надо из другого, чистого объекта. И прочая питушня. В старых версиях языка наверно легче было к каждому ключу добавлять префикс, с которого с большой вероятностью не будут начинаться поля и методы. Сейчас в JS встроили специально написанные мапы, но их просто так не задашь литералом.
                Ответить
                • В фитоне все магические методы окружили магическими __ __, чтобы случайно имя не занять.
                  Ответить
                  • >>> d = dict()
                    >>> d['values'] = 1
                    >>> d.values()
                    dict_values([1]) # не ошибка вызова и не 1

                    Тут и без __ __ всё работает. В JS бы в аналогичном примере была ошибка вызова числа как функции.
                    Ответить
                    • >В JS бы в аналогичном примере была ошибка вызова числа как функции.
                      Не понял
                      Ответить
                      • Что непонятного? Число "1" бы вызвали как функцию.
                        > var x = {};
                        undefined
                        > x.hasOwnProperty('aaa')
                        false
                        > x['hasOwnProperty'] = 1;
                        1
                        > x.hasOwnProperty('aaa')
                        Uncaught TypeError: x.hasOwnProperty is not a function
                        Ответить
                        • Потому что ты перезаписал метод hasOwnProperty!

                          В питоне тоже случается как за нехуй.
                          class Gidripidaras():
                              def __init__(self, login, passwd):
                                  self.login = login
                              def login():


                          Вылетит при вызове obj.login() догадайся почему
                          Ответить
                          • Тут метаданные переписали метаданные. В нормальном коде такое возможно только если программист ошибся.
                            В моём примере данные переписали метаданные. В нормальном коде такое возможно, если в пользовательском вводе встретилась подходящая питушня.
                            Ответить
                            • Ты хочешь иметь два неймспейса, для элементов и для методов? Можно было сделать как в питоне с __ __ и запрещать присваивать их
                              Ответить
                              • Наверно нет, т.к. тогда накроется красивая эквивалентность a['b'] и a.b, и надо будет думать, куда и что положить.
                                Запрещать присваивать что-то в динамическом массиве - тоже не вариант, пользователь имеет полное право вставить __питушню__, невставка __питушни__ будет эквивалентна вставке питушни, перетирающей поля и методы: проверять всё равно придётся.
                                А вот подход Lua - наверно то, что нужно.
                                Ответить
                                • А какой там подход?
                                  Ответить
                                  • В таблицу можно установить метатаблицу, в метатаблице можно определить операторы над таблицей (+,-,...), повлиять на метатаблицу питушением свойств таблицы нельзя (в отличие от иногда встречающегося __proto__ в JS), метатаблица назначается отдельной функцией, операторы (+,-,...) нельзя задать из самой таблицы.
                                    Lua>x = {}
                                    Lua>function x.__add(f1, f2) return f1.x + f2.x; end
                                    Lua>x.x = 5
                                    Lua>x:__add(x)
                                    10
                                    Lua>x + x -- __add в самой таблице не работает
                                    stdin:1: attempt to perform arithmetic on a table value (global 'x')
                                    stack traceback:
                                            stdin:1: in main chunk
                                            [C]: in ?
                                    Lua>y = {x = 2}
                                    Lua>setmetatable(y, x)
                                    table: 00958510
                                    Lua>y + y -- __add работает, когда в он в нашей метатаблице
                                    4
                                    Lua>function y.__add(l, r) return 42 end
                                    Lua>y + y -- __add у себя не мешает __add в метатаблице
                                    4
                                    Lua>y:__add(y)
                                    42
                                    Ответить
                                    • В качестве дополнения: в Lua можно явно решать, что делать с this/self-питухом. Можно выбрать точку или двоеточие при определении и вызове функции.
                                      Ответить
      • > Зачем тут ДВА доллара: $this->$tag ?

        Потому что $foo->bar — это поле bar объекта foo
        А $foo->$bar — это поле объекта foo, имя которого будет взято из переменной bar во время вполнения.

        Та же залупа, что и с $$var.

        Понятное дело, любая ide пойдёт нахуй от такого кода.
        Ответить
        • ахаха,это пиздец

          Тогда я целиком и полностью за
          $foo->{$bar}
          Ответить
      • > Точечка вообще существует?

        Da!
        Для конкатенации строк.
        Ответить
        • Две вещи я считаю глупостью в языках где программист не управляет расположением объекта: стрелочку и оператор new.

          Зачем?
          Ответить
          • Я так понимаю, здесь всё ровно так же, как и во всем остальном PHP: сначала сделали, потом не стали убирать из-за обратной совместимости.
            Ответить
          • > оператор new.
            В жаве тоже?
            Ответить
            • В принципе да, без него обойтись можно вполне.
              Ответить
              • Как отличишь создание нового объекта от вызова функции? Ах да, в жаве, кажется, у них разные неймспейсы (хотя классы все равно должны начинаться с большой, а методы - с маленькой)
                Ответить
                • > Как отличишь создание нового объекта от вызова функции
                  А оно надо?
                  Ответить
                  • >кажется, у них разные неймспейсы
                    Ответить
                    • Так какая разница, зачем это нужно?

                      Знать об этом нужно только компилятору, чтобы выделить кусок памяти под новый объект при вызове. Если функция f была описана как конструктор выше по коду, компилятор знать будет.
                      Ответить
                  • Вот кстати нет

                    в питончике очень часто этим пользуются: ты можешь и не знать что вчера ты вызывал функцию, а теперь конструктор
                    Ответить
                • Чем концептуально отличается создание нового объекта от вызова функции, которая вернёт новый объект ?

                  И вообще, можно пойти по крестопути и сделать
                  Foo foo(12);
                  Ответить
                  • В джаве точно ничем не отличается.

                    Может отличаться в япах с полуручным управлением памятю, когда ты должен вручную делать(или не делать) release объекту (так было в objc до arc)
                    Ответить
                    • Да даже в языках с полуручным управлением результат один: у тебя есть живой объект. Неважно создал ты его сам или тебе передала его (со всей ответственностью) какая-то функция.
                      Ответить
                      • она могла передать тебе его без ответственности

                        смешно, но в Core foundation и Foundation у яблов был код стайл.

                        Типа если функция называется так, но она сама отвечает за обхект, а если этак -- то ты.

                        Я не шучу, погугли "Memory Management Programming Guide for Core Foundation" и там ownership policy
                        Ответить
                  • > Foo foo(12);

                    Конструкторы — в принципе нинужное говно. Даже жависты это поняли. Функций хватит всем.
                    Foo.of(12)
                    Ответить
                    • Или как в дельфи

                      Foo foo = Foo.Create(12)
                      Foo foo = Foo.CreateFromDouble(12)
                      Ответить
                      • Так в паскале конструкторы вроде можно было называть как угодно

                        constructor of(i : integer);
                        Foo.of(12)


                        Причём помнится без малого 10 лет назад Тарас всё это уже обосновывал. Но тогда его минусовали, считая трололо/поехавшим.
                        Ответить
                        • Так и знал, что Тарас опережает своё время на десятилетие… ))
                          Ответить
                          • А я объясню что происходит в этом треде.

                            Крестушки наконец стали осозновать что добрая часть хвалёного С++ — «нинужное говно». Ну речь о крестовиках с богатым кругозором.

                            Ведь какой язык изначально назывался C With Classes?

                            Это ж ведь не создатели жабы сочинили new, class, static, private, public, наследование и остальной ООП-кал.

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

                            Объявление типа, например
                            Foo foo
                            var foo : Foo = ...
                            Только в новомодных языках конца 00х-10х (go, rust, scala, kotlin, younameit) стали отказываться от сишной традиции делать типы спереди.
                            Ответить
                        • Посмотрел, как в обероне сделали:
                          PROCEDURE New* (VAR r : Rectangle);
                          BEGIN
                             NEW(r);
                             Figures.Init(r, Handle);
                          END New;
                          Всю магию поместили в волшебную функцию new. Правильно, так парсер проще.
                          Ответить
                    • > Конструкторы — в принципе нинужное говно.
                      Да и классы — тоже. "Конструктор" возвращает приватный ADT, "методы" умеют с ним работать. Ничего нового классы не дают, только зачем-то разделяют функции/методы/статические методы (и это заканчивается ёблей и унынием).
                      Ответить
                      • > Да и классы — тоже. "Конструктор" возвращает приватный ADT, "методы" умеют с ним работать. Ничего нового классы не дают, только зачем-то разделяют функции/методы/статические методы (и это заканчивается ёблей и унынием).

                        Аминь. My point of view exactly.
                        Ответить
                      • правило 42 гласит: о чём бы ни говорили на ГК всё равно всё сведут к обсыранию ООП
                        Ответить
                        • Походу, скоро кому-нибудь придётся перезайти за ООП'шников. Иначе спорить будет не с кем.
                          Ответить
                          • Я - за АОП
                            Ответить
                          • >Походу, скоро кому-нибудь придётся перезайти за ООП'шников

                            Жаль wvxvw ушёл, он бы мог вписаться, создав длинный пост о том что: "вы обсираете неправильное ООП,
                            а в правильном всё по-другому"

                            К сожалению я так не умею.
                            Ответить
                            • > а в правильном всё по-другому

                              ООП в Common Lisp действительно менее убогое, потому что оно реально делает язык более выразительным (добавляет multiple dispatch). Плюс, основой ООП в CL является функция, а не класс. Можно использовать "generic functions", ни написав вообще ни одного класса, и определять их реализации ("методы") для примитивных типов.
                              Есть ещё довольно занятная идея комбинаторов методов.
                              Ответить
                              • >добавляет multiple dispatch

                                А в кресты его еще не завезли?

                                >Можно использовать "generic functions", ни написав вообще ни одного класса, и определять их реализации ("методы") для примитивных типов

                                Это когда для флоата, инта и комплексоного, например, можно по-разному определить арифметику?

                                >занятная идея комбинаторов методов

                                Можно поподробнее?
                                Ответить
                                • Generic functions похожи на traits в Rust или Default protocol implementation в Swift
                                  Ответить
                                • > Можно поподробнее?

                                  Вкратце: "методы" — это (куски) реализации generic функций. На методах определена операция "сравнения", т.е. из двух методов всегда можно выбрать "более специальный".

                                  Комбинаторы являются атрибутами этих методов у определают, как из списка подходящих "методов" собирается "эффективный метод".

                                  Если комбинатор не указан, т.е. просто типичная "перегрузка", aka primary method.

                                  Kомбинатор :before/:after означает, что текущий метод нужно выполнить ДО/ПОСЛЕ подходящей primary-реализации. :around означает, что нужно обернуть primary-реализацию и вставить что-то до и после (базовая форма АОП).

                                  Есть ещё более эзотерические кобенаторы, вроде "сложи все результаты от всех определённых методов" (как число/список), но на практике я их ни разу не видел.

                                  За детальной информацией прошу сюда
                                  http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html
                                  ISBN-13: 978-0201175899
                                  Ответить
                                  • Я правильно понимаю, что в Рэкете это оно: https://docs.racket-lang.org/reference/struct-generics.html ?
                                    Ответить
                                    • > в Рэкете это оно

                                      Нет, больше похоже на обычные тайпклассы, как, впрочем, и traits в Rust.

                                      Я понимаю, что соблазн сказать "а, это тоже самое, что X" велик (ведь тогда ни в чём разбираться не надо, типа всё уже знаешь), но нет, не тоже самое.
                                      Ответить
                                      • Я думаю, что мне надо было не на тот комментарий отвечать. Я имел в виду не комбинаторы, а сами generic functions.

                                        Просто семантически оно вроде похоже (что, видимо, играет злую шутку)
                                        Ответить
                                        • > сами generic functions

                                          Сами generic functions тоже не похожи. В CL они не привязываются к одному конкретному типу. Например, можно определить функцию (defgeneric intersects (a b)) и написать методы для случаев (defmethod intersects ((a rectangle) (b circle))), (defmethod intersects ((a circle) (b circle))), (defmethod intersects ((a interval) (b point)))
                                          В рантайме будет выбран наиболее подходящий эффективный метод. Т.е. это настоящие мультиметоды.
                                          Ответить
                                          • Я такое на сишарпе писал

                                            Спасибо за ликбез
                                            Ответить
                                            • > Я такое на сишарпе писал

                                              В сишарпах это обычно решается через тучу перегруженных функций в интерфейсе, которые знают о всех остальных классах. В CL можно наопределять структур в N разных модулях, которые ничего друг о друге не знают, а потом в N+1 модуле запилить обобщённую функцию, которая определяется для разных кобенаций входных параметров. М — Модульность.
                                              Ответить
                                              • > М — Модульность.
                                                То же отношение между виджетами и событиями на таких generic'ах прикольно формулируется. Без всяких свичей, визиторов и прочего одномерного говна.
                                                Ответить
                                                • > на таких generic'ах прикольно формулируется.
                                                  >Без всяких свичей, визиторов и прочего одномерного говна.

                                                  А в кресты ничего лучше полиморфизма так и не завезли?
                                                  Ответить
                                                  • > лучше полиморфизма
                                                    Ну есть предложение с open method'ами. Но ему ещё далеко до стандарта.

                                                    З.Ы. Под полиморфизмом ты же имел в виду убогую но простую и эффективную реализацию через таблицы виртуальных методов? Так то это всё проявления полиморфизма.
                                                    Ответить
                                                    • >Под полиморфизмом ты же имел в виду убогую но простую и эффективную реализацию через таблицы виртуальных методов

                                                      Так точно.
                                                      http://govnokod.ru/23894#comment407449

                                                      Как под ООП все по дефолту подразумевают убогую, но простую реализацию его в крестах и жабах :)
                                                      Ответить
                                              • Доберусь до компа, набросаю пример на Свифте
                                                Ответить
                                              • >В сишарпах это обычно решается через тучу перегруженных функций в интерфейсе, которые знают о всех остальных классах

                                                Поскольку полиморфизм, то бишь выбор из таблицы виртуальных функций можно свести к свитчу.

                                                Выбор подходящей функции для мультиметода можно сделать через pattern matching, передав туда кортеж из типов. Не?
                                                Ответить
                                                • > Выбор подходящей функции для мультиметода можно сделать через pattern matching, передав туда кортеж из типов. Не?

                                                  Можно. Основная проблема в том, что такой подход сложно расширить на новые типы, см. Expression problem.
                                                  Проблема расширения на новые типы в функциональных языках решаема, но нужно заранее структурировать код определённым образом.

                                                  https://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Dr-Ralf-Laemmel-Advanced-Functional-Programming-The-Expression-Problem
                                                  Ответить
                                              • >В сишарпах это обычно решается через тучу перегруженных функций в интерфейсе, которые знают о всех остальных классах.

                                                Эээ, по-моему конкретно в сишарпах это уже есть, лет 10 как, благодаря кейворду dynamic.

                                                https://ideone.com/ef75t6
                                                Ответить
                                                • > Эээ, по-моему в сишарпах это уже есть, лет 10 как.


                                                  Ок, не знал, спасибо. Расширить табличку можно только через partial-классы, конечно?
                                                  Ответить
                                                  • Тот кто мне поведал о этой фиче, добавил что она и тупит просто безбожно.

                                                    Скорость исполнения падает в тысячи раз: до интерпретаторных значений.

                                                    Думаю в той же жабе такое можно замутить, через рефлексию, полным перебором сигнатур.

                                                    >Расширить табличку можно только через partial-классы, конечно?

                                                    Не совсем понял вопрос.
                                                    Ответить
                                                    • > Не совсем понял вопрос.

                                                      Если захочется добавлять новые пары для новых типов, придётся править оригинальный .cs-файл.
                                                      Ответить
                                                      • А, ну в этом плане да.

                                                        Но как мне объясняли, их делали для других целей.

                                                        Там же для ololo-linq-to-sql запилены генереции DTO из таблиц в базе.

                                                        Естественно в автогенерированный код вносить изменения бессмысленно.

                                                        Но иногда хочется что-то переопределить, потому сделали частичные классы.

                                                        PS> Решил проверить ambiguous-случай, С# стрельнул рантайм-исключением. Как в CL разруливают diamond-проблемы?

                                                        http://govnokod.ru/23905
                                                        https://ideone.com/Jm5LJA
                                                        Ответить
                                                        • Ещё partial для WinForms.

                                                          Но они в вашем случае мало помогут, потому что все куски partial class'а должны быть описаны в одном неймспейсе. Короч, либу не расширишь
                                                          Ответить
                                                        • > Как в CL разруливают diamond-проблемы?

                                                          Эту проблему решают тем самым сравнением методов. Первые аргументы важнее последующих, более специальный первый аргумент выиграет.
                                                          https://ideone.com/l4Soof
                                                          Ответить
                                                          • >Первые аргументы важнее последующих

                                                            Ну да в традициях функциональных языков принято применять аргументы по одному.

                                                            Но я хотел спросить про классический diamond, когда множественное наследование, как тогда дуплить?

                                                            (defclass A (object B C) ())

                                                            Пишут что CLOS приоритизирует типы в порядке перечисления в defclass.
                                                            Ответить
                                                            • > Пишут что CLOS приоритизирует типы в порядке перечисления в defclass.


                                                              Ну у тебя теперь есть отправная точка для экспериментов, проверь :)
                                                              Ответить
                          • > Иначе спорить будет не с кем.

                            Давайте я зайду за ООП. Ну почти.

                            Я думаю ООП — это что-то вроде школы. В школе тебе говорят, что, когда ты вырастешь, ты сможешь стать кем угодно, хотя в общем-то почти сразу понятно, что не так уж и кем угодно. Но главное — учиться на пятёрки.

                            Так же и в ООП. Это замечательный полигон и точка входа в программирование, которое обещает тебе настолько райскую жизнь, что в погоне за ним, тебе хватает сил перебраться из внешнего мира сюда к нам, в программирование. Плевать, что потом оказывается, что все мечты были несбыточными. Ты уже в деле.

                            После школы тоже выбор между армией и институтом, а после институда — в сварщики или танцоры, или работники сферы услуг, или офисный планктон, или, в хорошем случае, в талантливые мастера какого-нибудь благородного не подлого и не паразитского дела.

                            Ведь мы все любим программировать и начали этим заниматься, не потому, что хотели работать на такой работе. Это просто само по себе чудесно.
                            Ответить
                        • А где обсирали ООП? Пока что обосрали слово new
                          Ответить
                          • > Конструкторы — в принципе нинужное говно

                            > Да и классы — тоже

                            > класс смешивает в себе кучу ортогональных вещей
                            Ответить
                      • > разделяют функции/методы/статические методы
                        Самое печальное - что статические поля отличаются от обычных полей, а статические методы не отличаются от обычных методов.
                        В C++ вообще нет методов, которые относятся к объекту. Самое большое, что реализовали - методы, разделяемые кучей объектов (виртуальные питухи). Методы объекта там могут только эмулироваться громоздкими указателями на функции, но this в них приходится передавать явно и терпеть отсутствие private/protected-членов.
                        Ответить
                        • > а статические методы не отличаются от обычных методов

                          Отличаются. Их нельзя переопределить в подклассе.

                          > нет методов, которые относятся к объекту

                          То ли дело «Common Lisp».
                          Ответить
                        • ООПшники любят залечивать о том, что каждая херня должна решать одну задачу. Но где было это хвалёное single responsibility когда придумывали концепцию класса? Ведь класс смешивает в себе кучу ортогональных вещей — пространство имён, структуру данных и генерацию волшебных функций…
                          Ответить
                          • >И это различие породило такой бесполезный паттерн как синглтон.
                            Понял что написал херню и потер?
                            Ответить
                            • > Понял что написал херню
                              Да. Но синглтон от этого полезным не стал.
                              Ответить
                              • Стал
                                Ответить
                                • > Стал
                                  И в чём польза синглтона? Какую проблему он решает?

                                  Абсолютно та же хуйня, что и глобалки. Только в красивой обёртке.
                                  Ответить
                                • З.Ы. Да ещё и смешивает в кучу 2 концепции — управление временем жизни объекта и полезный функционал.
                                  Ответить
                                  • *Управляет количеством копий и предоставляет глобальную точку доступа.
                                    Ответить
                                    • > и предоставляет глобальную точку доступа…
                                      …которая прибивает к нему гвоздями всех клиентов.
                                      Ответить
                                • Синглтоны - это полная параша. Например, опенссл - это синглтон фактически. Как же охуенно, когда две библиотеки при инициализации настраивают общий опенссл и от этого конфликтуют. Или другая крайность: библиотека использует крипту из опенссл но сама его никак не инициализирует. И если хочешь потокобезопасности - будь добр настроить опенссл, про который ты ни сном ни духом и вообще с ним не линкуешься.
                                  Другой пример говнобиблиотеки - либкурл, все те же грабли.
                                  Только что характерно, все это говно написано на "няшной" сишочке, а не на джаве. Что подтверждает, что синглтоны изобрели очень давно, но раньше их называли глобальными переменными.
                                  Ответить
                                  • >Синглтоны - это полная параша. Например, опенссл - это синглтон фактически.
                                    Млять. Я не предлагал же их пихать везде. Они *могут* быть полезны. Неужели непонятно?
                                    Ответить
                                    • > *могут* быть полезны
                                      Где и чем? В чём преимущество перед обычными функциями.
                                      Ответить
                                      • Сады удобрять.
                                        Ответить
                                      • если, в зависимости от каких-нибудь условий и настроек, создаётся один из нескольких объектов. Например, в зависимости от того, ведётся лог или нет, создаётся или настоящий объект, пишущий в файл, или «заглушка», ничего не делающая.
                                        Ответить
                                        • Почему это не может сделать обычная функция? Это логично делать функцией а не обременять класс знаниями о том, что лог может вестись, а может не вестись (а если понадобится два уровня логирования для разных подсистем?), знаниями о том что есть ещё другой класс-заглушка, и что иногда нужно подставлять его.
                                          Ответить
                                          • Объект логгера у тебя синглтон, нет? Причем тут класс? Переменная класса - это *реализация*
                                            Ответить
                                            • Ты видимо под синглтоном понимаешь какую-то свою особую херню.

                                              Классическое определение синглтона: это класс, который не даёт возможности создать больше одного экземпляра ("сингл"), созданием которого сам и управляет, и даёт возможность доступа к этому экземпляру.
                                              Ответить
                                              • Под синглтоном я понимаю объект, существующий в одном экземпляре
                                                Ответить
                                                • Вот ты опять привязываешь устоявшуюся терминологию к какому-то своему пониманию, и потом обвиняешь всех вокруг в том что они не читают твой разум и говорят не о том.

                                                  Объект существующий в единичном экземпляре ≠ класс, который следит, чтобы больше одного экземпляра не было создано.
                                                  Ответить
                                                  • диночка (англ. Singleton) — порождающий шаблон проектирования, гарантирующий, что в однопроцессном приложении будет единственный экземпляр некоторого класса, и предоставляющий глобальную точку доступа к этому экземпляру.

                                                    это класс, который не даёт возможности создать больше одного экземпляра ("сингл"),

                                                    Чувствуешь разницу?
                                                    Ответить
                                        • > настоящий объект, пишущий в файл, или «заглушка»
                                          ООПшники всегда любят себе создать одну из нескольких проблем… Даже на таком простом примере какую-то неюзабельную хуйню надизайнили. А если я захочу ошибки писать на экран, а подробные логи — в файл? Или иметь по логгеру на тред?
                                          Ответить
                                          • Ты же напитоне писал. Логгер для модуля там сингтон же, нет?
                                            Ответить
                                            • > Логгер для модуля там сингтон же, нет?
                                              Ты про logging.debug() без запиливания своего инстанса логгера? Ну дык это обычные функции, внутри синглтон там может и есть, но это деталь реализации этих функций.
                                              Ответить
                                              • Вообще-то там есть глобальное состояние, которое можно теребить через logging.basicConfig, так что не обычные функции, а очень даже синглтон.
                                                Ответить
                                              • Если синглтон используется в потрохах модуля который ты используешь то это уже и не синглтон. Ясно.
                                                Ответить
                                      • В некоторых языках у синглтонов лучше с инкапсуляцией. Класс становится отдельной единицей, внутри которой (1) создают объект и (2) знают, как с ним работать. Если функция будет создавать объекты нужного типа, то её может понадобиться дополнительно отдельное определение класса, которое будет вносить дополнительное имя в пространство имён, к тому же разрешая всем невозбранно создать 100500 объектов.
                                        Ответить
                                      • Синглтоны сервисы бывают полезными.

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

                                        Его конечно можно заменить лямбдой со static переменной(или структурой из пачки таких лямбд), но ООПетушкам всё таки приятнее общаться с классами и интефейсами.

                                        В жырном энтерпрайзе в DI на спринге часто бывают сервисы с лайфтаймом singleton. У некоторых IDE бывают всякие application service которые живут пока живо приложение итд


                                        А вот когда вместо функции fuu делают класс-синглтон (Со всей говномашинерией, ибо в жабе нативной поддержки оных нет) ради одной функции это правда смешно.
                                        Ответить
                                        • > DI
                                          Но там же сам класс не завязан на то, что контейнер запилит ровно один его инстанс. И его клиенты об этом не знают. Так что это всё-таки не классический говносинглтон.
                                          Ответить
                                          • Тоесть тебя бесит сам класс, который физически нельзя тнтсанциировать два раза? А если он реализует интерфейс, тогда он нужен в е таки?
                                            Ответить
                                            • > бесит сам класс, который физически нельзя тнтсанциировать два раза
                                              Меня бесит, когда код завязывается на то, что инстанс будет ровно один.

                                              Да и сам способ получения через какой-нибудь getInstance().
                                              Ответить
                                    • Полезность сомнительна, вредность очевидна. Я готов мириться с "синглтоном", как с дефолтным экземпляром класса (например логер), при условии, что буду иметь возможность создавать собственные экземпляры сколько захочу. Но даже в этом случае я предпочту не использовать дефолтный логер, а таскать везде собственный, потому что глобальные переменные и неявные зависимости до добра не доводят.
                                      Ответить
                          • >>ООПшники любят залечивать о том, что каждая херня должна решать одну задачу

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

                        Внезапно выяснилось что паскальный подход был логичнее.
                        А крестобляди 90х и последовавшие за ними жависты, шарперы, опять обосрались.
                        Ответить
                    • как же raii?
                      Ответить
                      • > как же raii?
                        >> в языках где программист не управляет расположением объекта

                        Да даже в каких-нибудь крестах можно было обойтись, просто "волшебные" функции иметь, на наличие которых полагается компилятор.
                        Ответить
                • В питоне ты как отличаешь?

                  неймспейс создает именно "new", регистр в джаве на это не влияет (это не ruby, где UPPERCASE всегда R/O), но можно было изначально не делать new и не писать одинаковых методов и иннер классов (напомню что в жабе топ-лепел функций нет)
                  Ответить
            • Конечно, зачем он там?
              в колине его нет

              "new" значит "создать объект в динамической памяти". Лол! Будто-бы в жабе я могу этим управлять.
              Ответить
              • # "new" значит "создать объект в динамической памяти"

                "new" обычно значит "создать объект и вызвать конструктор"
                Ответить
                • нет, new означает _выделить_динамически_памяти_в_куче

                  Интуитивно должно быть так:
                  Foo foo = Foo(); //Foo на стеке
                  Foo* foo = new Foo(); //Foo на куче

                  Так как в жабе, JS, C#, и прочей автоматически работающией с памятью питушне пользователь не управляет выбором места (он как-бы думает что объект всегда на куче, хотя это не так на самом деле) то смысла в слове new нет
                  Ответить
                  • # _выделить_динамически_памяти_в_куче

                    А теперь отличи это от malloc
                    Ответить
              • >"new" значит "создать объект в динамической памяти".

                В жабе new они сделали больше из соображений читабельности и чтобы народу с крестов было проще пересаживаться.

                >Лол! Будто-бы в жабе я могу этим управлять.

                Изначально все объекты действительно тупо плодились на куче. Спустя годы хотспот обучили новым трюкам (сугубо из соображений оптмизиации).
                А рудименты от крестов остались:

                int[] a={1,2,3,4};
                int[] a=new int[10];
                int[] a=new int[]{1,2,3,4};
                Ответить
                • Изначально для читабельности, а потом это перекочевало в JS, в C# итд. И только в конце нулевых люди поняли что new не нужен: в котлине его уже нет, например;)
                  (кстати, в Питоне его не было изначально)

                  >> Спустя годы хотспот обучили новым трюкам
                  Под капотом JVM имеет право создать объект на стеке если понимает что ты указатель на него никуда не передаешь и не возвращаешь, но думать об этом ты не должен;)

                  >>int[] a=new int[]{1,2,3,4};
                  м-да, вербозненько
                  Ответить
                  • > объект на стеке если понимает что ты указатель на него никуда не передаешь

                    В яве нет указателей, только ссылки.

                    >[new] Изначально для читабельности

                    Налицо полное непонимание. Когда делали яву, постоянно оглядывались на С++. А там при присваивании стековых объектов, они копируются.
                    Ответить
          • А я думаю, что стелочка и оператор new никак не зависят от возможности управления рсположением объекта.
            Ответить
            • потому что ты ламер
              Ответить
            • Тебе напомнить откуда есть пошли стрелочка и точка? Помнишь структуры в plain c?
              Ответить
              • Я всё прекрасно помню, но какая уже разница, откуда они пошли давны-давно? Раньше и проститутка была девствинницей.
                Ответить
                • оттуда что это семантический мусор, который не нужен

                  зачем мне лишние буквы в коде?
                  Ответить
                  • # зачем мне лишние буквы в коде?

                    Зачем тебе вообще код?
                    Ответить
                    • Код выражает алгоритм, а лишние буквы -- нет.

                      В котлине я пишу
                      val foo = Foo();
                      foo.bar();
                      Это точно так же понятно как и
                      $foo = new Foo();
                      $foo->bar();
                      хотя букв меньше
                      Ответить
                      • А вдруг когда-нибудь появится ключевое слово old? (Берет объект нужного класса, на который уже не осталось ссылок, но сборщик его ещё не выкинул) И как ты тогда будешь отличать новые объекты от старых?
                        Ответить
                        • Это можно запилить как оптимизацию new
                          Ответить
                          • Нельзя. New возвращает свежий объект, а old — уже поюзанный, со значениями полей, оставшимися с последнего использования.
                            Ответить
                            • надо просто ввести новый тип конструктора который бы чистил объект
                              Ответить
                              • Обратную совместимость сломаешь. Существующий код же ничего не чистит вилкой после получения объекта.
                                Ответить
                                • Не сломаешь. Изначально это было ub поэтому на практике с кучи могло возвращаться всё что угодно. Некоторые юзали это также как когда-то в Pascal юзали значение переменной цикла после выполнения тела, но хороший код на такие фичи никогда не полагается. После того как ввели конструкторы с очисткой, стандартом де-факто постепенно стало рассчитывать на то что объект будет чистым.
                                  Ответить
                        • Кстати, а ведь удобный синтаксис для ORM'ов:
                          user = new User(id=42, name="foo") # это новый юзер
                          user = old User(id=42)             # а это он же
                          Ответить
                          • Даешь встроенную в язык поддержку ORM:)

                            в Django есть User.objects.get_or_create() :)
                            Ответить
    • По поводу ООП и protected/private/public.

      docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7-2#private-protected-access-modifier
      Ответить
      • >>private protected:

        Спецификация C# пока не дотягивает по размерам до спеки C++, но ребята работают.
        Скоро c# станет сложнее крестов
        Ответить
        • Там новый конкурент догоняет: ecmaScript;
          Ответить
          • Сраные 885 листов, вообще не конкурент. А у шарпа всего 543 листа.

            З.Ы. "Предварительная спецификация C# 6.0", время чтения: 2 минуты.
            Ответить
          • Вы можете отправить запрос на вытягивание в тот же репозиторий. Надо запомнить фразу.
            Ответить
            • Надмозги и git pull?
              Ответить
            • Обожаю переводы, особенно автоматические. После того как я прочитал вслух слово "описатель" мне пришлось идти к стоматологу
              Ответить
              • "Этот перевод выполнен не человеком". Они своих переводчиков даже за людей не считают.
                Ответить
            • Чтобы опубликовать изменения содержимого, необходимо отправить запрос на вытягивание из своей вилки. Отправка и обработка запросов на вытягивание подробно описаны в рабочих процессах по внесению незначительных или эпизодических изменений и внесению значительных или времязатратных изменений
              Ответить

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