Pull to refresh
38
0
LoneCat @LoneCat

User

Send message
Например qbasic :) Какой всё-таки замечательный был язык… :)
Ну вот с точки зрения principle of least surprise чертова куча библиотек под си работает именно с таким соглашением, а это gtk+, mysql, gd и т.д., и если уж говорить о php — то в нём тоже большинство функций работы с массивами принимает первым аргументом массив, большинство функций работы со строками — строку, с регулярками — регулярярное выражение, это и есть то самое ожидаемое для программиста поведение.

«все функции, принимающие на вход массив(ы) и callback должны иметь callback в одном и том же месте» — а что, в этом топике есть хоть один человек который с этим спорит? Должны, и это место — место второго аргумента по вышеобозначенному вами-же принципу, так как в php первый занят массивом в большинстве функций array_*.

И за весь наш разговор ни одного аргумента в поддержку вашей позиции я пока не услышал, как собственно и самой позиции, подозреваю что их вообще нет. Адекватный спор — попытка доказать свою точку зрения, а не хамством опровергнуть чужую, поэтому считаю дискуссию закрытой, у меня нет желания приводить свои доводы и получать в ответ аргументы в виде «ну это в натуре бред», я себе не враг.
Если функция называется array_filter — то первым аргументом она должна принимать массив, это ожидаемое от неё поведение, было-бы как минимум нелогично если-бы preg_replace принимал первым аргументом строку замены, а не шаблон регулярного выражения, str_split количество символов для разбивки строки, а не саму строку и т.п., так как у них в названии это написано:
массив_фильтровать($массив, $чем_фильтровать);
строку_разбить($строка, $на_сколько_символов_разбить);

И тон смените, я вам спокойно излагаю свою позицию, а вместо аргументированного ответа получаю какое-то брызганье слюной.
И что не так с array_filter? Сигнатура такая-же как у array_reduce, да и по логике оно так как должно быть, в объектном стиле это-бы выглядело $array->filter() / $array->reduce(), если рассматривать функцию как первичный аргумент относительно массивов, как в array_map — то тогда и называться они должны наоборот, function_filter_array, function_reduce_array и т.п., ну или в недостижимом идеале — как в других языках — просто filter, просто map, просто reduce, а префикс array_ однозначно указывает что в первую очередь операция производится над массивом, а уже потом какая, как и чем, это как-бы привычное человеческому восприятию соглашение об именовании, вон например в gtk+ — все функции gtk_window_* принимают первым аргументом структуру GtkWindow, что логично, gtk_widget_* соот-но GtkWidget и т.п.
Это безусловно кривизна, но мотивы оной в документации описаны, array_map принимает несколько массивов, соот-но массив у него вторым параметром потому как может быть ещё и третий, четвертый и т.п., ради этого разработчики php решили испохабить его сигнатуру.
Так тогда я не понимаю что вас смущает, в объектах первого типа инкапсуляция важна — соот-но нужны геттеры и сеттеры, в объектах второго типа, раз уж они как объекты не используются, ее можно не соблюдать, тобишь для языков которые позволяют прямое обращение к публичным полям данных — использовать их, или например в ди, помимо полноценных объектов, есть структуры — как более легковесный аналог оным, с прямым доступом к данным, и ваши сомнения решаются вообще идеально, нет объекта — нет проблем :)
Для языков без поддержки ООП и интерпретируемых языков — это так, с другой стороны компилируемый строго типизованный язык с поддержкой ООП таблицу вызовов может иметь только на этапе компиляции, и в результате переопределённые методы будут вызывать методы потомка, не переопределённые — родителя, так как тип (класс) на этапе компиляции будет известен.

Так что с одной стороны вы конечно правы, а с другой, если возвращаться к теме нашей дискуссии — если сравнивать например си и ди, как два компилируемых языка, то обе записи, вокруг которых и развернулся спор, будут равнозначны, обе выделяют память, инициализируют данные и предоставляют методы для работы с оными, которые в свою очередь сводятся к передаче контекста (данных объекта/структуры) в функцию обработки оных, GDateTime реализованный в виде объекта тут ничем не проигрывает, даже наоборот — приобретает, тот-же самый полиморфизм.
Там где нет нативной поддержки чего-либо — приходится довольствоваться соглашениями. В GTK например вызов gtk_window_new возвращает структуру, из которой, вычислив смещение, можно выцыганить, например, имя окна, что в принципе нарушает инкапсуляцию, однако-же есть соглашение так не делать, а пользоваться для этого функцией (методом) gtk_window_get_title. Или как в старом php или текущем яваскрипте — приватных методов и свойств нет, потому есть соглашение писать имена приватных методов с _, ничто не мешает вызывать их извне, но с точки зрения соглашения их можно вызывать только внутри объекта.

Ну и в конце концов в тот-же GTK+ работает по тому-же принципу, и если цепочка наследования выглядит как GObject > GtkWidget > GtkBin > GtkWindow — то методы виджета нужно вызывать через gtk_widget_*, а методы окна через gtk_window_* — однако-же никто не спорит что GTK+ — объектно-ориентированная библиотека.

Так что я повторюсь — это детали реализации ооп для конкретного языка/библиотеки и т.д. и т.п., где-то реализовано больше, где-то меньше, где-то так, где-то иначе.
На асме очень удобно под gtk+ писать, вызовы те-же, а накладных расходов на них в разы меньше, да и не нужно постоянно вызывать GTK_WIDGET, GTK_WINDOW и т.д. и т.п., можно просто передать указатель, типизации-то нет.
И в чем проблема?
void g_date_time_ext_add_month(GDateTimeExt* datetime, int month) {
  g_date_time_add_month((GDateTime*)datetime, month + 1);
}

Это уже детали реализации.
Так в этом и разница, вы не даете полный доступ к полям данных через методы, вы даете полный доступ к результатам работы методов, это могут быть поля данных в одной реализации, обработанные поля данных в наследнике, например, и левая байда из /dev/random в другой реализации, при этом сохраняя общий интерфейс.
Хочу напомнить что си вообще не относится к языкам с нативной поддержкой ооп, и обобщённых алгоритмов работы с объектами в нём вообще нет, GObject — частная реализация библиотеки glib, тоже что реализация GDateTime не связан с GObject ровным счётом никакого отношения к нашему разговору не имеет.

Но таки различие в чём? g_date_time_new — аллокатор, инициализирует данные, размещает их в памяти и возвращает на них ссылку, new DateTime тоже, g_datetime_add_* — работают, принимая первым аргументом контекст выполнения, в time.add* контекст указывается до точки, принципиальная разница где?

И я таки на всякий случай отнаследую вам вашу структуру
struct GDateTimeExt {
  struct GDateTime dateTime;
  gboolean extended;
}

gboolean g_date_time_ext_get_extended(GDateTimeExt* datetime) {
  return datetime.extended;
}

void g_date_time_ext_set_extended(GDateTimeExt* datetime, gboolean extended) {
  datetime.extended = extended;
}

int main(int argc, char** argv) {
  GDateTimeExt* datetime = g_date_time_ext_new();
  g_date_time_add_month((GDateTime*)datetime, 1);
  g_date_time_ext_set_extended(datetime, TRUE);
  return 0;
}
И в чем-же тогда его отличия от класса? Даже так, в чем кардинальные отличия двух приведённых мной вариантов?
А, ну это безусловно, каждая команда си — это десяток, если не сотня драгоценных ассемблерных инструкций! К тому-же инлайновое переписывание команды printf заново — на си могут счесть говнокодом, а на ассемблере это уникальная, эффективная реализация и устранение внешних зависимостей :)
«бозон Хиггса — это непонятная хрень» — а вы разве не согласны? :)
Не понял о чем вы — но наверное да :)
Мы-то разговор ведем в ключе того что ленивые программисты придумали мерзкий ооп чтобы кода больше вышло — так что с этой точки зрения самый эффективный код вот:
	mov eax, источник
	mov ebx, назначение
	mov ecx, 10
loop:
	dec ecx
	mov byte [ebx], [eax]
	inc eax
	inc ebx
	cmp ecx, 0
	jnz loop

строчек — аж целых 10!
Вы шутите? Это-же ассемблер, одна инструкция — одна строка, и каждая инструкция — низкоуровневая, для копирования области памяти через индексные регистры их уже нужно 4, да и для вызова процедуры копирования памяти столько-же, так как 3 инструкции — для задания откуда, куда и сколько, которые нужны так или иначе, 300 строк тут — вообще пшик, было-бы желание.
Даже смущаюсь спросить, это
GDateTime* time = g_datetime_new();
g_datetime_add_years(time, 1);
g_datetime_add_months(time, 2);
g_datetime_add_weeks(time, 3);
g_datetime_add_days(time, 4);

и это
DateTime time = new DateTime();
time.addYears(1);
time.addMonths(2);
time.addWeeks(3);
time.addDays(4);

не кажется вам слегка похожим? Только не приходится каждый раз писать g_datetime_, оно в принципе во всех биндингах gtk+ на объектно-ориентированные языки примерно так и выглядит.
А как-же call/ret? В асме тоже есть процедуры :)
1
23 ...

Information

Rating
Does not participate
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity