- 1
- 2
- $pending = $this->$tag['callback']($open['data'], $open['option']);
+ $pending = $this->{$tag['callback']}($open['data'], $open['option']);
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
−1
- $pending = $this->$tag['callback']($open['data'], $open['option']);
+ $pending = $this->{$tag['callback']}($open['data'], $open['option']);
Копаюсь в сорцах говнокода.
В PHP 7 поменяли приоритет, пол часа не мог понять что за хуйня.
Ку вот зачем тут стрелочка? this может быть не указателем? Точечка вообще существует?
Зачем тут ДВА доллара: $this->$tag ?
Почему все юзают дикты? Потому что нет лёгкого способа описать объект как в JS (где хеш есть объект) или как OpenStruct в Ruby?
Тогда почему не разрешить нормальный синтаксис через точку?
Семантический мусор же.
/fixed
PHP7 -> JS:
PHP5 -> JS:
(ЕМНИП)
А потом пердолить этим людей не хуже, чем сишным int *a[10] vs int (*p)[].
Я считаю что разделять структуры/записи (ну классы без методов) и дикты (они же мэпы они же хеши они же ассоциативные массивы) в ЯПах без обязательной стат типизации смысла нет, то-есть в JS сделано правильно.
Вот нуб пришел на работу и не знает как передать 20 параметров: ассоциативным массивом или классом?
Старый жабист говорит: "коненчно классом, так ты не опечатаешься и в рантайме узнаешь если ошибся".
Старый, не знаю, перловик говорит: "конечно хешем, не выябывайся".
В результате получается и так и сяк.
Q: что лучше: $petushok['age'] или $petushok->age?
A: ахуйегознает
>в рантайме узнаешь если ошибся
Не-не-не, жабисты так точно не говорят.Только те что на спринг expression-language пишут.
> то-есть в JS сделано правильно
Вот. Но не совсем.
1024-- как-то говорил что еще кошернее и в духе доброго похуистичного js, было бы сделать чтоб цепочки свойств не падали.
user['pituh']['age'] //undefined, если питуха нет
в 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
С одной стороны достаточно полезно было бы иметь, с другой в мерзком ECMA-2015 можно запилить
Думаю и в js можно через proxy добиться такого поведения.
ты походу не дебажил случаи, когда у тебя один из этих параметров в конце длинной цепочки преобразований почему-то undefined, а посередине сплошное жонглирование с Object.keys и прочим весельем
Так что я тут согласен с SemaReal.
A: (:age petushok)
В JS сделано отчасти хорошо (читай: плохо).
Хорошо сделано в Lua, где есть метатаблицы, из-за которых можно отличить, где у тебя в ассоциативном массиве лежит ключ (данные), а где - его поле или метод.
Иначе общение с ассоциативным массивом превращается в пердолинг. Если кто-то добавил в Object.prototype что-то полезное (те же полифиллы), in для всех ассоциотивных питухов уже будет срабатывать на это полезное. На hasOwnProperty рассчитывать нельзя, т.к. его могли добавить как ключ. Брать hasOwnProperty надо из другого, чистого объекта. И прочая питушня. В старых версиях языка наверно легче было к каждому ключу добавлять префикс, с которого с большой вероятностью не будут начинаться поля и методы. Сейчас в JS встроили специально написанные мапы, но их просто так не задашь литералом.
Тут и без __ __ всё работает. В JS бы в аналогичном примере была ошибка вызова числа как функции.
Не понял
В питоне тоже случается как за нехуй.
Вылетит при вызове obj.login() догадайся почему
В моём примере данные переписали метаданные. В нормальном коде такое возможно, если в пользовательском вводе встретилась подходящая питушня.
Запрещать присваивать что-то в динамическом массиве - тоже не вариант, пользователь имеет полное право вставить __питушню__, невставка __питушни__ будет эквивалентна вставке питушни, перетирающей поля и методы: проверять всё равно придётся.
А вот подход Lua - наверно то, что нужно.
Потому что $foo->bar — это поле bar объекта foo
А $foo->$bar — это поле объекта foo, имя которого будет взято из переменной bar во время вполнения.
Та же залупа, что и с $$var.
Понятное дело, любая ide пойдёт нахуй от такого кода.
Тогда я целиком и полностью за
$foo->{$bar}
Da!
Для конкатенации строк.
Зачем?
В жаве тоже?
А оно надо?
Знать об этом нужно только компилятору, чтобы выделить кусок памяти под новый объект при вызове. Если функция f была описана как конструктор выше по коду, компилятор знать будет.
в питончике очень часто этим пользуются: ты можешь и не знать что вчера ты вызывал функцию, а теперь конструктор
И вообще, можно пойти по крестопути и сделать
Foo foo(12);
Может отличаться в япах с полуручным управлением памятю, когда ты должен вручную делать(или не делать) release объекту (так было в objc до arc)
смешно, но в Core foundation и Foundation у яблов был код стайл.
Типа если функция называется так, но она сама отвечает за обхект, а если этак -- то ты.
Я не шучу, погугли "Memory Management Programming Guide for Core Foundation" и там ownership policy
Конструкторы — в принципе нинужное говно. Даже жависты это поняли. Функций хватит всем.
Foo.of(12)
Foo foo = Foo.Create(12)
Foo foo = Foo.CreateFromDouble(12)
Причём помнится без малого 10 лет назад Тарас всё это уже обосновывал. Но тогда его минусовали, считая трололо/поехавшим.
Крестушки наконец стали осозновать что добрая часть хвалёного С++ — «нинужное говно». Ну речь о крестовиках с богатым кругозором.
Ведь какой язык изначально назывался C With Classes?
Это ж ведь не создатели жабы сочинили new, class, static, private, public, наследование и остальной ООП-кал.
Создатели жабы просто заимствовали фичи (вплоть до синтаксиса) из модных тогда крестов, пытаясь сделать из них хоть что-то приличное.
Увы, безуспешно.
Объявление типа, например
Foo foo
var foo : Foo = ...
Только в новомодных языках конца 00х-10х (go, rust, scala, kotlin, younameit) стали отказываться от сишной традиции делать типы спереди.
Да и классы — тоже. "Конструктор" возвращает приватный ADT, "методы" умеют с ним работать. Ничего нового классы не дают, только зачем-то разделяют функции/методы/статические методы (и это заканчивается ёблей и унынием).
Аминь. My point of view exactly.
Жаль wvxvw ушёл, он бы мог вписаться, создав длинный пост о том что: "вы обсираете неправильное ООП,
а в правильном всё по-другому"
К сожалению я так не умею.
ООП в Common Lisp действительно менее убогое, потому что оно реально делает язык более выразительным (добавляет multiple dispatch). Плюс, основой ООП в CL является функция, а не класс. Можно использовать "generic functions", ни написав вообще ни одного класса, и определять их реализации ("методы") для примитивных типов.
Есть ещё довольно занятная идея комбинаторов методов.
А в кресты его еще не завезли?
>Можно использовать "generic functions", ни написав вообще ни одного класса, и определять их реализации ("методы") для примитивных типов
Это когда для флоата, инта и комплексоного, например, можно по-разному определить арифметику?
>занятная идея комбинаторов методов
Можно поподробнее?
Вкратце: "методы" — это (куски) реализации generic функций. На методах определена операция "сравнения", т.е. из двух методов всегда можно выбрать "более специальный".
Комбинаторы являются атрибутами этих методов у определают, как из списка подходящих "методов" собирается "эффективный метод".
Если комбинатор не указан, т.е. просто типичная "перегрузка", aka primary method.
Kомбинатор :before/:after означает, что текущий метод нужно выполнить ДО/ПОСЛЕ подходящей primary-реализации. :around означает, что нужно обернуть primary-реализацию и вставить что-то до и после (базовая форма АОП).
Есть ещё более эзотерические кобенаторы, вроде "сложи все результаты от всех определённых методов" (как число/список), но на практике я их ни разу не видел.
За детальной информацией прошу сюда
Нет, больше похоже на обычные тайпклассы, как, впрочем, и traits в Rust.
Я понимаю, что соблазн сказать "а, это тоже самое, что X" велик (ведь тогда ни в чём разбираться не надо, типа всё уже знаешь), но нет, не тоже самое.
Просто семантически оно вроде похоже (что, видимо, играет злую шутку)
Сами 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'ах прикольно формулируется. Без всяких свичей, визиторов и прочего одномерного говна.
>Без всяких свичей, визиторов и прочего одномерного говна.
А в кресты ничего лучше полиморфизма так и не завезли?
Ну есть предложение с open method'ами. Но ему ещё далеко до стандарта.
З.Ы. Под полиморфизмом ты же имел в виду убогую но простую и эффективную реализацию через таблицы виртуальных методов? Так то это всё проявления полиморфизма.
Так точно.
http://govnokod.ru/23894#comment407449
Как под ООП все по дефолту подразумевают убогую, но простую реализацию его в крестах и жабах :)
Поскольку полиморфизм, то бишь выбор из таблицы виртуальных функций можно свести к свитчу.
Выбор подходящей функции для мультиметода можно сделать через pattern matching, передав туда кортеж из типов. Не?
Можно. Основная проблема в том, что такой подход сложно расширить на новые типы, см. Expression problem.
Проблема расширения на новые типы в функциональных языках решаема, но нужно заранее структурировать код определённым образом.
Эээ, по-моему конкретно в сишарпах это уже есть, лет 10 как, благодаря кейворду dynamic.
https://ideone.com/ef75t6
Ок, не знал, спасибо. Расширить табличку можно только через partial-классы, конечно?
Скорость исполнения падает в тысячи раз: до интерпретаторных значений.
Думаю в той же жабе такое можно замутить, через рефлексию, полным перебором сигнатур.
>Расширить табличку можно только через partial-классы, конечно?
Не совсем понял вопрос.
Если захочется добавлять новые пары для новых типов, придётся править оригинальный .cs-файл.
Но как мне объясняли, их делали для других целей.
Там же для ololo-linq-to-sql запилены генереции DTO из таблиц в базе.
Естественно в автогенерированный код вносить изменения бессмысленно.
Но иногда хочется что-то переопределить, потому сделали частичные классы.
PS> Решил проверить ambiguous-случай, С# стрельнул рантайм-исключением. Как в CL разруливают diamond-проблемы?
http://govnokod.ru/23905
https://ideone.com/Jm5LJA
Но они в вашем случае мало помогут, потому что все куски partial class'а должны быть описаны в одном неймспейсе. Короч, либу не расширишь
Эту проблему решают тем самым сравнением методов. Первые аргументы важнее последующих, более специальный первый аргумент выиграет.
Ну да в традициях функциональных языков принято применять аргументы по одному.
Но я хотел спросить про классический diamond, когда множественное наследование, как тогда дуплить?
(defclass A (object B C) ())
Пишут что CLOS приоритизирует типы в порядке перечисления в defclass.
Ну у тебя теперь есть отправная точка для экспериментов, проверь :)
Давайте я зайду за ООП. Ну почти.
Я думаю ООП — это что-то вроде школы. В школе тебе говорят, что, когда ты вырастешь, ты сможешь стать кем угодно, хотя в общем-то почти сразу понятно, что не так уж и кем угодно. Но главное — учиться на пятёрки.
Так же и в ООП. Это замечательный полигон и точка входа в программирование, которое обещает тебе настолько райскую жизнь, что в погоне за ним, тебе хватает сил перебраться из внешнего мира сюда к нам, в программирование. Плевать, что потом оказывается, что все мечты были несбыточными. Ты уже в деле.
После школы тоже выбор между армией и институтом, а после институда — в сварщики или танцоры, или работники сферы услуг, или офисный планктон, или, в хорошем случае, в талантливые мастера какого-нибудь благородного не подлого и не паразитского дела.
Ведь мы все любим программировать и начали этим заниматься, не потому, что хотели работать на такой работе. Это просто само по себе чудесно.
> Да и классы — тоже
> класс смешивает в себе кучу ортогональных вещей
Самое печальное - что статические поля отличаются от обычных полей, а статические методы не отличаются от обычных методов.
В C++ вообще нет методов, которые относятся к объекту. Самое большое, что реализовали - методы, разделяемые кучей объектов (виртуальные питухи). Методы объекта там могут только эмулироваться громоздкими указателями на функции, но this в них приходится передавать явно и терпеть отсутствие private/protected-членов.
Отличаются. Их нельзя переопределить в подклассе.
> нет методов, которые относятся к объекту
То ли дело «Common Lisp».
Понял что написал херню и потер?
Да. Но синглтон от этого полезным не стал.
И в чём польза синглтона? Какую проблему он решает?
Абсолютно та же хуйня, что и глобалки. Только в красивой обёртке.
…которая прибивает к нему гвоздями всех клиентов.
Другой пример говнобиблиотеки - либкурл, все те же грабли.
Только что характерно, все это говно написано на "няшной" сишочке, а не на джаве. Что подтверждает, что синглтоны изобрели очень давно, но раньше их называли глобальными переменными.
Млять. Я не предлагал же их пихать везде. Они *могут* быть полезны. Неужели непонятно?
Где и чем? В чём преимущество перед обычными функциями.
Классическое определение синглтона: это класс, который не даёт возможности создать больше одного экземпляра ("сингл"), созданием которого сам и управляет, и даёт возможность доступа к этому экземпляру.
Объект существующий в единичном экземпляре ≠ класс, который следит, чтобы больше одного экземпляра не было создано.
это класс, который не даёт возможности создать больше одного экземпляра ("сингл"),
Чувствуешь разницу?
мне нравится такое название
ООПшники всегда любят себе создать одну из нескольких проблем… Даже на таком простом примере какую-то неюзабельную хуйню надизайнили. А если я захочу ошибки писать на экран, а подробные логи — в файл? Или иметь по логгеру на тред?
Ты про logging.debug() без запиливания своего инстанса логгера? Ну дык это обычные функции, внутри синглтон там может и есть, но это деталь реализации этих функций.
Такой объект лениво создается, считает всякое разное, сохраняет во внутреннем состоянии эти расчеты, и может передаваться в разные функции как стратегия.
Его конечно можно заменить лямбдой со static переменной(или структурой из пачки таких лямбд), но ООПетушкам всё таки приятнее общаться с классами и интефейсами.
В жырном энтерпрайзе в DI на спринге часто бывают сервисы с лайфтаймом singleton. У некоторых IDE бывают всякие application service которые живут пока живо приложение итд
А вот когда вместо функции fuu делают класс-синглтон (Со всей говномашинерией, ибо в жабе нативной поддержки оных нет) ради одной функции это правда смешно.
Но там же сам класс не завязан на то, что контейнер запилит ровно один его инстанс. И его клиенты об этом не знают. Так что это всё-таки не классический говносинглтон.
Меня бесит, когда код завязывается на то, что инстанс будет ровно один.
Да и сам способ получения через какой-нибудь getInstance().
лол, в процедурном подходе это как-то не так?
>Да и классы — тоже.
Внезапно выяснилось что паскальный подход был логичнее.
А крестобляди 90х и последовавшие за ними жависты, шарперы, опять обосрались.
>> в языках где программист не управляет расположением объекта
Да даже в каких-нибудь крестах можно было обойтись, просто "волшебные" функции иметь, на наличие которых полагается компилятор.
неймспейс создает именно "new", регистр в джаве на это не влияет (это не ruby, где UPPERCASE всегда R/O), но можно было изначально не делать new и не писать одинаковых методов и иннер классов (напомню что в жабе топ-лепел функций нет)
в колине его нет
"new" значит "создать объект в динамической памяти". Лол! Будто-бы в жабе я могу этим управлять.
"new" обычно значит "создать объект и вызвать конструктор"
Интуитивно должно быть так:
Foo foo = Foo(); //Foo на стеке
Foo* foo = new Foo(); //Foo на куче
Так как в жабе, JS, C#, и прочей автоматически работающией с памятью питушне пользователь не управляет выбором места (он как-бы думает что объект всегда на куче, хотя это не так на самом деле) то смысла в слове new нет
А теперь отличи это от malloc
В жабе new они сделали больше из соображений читабельности и чтобы народу с крестов было проще пересаживаться.
>Лол! Будто-бы в жабе я могу этим управлять.
Изначально все объекты действительно тупо плодились на куче. Спустя годы хотспот обучили новым трюкам (сугубо из соображений оптмизиации).
А рудименты от крестов остались:
int[] a={1,2,3,4};
int[] a=new int[10];
int[] a=new int[]{1,2,3,4};
(кстати, в Питоне его не было изначально)
>> Спустя годы хотспот обучили новым трюкам
Под капотом JVM имеет право создать объект на стеке если понимает что ты указатель на него никуда не передаешь и не возвращаешь, но думать об этом ты не должен;)
>>int[] a=new int[]{1,2,3,4};
м-да, вербозненько
В яве нет указателей, только ссылки.
>[new] Изначально для читабельности
Налицо полное непонимание. Когда делали яву, постоянно оглядывались на С++. А там при присваивании стековых объектов, они копируются.
зачем мне лишние буквы в коде?
Зачем тебе вообще код?
В котлине я пишу
val foo = Foo();
foo.bar();
Это точно так же понятно как и
$foo = new Foo();
$foo->bar();
хотя букв меньше
в Django есть User.objects.get_or_create() :)
docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7-2#private-protected-access-modifier
Спецификация C# пока не дотягивает по размерам до спеки C++, но ребята работают.
Скоро c# станет сложнее крестов
З.Ы. "Предварительная спецификация C# 6.0", время чтения: 2 минуты.