Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 5
×

Дейкстра уничтожил goto

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті


Дейкстра тот, кто заложил основы структурного программирования. Так что когда будете в следующий раз писать if, else, while, то вспомните этого героя. В этой статье расскажу о нем и его подвиге по уничтожению goto.

Родился Дейкстра в Роттердаме в 1930 году. Детство у него было не легкое. Сначала пережил бомбардировку Роттердама во время Второй мировой войны, потом оккупацию Нидерландов Германией.

В 1948 он окончил среднюю школу с лучшими отметками по физике, биологии, химии и математике. А уже в возрасте 21 года его взяли на работу в Математический центр Амстердама и там он стал первым программистом в Нидерландах.

Интересно, что в 1957 году, когда он хотел жениться на Марии Дебет, то для вступающих в брак нужно было указывать свою профессию. И когда он показал в документе, что он программист, то власть с него посмеялась, ведь никогда не слышала о такой профессии. Поэтому пришлось указать в документе профессию «физики-теоретик».

Его очень задело, что в то время никто не воспринимал программирование, как что-то серьезное. И его руководитель Адрианом, сказал, что он может быть основателем профессии и превратить программирование в науку. Так он и поступил...

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

Так в марте 1968 года была опубликована статья «О вреде оператора Go To» в журнале CACM и у мира программирования жопа запылала. Если тогда был бы интернет, то его бы закидали злобными сообщениями и мимасами))

За то людишки 10 лет закидывали гневными сообщениями редакторов многих на то время популярных журналов. В итоге в этой войне победил Дейкстра. Языки развивались и goto сдавал свою позицию, так что не дивно, что в современных языках нет goto, а все юзают парадигму структурного программирования.

Дейкстра за многие годы работы убедился, что инструкций goto вредна для структуры программы. Как бы фигово, что можно взять и в любой момент перескочить из одной части программы в другую. И поэтому он и предложил заменить goto конструкциями if//else и do/while/

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

А вот его замечание из статьи:
«Мое второе замечание — то, что наши интеллектуальные силы в большей степени связаны со статическими отношениями, и что наши способности представлять процессы, развивающиеся во времени, развиты относительно плохо. Исходя из этого, мы должны делать (как мудрые программисты, осознающие свои ограничения) все возможное, чтобы сократить концептуальную пропасть между статической программой и динамическим процессом, чтобы сделать соответствие между программой (разворачивающейся в пространстве текста) и процессом (разворачивающимся во времени) настолько очевидным, насколько это возможно.»

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

Спасибо Дейкстра, что дал нам возможность if-кать и else-ть.

Залетайте в мой Telegram канал, в котором уже 1400 подписчиков — t.me/javascript_vue

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному5
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Появилось что сказать. Если Дейкстра создал структурное программирование — он поступил плохо! Любое состояние программы можно описать набором истинных условий — выполнившихся для данных этой программы правил. Этих правил для каждого состояния разное количество. Не всегда одинаковое. Поэтому таблица правил указывающая на состояние не удобна. Но она маст хэв. Ибо иерархическое понимание такой таблицы это чисто конкретная ошибка моделирования.
Я теперь вижу программу как набор состояний, детерминированных правилами. И эти правила для каждого состояния могут быть и различными и совпадающими по логике и количеству, но не то и другое одновременно.
Да, такую «неравномерную» по количеству столбцов таблицу трудно реляционной сделать и в базу данных добавить, однако и описание такой таблицы в виде структуры Дейкстры тоже лажа.
Именно здесь обработка ошибок сидит. Та самая, которая так все портит в красоте структурной программы. Ведь метка появляется, не так ли?
А при программировании программы как неравномерной таблицы переходов от состояния к состоянию эти неоднозначности исчезают.
Так что, структуре нет, а матрице правил для переходов в то или иное состояние да.
Машина Тьюринга в моей теме. dou.ua/...​rums/topic/31466/#2006230
Правила в примере по ссылке могут быть сведены в таблицу — матрицу.
Оценка такой матрицы может обнаружить «забытые» логические последовательности и самые неожиданные корреляции.
Вот и думайте теперь — возможно ли написать безошибочную программу?

Забудь про таблицы. Chaitin to the rescue here he is!

Here is how you show that there is no solution, that there is no algorithm for determining whether or not a diophantine equation can be solved, that there will never be one.
It turns out that there is a diophantine equation that is a computer. It’s actually called a universal diophantine equation, because it’s like a universal Turing machine, math-speak for a general-purpose computer, one that can be programmed to run any algorithm, not just perform special-purpose cal- culations like some pocket calculators do. What do I mean? Well, here’s the equation:
Diophantine Equation Computer:
L(k,n,x,y,z,...) = R(k,n,x,y,z,...)
Program k Output n Time x,y,z,...
(The real thing is too big to write down!)

There’s a left-hand side L, a right- hand side R, a lot of unknowns x, y, z, . . . and two special symbols, k, called the parameter of the equation, and n, which is the unknown that we really care about. k is the program for the computer, n is the output that it produces, and x,y,z,... are a multi-dimensional time variable! In other words, you put into the equation L(k, n) = R(k, n) a specific value for k which is the computer program that you are going to run. Then you focus on the values of n for which there are solutions to the equation, that is, for which you can find a time x, y, z, . . . at which the program k outputs n. That’s it! That’s all there is to it!
arxiv.org/pdf/math/0404335.pdf 33 страница

Програма — это просто число: целое, положительное, большое

Неужели все сводится всего лишь к разным вариантам -> ( правил проверки select и правил изменения состояния delete, insert ) ?
Такой воркфло получается:
п.1. данные селектируются, полученное определяет некое состояние, состояние это некий процесс изменения данных.
А далее см. пункт 1 или если достигнуто искомое то оутпут и выход.

Хз, попробуй реляционной алгеброй дополнить ряд 1 2 5 7 11 ...

Р. алгебра не причем тут? Берем некое число 12 и зная, что ищем простые отбрасываем, берем 13 оно подходит. Проверяем условие делимости только на себя самое. А селект по нечетным ускорит определение простоты.

А откуда у скл, как предполагаешь, ноги растут?

PS: следующее число кстати куда писать собираешься: еще одна строка или еще один столбец? :)

А была разве поставлена задача хранения простых чисел? Нет, спасибо.

Задача — дополнить ряд 1 2 3 5 7 11 ... :)

Поддержи мой проект и я расскажу тебе о возможном решении проблемы хранения сверх больших простых чисел.
Любое простое число это такое нечетное число (кроме 2) которое не делится ни на одно нечетное число до него, за исключением 1.
Но когда числа становятся очень большими, возникают определенные сложности с их хранением.
Я задумался над этой проблемой и получил пару идей из астрала.
Вот так все было. И теперь мне не терпится поделится полученной информацией, но хочется с пользой для себя/своего проекта это сделать.

Спасибо, конечно, за возможность сделать что-то хорошее для тебя и твоего проекта, но у меня свои диллеры.

Например 15 тоже отлично подходит как следующий за 11 элемент ряда 1 2 3 5 7 11 ...

Если шо на видео лысый объяснит почему так: youtu.be/iJ8pnCO0nTY

Или \epsilon > 0 если уж выходить за множество натуральных чисел

Та я не шарю в сложном английском. Мне уровня детсадика надо (небольшой словарь самых простых и самых употребимых слов и словосочетаний, или предложений из пары -тройки слов) А потом уже надо добавлять в эту смесь более навороченные варианты. И вот так постепенно, можно изучить язык, со временем научиться понимать сколько угодно сложное произнесенное.
А сразу в воду, там где глубоко и чтобы непременно сам выплыл — это не для изучения языков. Да и плавать я с "поплавка","звезды" учился.
Кстати, вышеизложенное часть моего проекта.

подсказываю
все простые числа (кроме 2) — нечётные числа, и поэтому для них можно считать шагами по 2p, начиная с p*p где p-простое.

Все сводится к состояниям. Акторы, стейт машины.
Не все состояния валидны, И не все валидные состояния обладают ожидаемым поведением.
И если есть несколько компоненов, их состояния могут не соответствовать друг другу.

Невалидное состояние — креш или зависание.
Неожидаемое поведение — логический глюк или обрыв сценария использования.
Несогласованность состояний — глюки многопоточности.

Состояния описываются переменными (инты, байты, биты), стеком и регистрами.

Как говорили на одной конфе, программы делятся на 3 вида:
1) Обработка данных — то, что ты и написал. Прочел — переварил — выплюнул.
2) Хранение состояния. Сигнал на линии может быть чем угодно, в зависимости от предыдущих сигналов.
3) Интерактивный ввод — кнопочки на экране.

Обычно, в программе есть 2 или 3 из этих аспектов.
Пример: калькулятор. Он и умеет что-то считать, и запоминает нажатые кнопки и предыдущие значения, и позволяет тыкать мышкой по экрану.

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

Кажется я только что обнаружил нехватку важных инструментов на своем сайте. Сейчас предлагаемыми мной средствами можно описать структуру данных, но не ее изменение во времени, да и сам таймер для отдельной ветки трудно будет (или невозможно) создать/запустить.

Поэтому таблица правил указывающая на состояние не удобна. Но она маст хэв.

Охренеть как ты прав.
Хотел бы поправить. Эта «таблица» есть список событий, а указание на состояние подписка. Если совсем просто адресация, И эта «таблица» содержит функционал «программы». Если к этому добавить динамическое редактирование этой таблицы, получаем то, об чем я давно говорю.

Если состояние это процесс, то таблица состояний это таблица процессов.
Любой процесс выбирается на основании обнаружения истинности некоторой последовательности условий в ходе сравнения.
Например: слово «слово» сравниваем поэлементно с началом связи «л»


//жуткий не полный псевдокод
Для i от 0 до n (exclude)  { Если i-тый элемент === 'л' то возврат истина }
Кстати, ’л’ это хардкод и к слову сказать, хардкод рулит
Например, в нейронках подбираемые/подобранные коэффициенты это хардкод.
И этот хардкод продают, между прочим. Продажный хардкод. Вот так.
Если состояние это процесс

Если. Но, это не процесс, а результат процесса. Потому иногда подменяют понятием «событие», называя его именем новое состояние при изменении состояния. Например, состояние а равно 1, присваивая 0 переменной а (это процесс ) получаем событие Is Null. Определение состояния это не процесс, а определение истинности события. А если и процесс, то мета процесс. И его можно выполнять параллельно. Здесь в обычном программировании (и архитектуре процессора) заблуждение заключающееся в том, что команды сравнения и остальные команды содержатся вместе в теле программы. Их философия различна. Потому конвейерное выполнение это не изобретение инженеров, а исправление ими ошибки архитекторов философии процессора.

И получился у меня вот такой абстрактный алгоритм:

Входные данные проверяются по всему списку (или таблице) условий.
Все данные на все условия каждый раз! проверяются. Это важно.
Условия, дающие истину, указывают на действие с некоторыми данными из этих входных данных. Определенного рода действие.

То есть все сводится к:
Проверка условия — выполнение правила
Где правило это запись действий с данными.

Получить входные данные — определить подходящие условия (которые истинны для входного набора) — получить правила, которые нужно применить — выдать/сохранить во внутренней памяти измененные правилами новые данные.
И так делать пока не станет истинным условие нахождения ответа.
Полученные в итоге данные будут самим ответом.

Ты переизобрел Blackboard architectural pattern
en.wikipedia.org/...​ackboard_(design_pattern
www.hillside.net/...​7/Proceedings/lalanda.pdf
Штука очень крутая, и чуть ли не единственный подход, когда есть данные, но нет единственного общепринятого алгоритма их обработки.

Входные данные проверяются по всему списку (или таблице) условий.
Все данные на все условия каждый раз! проверяются. Это важно.

Это лишнее. Проще можно. При адресации к данным проверяется наличие подписок. Если есть подписка, по проверяются события на которые есть подписка. И если событие истинно, то переход по подписке. Если подписок нет, то ничего не делается. Таким образом программа превращается из последовательности команд в граф вершины которого концепты (команды или данные), а ребра это подписки адреса по которым переходим. Граф выполняется параллельно насколько хватает шин данных для адресации.

Тебе не хватает простых примеров. Ты хочешь скрыть правду от OpenSource ?
Определения дай мне всех слов из твоего словаря, при этом эти определения должны состоять из слов моего словаря. Что такое адресация к данным? И не заставляй читай свои статьи. Я уже не так не делаю, а выкладываю повторно, снова и снова все тоже самое. Это более эффективно. И в смысле распространения тоже.

Тебе не хватает простых примеров. Ты хочешь скрыть правду от OpenSource ?

Не понял. Ты об чем? Я рассказываю все когда меня слушают и пока понимают. О каких примерах речь?

Что такое адресация к данным

Адресация имеется в виду физическая. У меня 4 вида адресации. 1-Просто адресация, 2-адресация для чтения,3- для записи и 4- для инициализации. Первый вид присутствует в любой адресации, второй и третий очевидно, а 4-й для создания нового концепта из адресуемого. Само собой адресация тоже события, на которые можно подписаться. Данные я называл что б не уточнять и не запутывать. Потому что у меня и команды и переменные и все остальное единого формата, и я все называю концептами.

Я уже не так не делаю, а выкладываю повторно, снова и снова все тоже самое. Это более эффективно. И в смысле распространения тоже.

С этим согласен. Спрашивай. Только не очень по тупому..

Тем более, что мы говорим, как мне кажется, об одном и том же. Но я хочу отойти от порядков следования и указаний на порядок следования, потому что в случае одновременных проверок условий (определения их истинности или ложности) теряет смысл упорядоченность.
У меня одновременные проверки всех доступных (текущих) данных на все условия рано или поздно заканчиваются и высвечивают некоторую неупорядоченную последовательность истинности или ложности.
Такой ассоциативный массив получается пар: условие1 — истинно, условие2 — ложно
Если этот массив расценивать как уникальный идентификатор, ключ, то подходящий к нему замок это действие с данными.

Но я хочу отойти от порядков следования и указаний на порядок следования, потому что в случае одновременных проверок условий (определения их истинности или ложности) теряет смысл упорядоченность.

Это правильно. Ибо наличие команд сравнения и перехода в тексте программы фиксирует своим нахождением момент проверки состояния, и обычно требует наличия булевой переменной для сохранения необходимого для анализа и перехода по этому состоянию. В чем философский смысл этой проверки. Для примера и общности я приведу классическое высказывание. «Снег белый». В программе это будет выглядеть как выражение (типа Snow.Color= White). Истинность этого выражения проверяется по факту. Снег может быть белый, а может и нет. Это понятно. Но, есть еще пару вопросов. 1. А интересует нас какого он цвета? И 2. Когда нас это интересует?
Ответ на первый вопрос решается наличием подписки на это событие. Сам синтаксис такого события (SWhite) будет выглядеть так.****** Пока пропустим. Но, ясный пень такое событие надо как-то обозвать. В обычном языке сами буквы «Снег белый» могут применяться как определение высказывания, и как имя этого высказывания в зависимости от контекста. Здесь я красиво вышел из ситуации когда вместо слов истинность выражения «Снег белый» написал «истинность этого выражения». А теперь по тому вопросу, когда нас это интересует? А тогда когда мы обращаемся по имени!!! Т.е. по адресации! Вспоминаем как работает машина! Адресация, проверка на наличие подписок, анализ на истинность события и переход по подписке. Булевы переменные не нужны. Обращения к событию (к концепту) достаточно.

Ну или вообще можно устроить switch на кортежах (из извращений C#).
devblogs.microsoft.com/...​e-with-patterns-in-c-8-0

Как это переписать без goto?

if (0 != d.count())
{
	interval += d.count() + "day(s) ";
	goto h_l;
}
else
{
	h_l:
	if (0 != h.count())
	{
		interval += h.count() + " hour(s) ";
		goto m_l;
	}
	else
	{
		m_l:
		if (0 != m.count())
		{
			interval += m.count() + "min(s) ";
			goto s_l;
		}
		else
		{
			s_l:
			if (0 != s.count())
			{
				interval += s.count() + "sec(s) ";
			}
		}
	}
}

!d.count() ?: interval += d.count + "day(s) ";
!h.count() ?: interval += h.count + "hour(s) ";
!m.count() ?: interval += m.count + "min(s) ";
!s.count() ?: interval += s.count + "sec(s) ";

а чим таке не вгодило?

if(0 != d.count()) interval += d.count() + "day(s) "; 
if(0 != h.count()) interval += h.count() + "hour(s) "; 
if(0 != m.count()) interval += m.count() + "min(s) "; 
if(0 != s.count()) interval += s.count() + "sec(s) ";

або і взагалі

int counts[] = { d.count(), h.count(), m.count(), s.count() };
char * intervals[] = { "day(s) ", "hour(s) ", "min(s) ", "sec(s) " };
for(int i = 0; i < sizeof(counts) / sizeof(int); ++i){
    if(0 != counts[i]) interval += counts[i] + intervals[i];
}
(правда, якась дурнувата версія С виходить, так що це може навіть і не C)

або на пітоні :)

data = [(d.count(), "day(s)"), (h.count(), "hour(s)"), (m.count(), "min(s)"), (s.count(), "sec(s)"), ]
interval += " ".join(str(e[0]) + e[1] for e in data if 0 != e[0])

¬ Null S [ d.count, h.count, m.count, s.count] ’ Группа целевых событий S
String B:interval+("day(s)" «hour(s)» «min(s)» «sec(s)» )S
По моему так еще проще. Условия выделены в группу событий, а при формировании строки группа выражений выполняющихся в зависимости от индекса выполнившегося события группы S.
Более того результат можно получить адресуясь к атрибуту B. Команды у меня не выполняются последовательно, а только при их адресации.
Можно даже сделать разные выражения при адресации для чтения и для записи.

А шо это у вас группа событий не сигма-аддитивна?! В академотпуск и на повторный год!

А шо это у вас группа событий не сигма-аддитивна

Ты сам понял что ляпнул? Ты вообще о чем? О синтаксисе? Так там скобки есть. Какое объединение? О содержании? Так очень даже регулярное множество. А семантика так вообще не алгебра. Ты решил понтануться, а получилось сел в лужу.

Согласно ваших же слов, у вас там целая группа событий, а не какое-то там множество.

Студент Кузьмин, вы уж там или женитесь и жену называйте как хотите, или идите в академотпуск и возвращайтесь когда словами налево-направо попусту разбрасываться перестанете. Вы что не видите, что у вас на концептуальном уровне концы не сходятся? А что ж тогда будет, когда мы начнем реализацию «в железе» обсуждать? Вы ж абсолютно будете не в состоянии объяснить под каким углом атому хлора нужно будет атаковать атомы брома, чтобы вся эта алгебраическая структура запела и заиграла новыми, уже совсем не фон-Неймановскими красками

вас там целая группа событий, а не какое-то там множество.

Давно дал определение групп. Читай документы. Хамить не надо. Сам мальчик. Да, некоторые понятия определены не так как принято. Если я так назвал, то были тому причины. Но, не надо меня учить. Причем тут математические определения? Есть магнитное поле. И оно не имеет отношения к математическому полю.

Ах так! Но с собственными определениями это вам в Большую Академию Наук оф Юкрейн, а не в публичный интернет

Но с собственными определениями это вам в Большую Академию Наук оф Юкрейн, а не в публичный интернет

Приходится. Вот чем класс отличается от типа? В принципе понятно. Класс порождает объект, а тип значение. А у меня единый формат и нет разницы. Как назвать то, что порождает? Придумай.

Класс — это тип тоже.

Класс — это тип тоже.

Я тебе больше скажу тип это тоже класс. Вот до меня не доходит. Ты повторил то, что я написал, только с умным видом. А вопрос понял? О терминах говорили.

Вот до меня не доходит.

К сожалению, очень заметно.

К сожалению, очень заметно.

Умничать и быть умным это разные вещи.

Себ Тейлор уже давно придумал. Жалко вот только что НАНУ отстаёт от моды лондонских рейвов на пару десятков лет

What did you just call me?
— Lepton.
What the hell is that?
— You wouldn’t understand.
Whoa, wait a minute. Speak slowly then.
— Ok, A lepton is a z-particle.
So?
— Do you know what protons and electrons are?
Yeah.
— Ok, what are they?
They’re those teeny, tiny things that atoms are made of.
— Well, leptons are even smaller.
youtu.be/44ldOumF2wQ
Do you know what protons and electrons are?

....

leptons are even smaller.

звучить круто, тільки треба переконатися, що ніхто не знає:
* що електрони це теж лептони (en.wikipedia.org/...​i/Lepton#Table_of_leptons)
* що говорити про розмір того що не має розміру... ну такоє
* що навіть якщо під «більше»-«менше» розуміти масу, то навіть мюони важчі, а тау-лептони так взагалі

Деякі людські істоти розвиваються трошки інакшим чином, ніж особини з основної популяції. Це називається «Розлад Аутичного Спектру», в особливих випадках у таких діточок є «найулюбленіша тема для розмови» до якої вони зводять будь-яку дискусію на будь-яку тему. Це називається Особливий Інтерес людини з РАС: www.ambitiousaboutautism.org.uk/...​haviour/special-interests

Наскільки я можу судити, в англомовному середовищі, коли дитятко постійно говорить про свій Special Interest, його називають «%Special Interest Name% head». Цитата наведена з гоа-транс треку який назвається «Lepton Head».

Також, щоб прояснити деякий такий «творчий» засіб, пропоную ознайомитися з наступними треками того ж автора:
youtu.be/y7OIhBIIkIY
youtu.be/vNqrQvekn74
youtu.be/SG3TYYNq2eU

Я так підозрюю, він час од часу знаходить «зносячі дах» діалоги/монологи, які буквально змушують подивитися на природу реальності під незвичним кутом, и розвиває їх у трансові мікси. Думаю, що у гуманітарії для такого приколу навіть існує спеціальне ім‘я, яке не «дадаїзм»

ознайомився... ну мені якось важко оцінити — я більше фанат NDH.

Та я не то шоб великий фонат гоа-трансу; здебільшого це такі собі польові этнографічні дослідження по-інтернету. А там багато намішано: психонавтична наркоманія і психоз, різноманітні теорії змов і духовний пошук, місхьорд мудрість і сім смертних гріхів, таке і інше

Власне «музикального контенту» у порівнянні зі стовпами західної класичної традиції там дійсно кіт наплакав

Мабуть найбільш оптимальне рішення

Никак. Тут без goto никак не обойтись, и судя по всему этот пример наглядно доказывает что выводы Дейкстры были в корне неверными.

А в чём там вообще задумка? Что без ветвления алгоритма в том или ином виде не обойтись — ежу понятно, но в чём цель вообще оптимизировать эту часть задачи? Для меня участок кода выглядит редко используемым. От того что он будет работать на 0.1нс дольше — суммарно за всё время пользования всеми пользователями будет потрачено не больше времени, чем на написание, переписывание, тестирование и понимание кода.

Потому основную массу кода нужно писать максимально понятно. Пусть и не оптимально.

Это был сарказм. Нету тут никакой оптимизации, а более того подобные конструкции вполне могут изменить flow graph так что оптимизатор компилятора ничего не сможет оптимизировать. Короче говоря code mauris vulgaris (говнокод обыкновенный). Релевантные имплементации примера есть в ответах.

if (d.count()) 
{ 
  interval += d.count() + "day(s) "; 

  if (h.count()) 
  { 
    interval += h.count() + " hour(s) "; 

    if (m.count()) 
    { 
      interval += m.count() + "min(s) "; 

      if (s.count()) 
      {
        interval += s.count() + "sec(s) "; 
      } 
    } 
  } 
} 

Ну да, у Майка правильный вариант. Извращенцы...

У Лекса Фридмана на ютуб-канале есть интервью с Кнутом на эту тему :)

Так вот как выглядит Правило 34 для IT :)

Ну т.е. если у тебя 0 дней, то ты вообще ничего не положишь в строку.

А может кто-то человеческим языком объяснить, ЧТО оно вообще делает, в смысле что задумано?
Потому что по коду читатель не гарантированно поймёт в любой из версий. В том числе тот, кто это писал.

Понять можно, но решение, как бы сказать, достаточно странное. Глянь код Майка, он то самое делает.

В том-то и дело, что он делает магию. А какова цель этой магии, что хотелось — нихрена не понятно.

баянистый ответ Дейкстре, который я еще когда-то в Фидо читал: www.lib.ru/ANEKDOTY/non_pas.txt

теперь это можно считать историческим анекдотом

Добре, що він до COMEFROM не добрався

Ещё бы склонения слов подправить, а то впечатление, что перевод иностранца. Если бы не обороты типа «жопа запылала». :)
Если я напишу, что goto всего лишь инструмент, и тоже может пригодиться, — меня заклюют как Дейкстру. Но я напомню про return, break, try-except... Это варианты goto, но более специализированные и ограниченные, которыми труднее запутать программу.
Кстати, про буллинг, — если бы Дейкстра написал коммент или статью на сайте типа Хабра или другом сайте с рейтингами-кармой, то его сразу бы «похоронили». Это как пример для руссуждения о недостатках общения в современных условиях, когда масса может заклевать любую конструктивную мысль.

А что ты хотел от русского мира? Он такой. Зачмырили — ай, молодцы.
Украинцы в этом плане воспитаны не лучше. Радость — это когда у соседа корова сдохла.

Корова сдохла — это почин, хата сгорела — это оргазм, а радость — это где-то посередине %)

Эээ... Дейкстру где буллили? Я про весь мир говорил. Психология такая у людей стала. Думать, сомневаться не хотят, только лайкают-дизлайкают бездумно.

так вроде Боб писал, что Дейкстру и хейтили как раз по поводу goto, просто интернетов не было и приходилось негадовать через печать.

Оригінал вказували?
Robert Martin:
youtu.be/ya1xDCCMh7g?t=2768

I suggest you not include “don’t use goto.” Instead, be more clear, concise, and thorough, and state, “don’t use code constructs that disrupt the natural execution flow, readability, and modifiability of your code via the use of needless mid-method returns, labeled break and continue statements, and the goto keyword.” After all, readability, maintainability, and robustness are the underlying goals when we put together guidelines.

www.drdobbs.com/...​why-is-goto-bad/228200966

Чувак рекомендует пихать код во вложенные бранчи, не думая, сколько там отступов получится. В реальности после 5 отступов код уже сильно уехал, и править такое неулобно.
Поэтому я считаю, что лучше сделать несколько раз
if(error_condition) return false;
вверху функции и потом уже ставить основной код на уровне тела функции.
+ при этом основной код хорошо видно — он не теряется в лапше if ... else ... else if

Таких конструкций следует избегать превращая их в Select-Case. Это и наглядней легко редактируемо. Любая вложенная конструкция If , очевидно превращаема в Case. В моем языке предусмотрена работа с группой событий (S) и группой выражений (V). И перечислимый тип (i) , определяемый как индекс группы концептов у которого тип является именем группы.
Event S ( s1, s2, ... , sn) ’группа событий
S i ’ Определение перечислимого типа
Void V( v1, v2, ...,vn)i ’ Здесь i подстрочное как индекс группы выражений.
выполнение такого кейса начинается с адресации группы V
По правилам выполнения группы подстрочное и надстрочное значение всегда проверяется при выполнении группы а все значения находятся в памяти вместе с типом. При проверки типа процессор обнаруживает перечислимую переменную и обращается за получением его значения к группе событий S. Индекс первое истинного события и является индексом выполняемого выражения в группе V

Вообще-то делать отступы на каждом IF и не обязательно. Равно как и писать открывающую скобку с новой строчки. Это придумано во времена, когда платили за количество строк кода. С тех пор много воды утекло, но вот маразм...

По-хорошему, читабельный код должен быть похож на натуральные языки. Вы же не пишете «если» с новой строчки, не открываете после него скобку, и даже запятые не ставите. Так и с кодом: множество «если» очень часто становятся нечитаемыми — проще сформировать из этих «если» новые переменные, которые будут понятны человеку. Зато в коде можно делать абзацы, разбивая его на логические части. Это как минимум позволяет увидеть, в каких точках код можно протестировать.

Ну и вообще отступы более 2 символов — лишь попытка размазать говно по тарелке. Опять же, унаследованная со времён, когда код оценивали деньгами по количеству кода.

Обратная сторона маразма — когда пытаются писать код в 1 строчку, чрезмерно используя синтаксический сахар. Совершенно забывая, что память человека синтаксического сахара не имеет, и вся эта «магия» моментально становится обфускацией.

Да, лучше отсечь все очевидно неприемлимые случаи сразу (отфильтровать мусор), чтобы основной алгоритм был проще и яснее.

Итак, вы пересказали содержимое вступление к главе 4 книги «Чистая Архитектура» Р. Мартина. Стало быть, в Telegram-канале можно прочитать пересказ остальных глав? ;)

Вассаби говорит, что любой безусловный переход это вырожденный условный переход.

Вассаби говорит, что любой безусловный переход это вырожденный условный переход.

Почему вырожденный? Есть четкое условие — программа дошла до адресации команды перехода. Или пришла очередь выполнить команду перехода. Чем не условие? Последовательное выполнения команд, в общем случае, отнюдь не аксиома.

Забыл клавиатуру дома, поэтому трудно думать «вслух_впечать» юзая экранную.
Это между ветвление и не_ветвление. Исчезает альтернатива. Такого рода вырождение.

Так по сути и есть, но то что с машинной точки зрения вырожденное условие — для человека просто более сложное условие, которое сложно записать в одну строчку с кодом.

Львиная доля безусловных переходов — это обычный return. Ты знаешь, чем его заменить, чтобы код стал понятнее? Не думаю.

Я уничтожил If и циклы. Только мало кто понимает что это будущее программирования.

Если не разрекламировать — то не будущее.

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

Думаю, для начала нужно определить, чем оно лучше существующих систем. Для этого нужно знать, что уже есть. Для этого надо английский и почитать книжки. Например, github.com/...​ion.in.Scala.and.Akka.pdf

Я уже столько перечитал, что и сам могу написать. Но, главное что я уже столько сделал и придумал, что у меня нет восхищения перед забугорьем. Мне стыдно за свою страну, что не делает свой продукт, и вузы что занимаются копированием чужого продукта. Своей мысли нет. Мы очень многое можем делать сами.

Мы очень многое можем делать сами.

Теория проверятся практикой. Практика показывает, что не можем.

Практика показывает, что не можем.

Просто отсутствие амбиций. Проще купить. Никакого головняка и возможности подерибанить. И политика государства не стимулирует.

Просто отсутствие амбиций.

Как же? А мнение на форуме, что русские ничего не умеют и тупее украинцев? Разве это — не амбиции?

Только мало кто понимает что это будущее программирования.

Пост-апокалиптическое будущее...

Скорее, как в Еве

Это как в игре про космические корабли, которые бороздят просторы вселенной в которой не работают законы небесной механики?

Ну хз.. как по мне Михаил больше по «программированию» церебрал процессинг юнитов очевидно выступает. Пример в псевдокоде:

Підписка на событие «михаилу нужны деньги» <- 
     обработчик «же нема пасижур»:
           ~ перечисли сколько не жалко

Ну и конечно, строковый формат текста в таком случае, к сожалению, пока плохо приспособлен для передачи того, что Хомскі и сотоварищи назвали бы «the Deep Structure»

Не, то был мультик

Мудацтво, як і свобода волі — non-observable property :P

Но умный. Мне вот таки прикольно — без него придумали бы (кривую, тупую, но удобную для обучения) схему 4-х уровней сложности грамматик, или нет?

(кривую, тупую, но удобную для обучения) схему 4-х уровней сложности грамматик, или нет?

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

Ну хз.. как по мне Михаил больше по «программированию» церебрал процессинг юнитов очевидно выступает. Пример в псевдокоде:

Обратил внимание на прямую зависимость. Чем меньше человек понял, так сильнее старается сказать что-то умное. И редко получается. Потому как для того что б понять мозги нужны. А с этим проблемы.

Из умного что-то сказать, так это только вы пытаетесь, но пока безуспешно

Не вы первый. Машина Тьюринга уже работает именно так.

Не вы первый. Машина Тьюринга уже работает именно так.

Само определение детерминированности и полноты связано с появлением МТ. Где вы увидели что я оспариваю первенство Тьюринга? Увы, у компьютеров из недетерминированности только прерывание. И в языках программирования тоже. Вот тут я готов поучаствовать.

Увы, у компьютеров из недетерминированности только прерывание.

Ну почему же. Есть генераторы случайных чисел.

Вот тут я готов поучаствовать.

Почётный значок «Участник броуновского движения».

Если эти генераторы имеют seed то они уже детерминированы, а таких псевдослучайных генераторов большинство.

Потому я и сказал про генераторы _случайных_ чисел :)

Ну почему же. Есть генераторы случайных чисел.

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

Давайте такі функції вкладеними if-ами переробимо :-D

static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
{
        struct dw_pcie *pci = imx6_pcie->pci;
        struct device *dev = pci->dev;
        unsigned int offset;
        int ret = 0;

        switch (imx6_pcie->drvdata->variant) {
...
        case IMX8QXP:
        case IMX8QM:
                ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
                if (ret) {
                        dev_err(dev, "unable to enable pcie_axi clock\n");
                        return ret;
                }
                ret = clk_prepare_enable(imx6_pcie->pcie_per);
                if (ret) {
                        dev_err(dev, "unable to enable pcie_per clock\n");
                        goto err_pcie_per;
                }
                ret = clk_prepare_enable(imx6_pcie->phy_per);
                if (unlikely(ret)) {
                        dev_err(dev, "unable to enable phy per clock\n");
                        goto err_phy_per;
                }
                ret = clk_prepare_enable(imx6_pcie->misc_per);
                if (unlikely(ret)) {
                        dev_err(dev, "unable to enable misc per clock\n");
                        goto err_misc_per;
                }
...
                if (imx6_pcie->drvdata->variant == IMX8QM
                                && imx6_pcie->controller_id == 1) {
                        ret = clk_prepare_enable(imx6_pcie->pcie_phy_pclk);
                        if (unlikely(ret)) {
                                dev_err(dev, "can't enable pciephyp clock\n");
                                goto err_pcie_phy_pclk;
                        }
                        ret = clk_prepare_enable(imx6_pcie->pciex2_per);
                        if (unlikely(ret)) {
                                dev_err(dev, "can't enable pciex2 per clock\n");
                                goto err_pciex2_per;
                        }
                }
                break;
        default:
                break;
        }

        return ret;
err_pciex2_per:
        clk_disable_unprepare(imx6_pcie->pcie_phy_pclk);
err_pcie_phy_pclk:
        clk_disable_unprepare(imx6_pcie->misc_per);
err_misc_per:
        clk_disable_unprepare(imx6_pcie->phy_per);
err_phy_per:
        clk_disable_unprepare(imx6_pcie->pcie_per);
err_pcie_per:
        clk_disable_unprepare(imx6_pcie->pcie_inbound_axi);
        return ret;
}

Я недавно как раз коммитил подобный переделанный код в NXP репозиторий — он очень плохо поддерживается и расширяется, особенно если что-то вставить в середину, то потом начинается каша. Основная идея — отказ от множественных точек перехода — должна быть только одна. Дальше при уничтожении или деинициализации просто проверяем — если был создан ресурс — уничтожаем, не был создан — проходим мимо.

Когда действительно такой срани много — я делал так:

#define INIT(err, f, message) { \
    if (!err) { \
        int ret; \
        ret = f; \
        if (!ret) { \
            message; \
        } \
        err |= ret; \
    } \
} \

int err = 0;

INIT(err, function1(), dev_err(dev, "unable to enable pcie_axi clock1\n"));
INIT(err, function2(), dev_err(dev, "unable to enable pcie_axi clock2\n"));
INIT(err, function3(), dev_err(dev, "unable to enable pcie_axi clock3\n"));
INIT(err, function4(), dev_err(dev, "unable to enable pcie_axi clock4\n"));

if (err) {
     // shutdown;
}

Непагано виглядає, але тільки для простих випадків. А якщо потрібні додаткові перевірки перед винесенням рішення? Ускладнення макросів може привести до зворонього ефекту. Колись довелось правити помилки в макросі із логікою та математикою строк на 30. Так простіше вийшло розгорнути це в нормальний вигляд, бо макроси майже недебагопридатні.

До речі, для пробінгу вже давно проблема визволення ресурсів вирішена через модель devm_*, але ось такий наведений в мене зоопарк зустрічається трохи менше, ніж скрізь по ядру.

А что бы случилось, если бы вместо #define просто скопипастил код?
Да, кода получилось бы больше. Но читаемость однозначно повысилась бы. Мозг очень хорошо распознаёт повторяющиеся структуры и шаблоны, более того, считает это зоной комфорта.

если бы вместо #define просто скопипастил код

а потім цей код треба буде поміняти...

Ок, чудово. Давайте перепишемо ядро Linux на C++ :-D

Давно нужно было заменять извращения выше на С с классами.

Не получится. Т.к. компилятор для этих хардварных приблуд — есть, скорее всего, лишь сишный.

Это не хардварные приблуды, а ядро Линуха.
Но да, оно быстро компилится потому что там нет С++.
И быстро работает — частично потому же.

Это не хардварные приблуды, а ядро Линуха.

Тем более. За первый же коммит «плюсного» кода — Линус самолично руки поотбивает и тут же забанит.

И будет прав.

П.С. К тому же, ядро Линукса используется на многих хардварных приблудах, для которых есть лишь сишный компилятор.

Но да, оно быстро компилится потому что там нет С++.
И быстро работает — частично потому же.

А в чем отличие C от C++ то после компиляции?

В том, что в С++ программисты намного чаще юзают полиморфизм, STL и прочие операторы new. Что приводит к худшей локальности доступа. Что приводит к тормозам.

А в чем отличие C от C++ то после компиляции?

полиморфизм/виртуальные вызовы => медленнее/больше код
исключения/хэндлеры => медленнее/больше код/даже баги компиляторов

+ malloc быстрее new, но это отчасти потому что new умеет обрабатывать исключения.

malloc быстрее new, но это отчасти потому что new умеет обрабатывать исключения

По большому счёту, нью это обёрнутый маллок и есть. Другое дело, что в концепт нью/делит (вызовы маллок/фри) — не улёгся реаллок, с довыделением.

Так и есть, обёртка имеет свой оверхед.

Где доказательства?

в ядрі linux взагалі немає функції malloc. Там є різні *kmalloc*, *vmalloc*, *alloc_pages*, etc. тож, порівнятим C+±ний new тут просто ні з чим, бо це зовсім інший рівень керування пам’ятю.

Якщо справді цікаво, як в ядрі керувати пам’ятю, то є дока по цьому API:
www.kernel.org/...​test/core-api/mm-api.html

Я не мав конкретно ядро лінукс, але цікаво, дякую почитаю. Стосовно new і malloc, там різниця в часі їх роботи не є вирішальною на швидкодію програм написаних на С/С++(провіряв на gcc і g++), але вона є.

Зрозуміло.
Просто ця гілка як раз присвячена ядру лінукс :)

Ок, чудово. Давайте перепишемо ядро Linux на C++ :-D

А взагалі, для юзерленду я не бачу якихось переваг C над C++, тільки для дуже вузького класу задач, де дійсно потрібно вижимати із заліза 100%.

А взагалі, для юзерленду я не бачу якихось переваг C над C++, тільки для дуже вузького класу задач, де дійсно потрібно вижимати із заліза 100%.

Вспомню классическую цитату:

„C++ is a horrible language. It’s made more horrible by the fact that a lot of substandard programmers use it, to the point where it’s much much easier to generate total and utter crap with it. Quite frankly, even if the choice of C were to do nothing but keep the C++ programmers out, that in itself would be a huge reason to use C.

In other words: the choice of C is the only sane choice. [...] I’ve come
to the conclusion that any programmer that would prefer the project to be in C++ over C is likely a programmer that I really would prefer to piss off, so that he doesn’t come and screw up any project I’m involved with.

C++ leads to really really bad design choices. You invariably start using the ‚nice’ library features of the language like STL and Boost and other total and utter crap, that may ‚help’ you program, but causes:

— infinite amounts of pain when they don’t work (and anybody who tells me that STL and especially Boost are stable and portable is just so full of BS that it’s not even funny)

— inefficient abstracted programming models where two years down the road you notice that some abstraction wasn’t very efficient, but now all your code depends on all the nice object models around it, and you cannot fix it without rewriting your app.

In other words, the only way to do good, efficient, and system-level and portable C++ ends up to limit yourself to all the things that are
basically available in C. And limiting your project to C means that people don’t screw that up, and also means that you get a lot of programmers that do actually understand low-level issues and don’t screw things up with any idiotic ‚object model’ crap.
...”

Нажаль, знову ж таки, є певні індустрії, де C++ де-факто стандарт, тому, подобається це комусь чи ні, працюючи в цим індустріях доведеться писати на C++.

є певні індустрії, де C++ де-факто стандарт,

Это какие-такие? :)

Скажем, последние 10 лет мои проекты заключались в повальном переписывании систем с C++ на C#. Это крупные энтерпрайз системы для индастри (софт конфигурирования всякого-разного аппаратного, от отдельных контроллеров/сенсоров, до цеха фабричного производства), медицина (десктоп-клиенты для всяких томографов/ангиографов) от концернов, которые все знают.
И признаться, серьёзной ниши для «плюсов» я сейчас не вижу.

Системный софт — C. Пользовательский софт — шарп, жаба, броузер или прочий (как правило, интерпретируемый/сэйф) зоопарк. А «плюсы» где?

Automotive, proprietary firmware, Embedded middle-ware, non-critical RTOS apps, etc.

Это какие-такие? :)

Драйвера GPU и всё что связано с около GPU, LLVM — всё на С++. Даже кошерная ламповая Mesa3D заражена большим количеством С++ кода.

Драйвера GPU и всё что связано с около GPU

Подозреваю, сами драйвера на C. Но возможно на „плюсах” обёртки для внешних потребителей (типа, автомотива).

„C — If you check the core software and drivers that NVIDIA develops to integrate with the hardware line, they are all low-level programming. There is no better programming language for code embedded on hardware items than C. NVIDIA was very secretive about its internal development until 2013 when they started supporting open-source software development. They have released several documents ever since and most of the documents mention C as the primary programming language used in the development of the core-level software. In fact, most of the companies who are into hardware-based software development, most of them still use C and C++ which brings us to the next most used language by NVIDIA software developers.”

Подозреваю, сами драйвера на C.

Kernel driver — это обычно очень маленький драйвер на С, в ядре (потому и на С), который ложит память из юзеровского буфера в тот, где может его достать аппаратура и даёт команду на исполнение и ждёт конца работы. Всё остальные, настоящие драйвера в основном на С++ и работают на user level, вот они формируют команды для GPU, программируют состояние и т.п. Для С драйвера это просто бинарный блоб данных и он работает обычным передастом. В качестве примера — посмотри OpenCL для Intel GPUs: 01.org/compute-runtime — всё на С++ кроме ICD loader’а.

В качестве примера — посмотри OpenCL для Intel GPUs: 01.org/compute-runtime — всё на С++ кроме ICD loader’а.

„кроме ICD loader’а” и самого драйвера. О драйвере сказано следующее: „аs a closed-source binary package” — и подозреваю, написан он-таки на C.

„OpenCL™ (Open Computing Language) is a low-level API for heterogeneous computing that runs on CUDA-powered GPUs. Using the OpenCL API, developers can launch compute kernels written using a limited subset of the C programming language on a GPU.”

„кроме ICD loader’а” и самого драйвера. О драйвере сказано следующее: „аs a closed-source binary package” — и подозреваю, написан он-таки на C.

До конца читай, все исходники доступны С там нет практически нет, например:

Например, гитхаб на это говорит:
github.com/...​l/intel-graphics-compiler

C++
75.3%

C
22.0%

потому что он дурной и считает *.h чистым С кодом.

In 2016, Intel started consolidating OpenCL software technology engineering support in an effort to provide a single unified offering for all the customers. The result is a new and improved OpenCL Driver stack (informally known as „Neo”), that is intended to replace both previous closed-source driver (aka „Classic”) as well as the Beignet driver. Neo is a cross-platform, open source driver provided under MIT license, created in modern C++, and developed using Test Driven Development methodology. Neo (Compute Runtime) uses the following ingredients to deliver a complete OpenCL Driver stack:

До конца читай, все исходники доступны С там нет практически нет, например:

Это я видел. Но там, вроде, нет исходников самого драйвера — лишь вспомогательные приблуды (рантаймы, компиляторы, итп).

Правда, пишут с OpenCL 2.1 — „introduced the OpenCL C++ kernel language, based on a subset of C++14”
с OpenCL 2.2 — „brings the OpenCL C++ kernel language into the core specification”
с OpenCL 3.0 — " New preferred language is C++ for OpenCL with many C++17 features."
en.wikipedia.org/wiki/OpenCL

Похоже, таки „плюсы”...

Это я видел. Но там, вроде, нет исходников самого драйвера — лишь вспомогательные приблуды (рантаймы, компиляторы, итп).

Он в ядре линукса под BSD лицензией: drivers/gpu/drm/i915.

fintech, gamedev и десктоп тоже — браузеры например

fintech, gamedev и десктоп тоже — браузеры например

Десктопный финтех — уходит на шарп/впф. Всякий «высокочастотный» — остаётся на с.

Десктоп — шарп.

Современный геймдев, часто, вообще шарп.

И что, на маке и линуксе C# игры норм работают?

И что, на маке и линуксе C# игры норм работают?

Вроде, да. «Ксамарины» там всякие — для простых поделок.

Десктоп — шарп это фейспалм. Дальше обсуждать вообще нет смысла, тут майкрософт головного мозга.

Десктоп — шарп это фейспалм. Дальше обсуждать вообще нет смысла, тут майкрософт головного мозга

У мелкомягких 90% десктопа. И 100% корпоративного десктопа. Потому да, десктоп = шарп.

А вскяие хипстеры со своими бубунтами — никому не интересны. Т.к. всё одно за софт не платят.

Обидві мови чудові для своїх задач. Як на мене, одна з переваг С — більш проста семантика, якщо комусь треба ООП в С є GObject, але це ще та приблуда. Семантика С++ з кожним новим стандартом стає все різноманітнішою, а старі підходи ніхто не змінює для збереження зворотньої сумісності.

Обидві мови чудові для своїх задач.

В тезисе выше, в основном идёт упор на майндсет. В том смысле, что средний хипстер не станет писать на C — соответственно, избавит сишный проект от своих нубовских корявок, полных багов.

Есть и другой валидный момент:

„And if you want a fancier language [than C], C++ is absolutely the worst one to choose. If you want real high-level, pick one that has true high-level features like garbage collection or a good system integration, rather than something that lacks both the sparseness and straightforwardness of C, and doesn’t even have the high-level bindings to important concepts. ”

„And if you want a fancier language [than C], C++ is absolutely the worst one to choose. If you want real high-level, pick one that has true high-level features like garbage collection or a good system integration, rather than something that lacks both the sparseness and straightforwardness of C, and doesn’t even have the high-level bindings to important concepts. ”

допустим, мне нужен UI на железе с ограниченными возможностями. какие в опу

garbage collection

?

допустим, мне нужен UI на железе с ограниченными возможностями. какие в опу

en.wikipedia.org/wiki/Ncurses

и никаких плюсов :)

смешно, да

Ну а как ещё? Если у тебя настолько слабый целевой комп, что не запустится клиент на WinForms — остаётся старый-добрый текстовый терминал. Или там, VisualBasic с вызовами сишного кода из библиотек/API.

Или ты всерьёз будешь рассматривать написание UI на MFC?

WinForms
VisualBasic
MFC

откуда вы эту хрень берете?
на таких устройствах я пишу UI на Qt/QML

на таких устройствах я пишу UI на Qt/QML

Ок, в качестве «тонкого UI-враппера» над сишным кодом — может работать.

Хотя, не уверен насчёт оптимальности для целевых платформ. Bсё-таки, нативные UI-библиотеки (маковские, андроидные, виндовые, итп) — должны быть продвинутее универсальной QTшной.

П.С. И, кстати, для концернов Qt ещё покатит. Но для рядового кодерка, ~4к/год за лицензию для коммерческого использования — малоподъёмные деньги.

маковские, андроидные, виндовые, ит

под железом с ограниченными возможностями я подразумеваю какойнить арм с макс 500МБ рам

я подразумеваю какойнить арм с макс 500МБ рам

Ну да. Там будет крутиться какой-нибудь андроид или прочий встраиваемый юникс. Сo своим нативным UI-API (для Андроида, к примеру, он на жабе).

Там будет крутиться какой-нибудь андроид

не будет

прочий встраиваемый юникс

будет

Сo своим нативным UI-API

ага. фреймбуффер. бгг

Это из сериала из нескольких компакт-дисков «майкрософт вижуал студио 2002». Там еще в chm формате были 2 статьи:
1 про разворот 3д графики посредством перемножения матриц на с++,
2 про представления графов в реляционных базах данных с примерами на SQL-92 через osql

одна з переваг С — більш проста семантика

дуже влучно. Взагалі я би сказав C сама «чесна» серед мов високого рівня, в тому плані що вона не робить нічого такого під капотом, що явно не задане.

исключения/хэндлеры => медленнее/больше код/даже баги компиляторов

Вот тут спорный момент. Если есть куча вызовов методов, и после каждого проверяется, что он вернул (есть ли ошибка) — для успешного сценария это будет медленнее, чем тот же код, когда методы void, но могут кинуть исключение. Потому что из кода ушли все if().

для успешного сценария это будет медленнее, чем тот же код, когда методы void, но могут кинуть исключение

Ок, похоже на то. По крайней мере, для современных компиляторов.

должно сильно зависеть от стиля написания

должно сильно зависеть от стиля написания

Это оценка при идеальном сишном и плюсовом коде.

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

При идеальном написании С++ не будет медленнее (написание будет одинаковым). Может быть быстрее через темплейты.
При среднем написании — будет медленнее.

При идеальном написании С++ не будет медленнее (написание будет одинаковым).

При одинаковом написании — это будет не C++, а C код. :)

Рукожоп это вообще характеристика человека, а не инструментов, которыми он пользуется.

Чем проще кодить на языке — тем больше рукожопов.

Скажем, на С сложно кодить, не понимая как пользоваться указателями — рукожопы особо не выживают.

В C++ об указателях уже можно особо не знать (кроме нью/делит и передачи по референсу) — рукожопов больше.

В жабо-шарпе не нужно заниматься управлением памяти — рукожопов вообще дофига.

Не погоджусь. Я на С/С++ бачив таку жесть, що впевнений, що рукожопство корелює хіба що з відношенням вйобства до зарплати. Якщо таке відношення низьке, відразу набіжать хомячки із ШАГу чи GoIT і будуть влаштовувати локальний ад. Жаба як раз для таких розрахована, там всі револьвери, якими можна прострелити ногу, прибиті гвоздями, але вони іноді треба для інших задач. І взагалі, зараз наче пітон модний, там можна робити всілякі непотребства.

Проще языка программирования я не знаю.

Я имею в виду реальные полезные приложения, а не «хелло уорлд».

Такие приложения сложнее всего писать на ассемблере, затем С, затем C++, затем жабо-шарп (легче всего).

А туда, где легче — и лезут больше. И рукожопов, соответстгвенно, тоже.

Згідний, ще від задачі залежить. На хабрі хтосб уже запилив статтю: habr.com/ru/post/347688 . Мене у свій час здивувало, що Fortran швидчий С. Але теж залежить від задачі.

так может написать только тот кто не знает ни с и с++

Тобі ніхто не заважає так вважати, але почитай хоча б це: habr.com/ru/post/347688 . Що конкретно тебе так не влаштовує?

К примеру, en.wikipedia.org/...​wiki/Microchip_Technology

Процы очень популярные, но в основном к ним есть лишь сишные компиляторы. Как правило, C90.

И Линукс там крутится: www.microchip.com/...​it-mpus/linux-os-for-mpus

Давайте такі функції вкладеними if-ами переробимо :-D

 Ну вот это как раз очень плохой пример использования goto — все обработчики ошибок специфичны для условных веток, и просто перенести clk_disable_unprepare, clk_disable_unprepare etc. + return вместо соответствующих goto — код станет лучше, и даже ифов дополнительных не надо.

Нет, там проскок по цепочке обработчиков — если зафейлился последний иф, то віполнятся все 5 обработчиков

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

Тут проблема что в С нет деструкторов. Для С++ легко делается через RAII.

Знал бы ты, во что обходятся потом потерянные break, и как сложно их найти при чтении кода.

кто использует goto, тот двоечник! © AI

Двоечник — один из 10 типов людей

один из 10

т.е. из 2х?

goto must be used locally and with great carefulness. A guru does know what he does.

Берем перше-ліпше ядро лінукс:
cryo@cryobook:~/work/gitlab/linux-toradex (toradex_5.4-2.1.x-imx)*$ grep -R «\bgoto » [a-z]* | wc -l
167871

Упс. 160 тисяч goto :)

З іншого боку, goto там використовується не для порушення та «запутування» логики, а тільки майже виключно як зручна обробка помилок й швидкий вихід із відкатом стану.

Це схоже на: майже до кожної помилки призводить неправильне використання оператора if. Тоді давайте заборонемо if.

карочь используеться вместо выбрасывания исключений. Но ядру линукса вполне простительно экономить наносекунды оверхеда в исключениях, ось всетаки :-)

ексепшини в C? Ню-ню.

у мікрософта є розширення для власне C, вони його SEH називають
docs.microsoft.com/...​ndling-c-cpp?view=vs-2019

Схоже що це все-таки тільки для С++ приблуда. Для С вони навіть прикладів ніде не наводять. Хоча може я помиляюсь.

Навіть вони самі пишуть, що рекомендують використовувати C++, а не SEH:
Although Windows and Microsoft C++ support SEH, we recommend that you use ISO-standard C++ exception handling. It makes your code more portable and flexible.

Це була відповідь на питання

ексепшини в C

Принаймні один з крупних вендорів заморочився і зробив таку штуку.
І чесно попередив про граблі :)

Насколько помню, if был уже с goto. Т.е. условные переходы — сама суть программирования. Когда запускается реакция на сигнал от датчика.

Т.е. условные переходы — сама суть программирования. Когда запускается реакция на сигнал от датчика.

Ну, так зачем условный переход? Так и пиши реакция на событие. Т.е. подписка на событие

А если у события есть аргументы? Например, датчик шлет температуру каждую секунду, а тебе надо держать температуру в заданных пределах.

void OnTemperature(const int value) {
    if(value <= lower_)
        TurnOnHeater();
    else if(value >= upper_)
        TurnOffHeater();
}
перепиши без условий

Элементарно. Создаешь события верхняя и нижняя граница. И подписываешься на эти события.
Вот пример класса термометра.
‘ На входе необязательные параметры верхняя (U) и нижняя границы (D).
@{Real (U=Void, D=Void) Fun [ ‘ и метод запускаемый при создании объекта
Up=U ‘ Устанавливаем значения верхней и
Down=D ‘ нижней границ.
] ‘ с возможностью параллельного выполнения
}
Class Thermometers
‘ Атрибуты
‘ Текущее значение Value
{ Real {Value |Change (←Up, ←Down), ‘с подпиской на событие Change и реакцией на события Up и Down
‘ Верхняя граница Up
Up |Change ←Up, ‘с подпиской на событие Change и реакцией на событие Up
‘ Нижняя граница Down
Down ?Change ← Down ‘с подпиской на событие Change и реакцией на событие Down
}
‘События
>Up Value ~ Up ‘ Событие Up происходит когда текущее значение больше Up
< Down Value ~ Down ‘ Событие Down в случае текущее значение меньше Down
}
Вертикальная черта-подписка. Up и Down и имена атрибутов и событий. У меня могут быть одинаковые имена. Подсвечиваются цветом и имена события знаком ←

А сам термометр внутри как узнает, какое событие послать?

А сам термометр внутри как узнает, какое событие послать?

Это класс. При создании объекта атрибут Value необходимо подключить у интерфейсу. Подключение заключается в подписке на метод получающий значение, или запускать этот метод по времени. Если необходимо что-то выполнить, то подписываешь это к нужному событию. подписок допускается до 16 .

Метод вернул температуру 16. Какое событие будет отослано?

Это смотря как организовал. Если ты хочешь периодически опрашивать, то создаешь таймер в классе и при создании объекта задаешь интервал опроса. И по событию таймера Click обращаешься к методу чтения значение с интерфейса и по событию <> Value присваиваешь это значение Value

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

Я предлагаю свой инструмент.

Потому что не осилил существующие.

Та разные и деды есть. Этот же сам рассказывал что бред несёт уже лет 20 минимум.

а вот если мир на тебя какнет..

И шо?

Кроме того, у тебя получилось не меньше кода, и его не проще читать, чем у меня на С.

Кроме того, у тебя получилось не меньше кода, и его не проще читать, чем у меня на С.

Меньше кода или меньше текста? )) Текст можно уменьшить с помощью ролей. Это стандартный шаблон с верхней и нижней границей. Так же есть роли с производными и вторыми производными. Тогда все это выглядит одной строчкой. Я хотел показать механизм. Код результата с ролями будет еще меньше.

По поводу легкости чтения это вопрос привычки.

Про ***ю в жопу то же самое говорят. Так что можешь использовать как аргумент для сравнения.

А ты вслух это прочитай (не при дамах), может поймёшь, почему людям этот ****** не зайдёт.

Та я как бы не для дебилов пишу. И совсем не для аргументов понтоваться перед дамами.

А вот мог бы для дебилов написать — прикинь сколько деньжищ заработал бы!
Посмотри на устройство управления автомобилем: ну для дебилов же. И покупают.

А вот мог бы для дебилов написать

Я за текст на форуме))

предложил заменить goto конструкциями if//else и do/while/

какая феерическая чушь

За многие годы я утвердился во мнении о том, что квалификация программистов — функция, обратно зависящая от частоты появления операторов go to в их программах. Позже я открыл, почему оператор go to производит такой пагубный эффект, и я убежден в том, что оператор go to должен быть отменен в языках программирования «высокого уровня» (т.е. отовсюду, кроме, возможно, простого машинного кода).
Edsger Wybe Dijkstra
"Go To Statement Considered Harmful

про замену безусловного перехода на условый я даже комментировать не хочу — хорошо что сам Dijkstra до этого дня не дожил

Я так все равно и не понял где чушь.

Я так все равно и не понял где чушь.

нехай є змінна A
якщо вона менша 5 — тобі треба присвоїти змінній B 1
якщо більше/рівне — то змінній C 10

напиши це на ЧИСТИХ goto, без if/else

% ./a.out -2147483643
B = 1, C = 0
% ./a.out -2147483648
B = 0, C = 10

А де ти в тому бачиш натяк на підтримку топікстартера?

ці брудні хаки :-)
але ріспект

напиши це на ЧИСТИХ goto, без if/else

для чого і яке це має відношення до попереднього коменту?

для чого і яке це має відношення до попереднього коменту?

саме пряме

"

про замену безусловного перехода на условый я даже комментировать не хочу — хорошо что сам Dijkstra до этого дня не дожил

"
if/else — умовний
goto — безумовний
що не ясно?

В тебе з логікою все гаразд? В процитованому тобою мова йде про заміну безумовного на умовний, а ти мені пропонуєш для чогось іфи на готу переписати. От я і ще раз питаю в чому сенс цієї геніальної пропозиції.

В тебе з логікою все гаразд? В процитованому тобою мова йде про заміну безумовного на умовний, а ти мені пропонуєш для чогось іфи на готу переписати. От я і ще раз питаю в чому сенс цієї геніальної пропозиції.

в тому, що ти не розумієш у чому чушь? чи ти зрозумів, але прикидуєшся?
чи ти не знаєш, як if і goto в асемблерному коді реалізуються?

Ок. Я не зрозумів у чому чуш тому що у процитованій фразі її немає. Як if і goto реалізується у асемблерному коді немає ніякого стосунку до вищесказаного від слова зовсім, тому що мова йде тільки про МВР. Інтерпретація автора комента слів Дейкстри невірна тому що термін безумовний перехід ширше поняття ніж goto (виклик функції чи повернення так само в більшості випадків це безумовні переходи), тому мова не може йти про заміну в термінах переходів, а виключно в термінах структур управління. Так само твоя пропозиція використовувати goto замість if немає стосунку до предмету обговорення тому що мова йде про зворотнє.

тому мова не може йти про заміну в термінах переходів, а виключно в термінах структур управління.

так отож, нарешті :-)

Що нарешті? В мене є великі сумніви що ти читав цей тренд уважно.

Даешь Интернет из Гипертекста на ЛаТеХе!

Ой сорри, а где пост про то, как Кнут Дата Саенс изобрёл?

Дейкстра выступал против плохо структурированного кода, к которому, по его наблюдениям вело злоупотребление goto.
Сам оператор «goto» никак не противоречит идее структурного программирования, о чем писал еще Дональд Кнут в своем Structured Programming with go to Statements.
Более того, «соратники» goto, в виде «break» и «continue» вполне успешно существуют в большинстве современных (не функциональных) языков, хотя их использование явно противоречит идее «структурного програмирования».

На сегодня есть только три парадигмы программирования

Мир не ограничивается вашими знаниями, и не есть таким, как вы его себе представляете.

кхем,

в большинстве современных (не функциональных) языков

завели всякие iterate until, collect и так далее. эти операторы в юзер коде как и сами циклы — не нужны, а скорее вредны как источник излишней сложности и багов.

Ну а с другой стороны в том же окамле в отсутствие всех этих брейков и иже с ними вполне себе юзают эксепшны для выхода (пример github.com/...​ter/src/batList.mlv#L1191) — чтобы сделать код более «плоским» и простым для понимания и/или оптимизации... Так что истина где-то посередине как обычно :)

Зря юзают, это ружье чехова, которое рано или поздно выстрелит в кого-нибуть?

Підтримую, сам вже третій рік на scala в продакшені без while/break/return/var/throw. Goto — взагалі дикість

В «Чистій архітектурі» Мартін про нього пише більше. Він ще поняття тестування і відповідності вводив і ще багато чого іншого.

ну и совсем неприличное, уже не о чистой математике а об Идоле многих:

«Вычислительная наука имеет не большее отношение к компьютерам,
чем астрономия — к телескопам».

и на всяк случай, про тупня Дейкстру:
В 1972 г. он был награжден премией Алана Тьюринга

и нагуглилось попутно неплохое обсуждение
В чем разница между информатикой и программированием?
qastack.ru/...​r-science-and-programming

А вообще для программирования дейкстра очень много хорошего и полезного сделал.

навигация, о5 же

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

int do_some_stuff() {
    FILE *some_file;
    char *some_buffer;
    int result;

    pthread_mutex_lock(some_mutex);
    some_file = fopen(some_filename, "w");
    some_buffer = (char *)malloc(some_buffer_size);

    result = sub_1(some_file, some_buffer);
    if (result != 0) {
        goto finally;
    }
    result = sub_2(some_file, some_buffer);
    if (result != 0) {
        goto finally;
    }
    result = sub_3(some_file, some_buffer);

    finally:
    free((void *)some_buffer);
    fclose(some_file);
    pthread_mutex_unlock(some_mutex);

    return result;
}

Замена деструктора

Это сишный код — тут нет деструкторов.

Но вложенные ифы — решат проблему.

они не решат проблему, они ее создадут

Ифы это несмертельно. Более того, в твоём примере — не нужна переменная result и экономится одно присваивание на каждом вызове ( sub_1, sub_2, sub_3 ) :)

внєзапно

int do_some_stuff()
{
    FILE *some_file;
    char *some_buffer;
    int result;

    pthread_mutex_lock(some_mutex);
    some_file = fopen(some_filename, "w");
    some_buffer = (char *)malloc(some_buffer_size);

    result = sub_1(some_file, some_buffer);
    result = result != 0? sub_2(some_file, some_buffer): result;
    result = result != 0? sub_3(some_file, some_buffer): result;

    free((void *)some_buffer);
    fclose(some_file);
    pthread_mutex_unlock(some_mutex);

    return result;
}

тег < code > поламаний і це пічаль

Внезапно медленнее будет работать

Так, буде.
Але у коді, де є malloc та fopen, те уповільнення на мікросекунди (нано- ?) мало кому щось дасть, але читабельність чуть підніме.
А там, де ми рахуємо такти, буде вже зовсім інший код, ближчий до асемблера, ніж до C. І навіть, можливо, з goto

И внезапно, по-другому. Когда логика будет сложнее, очень сложно потерять это самое «по-другому». Да и зачем, когда язык позволяет try — finallу, которые просто идеальны для читаемости кода.

У випадку безкомпромісних хейтерів goto, хочеться запитати кращу аналогію такого запису:

for(int i = 0; i < width; i++)
{
	for(int j = 0; j < height; j++)
	{
		if(array[i][j] == 0)
		{
			goto loop_break;
		}
	}
}
loop_break:

У функцію та return. Я не є безкомпромісним хейтером, але таке мабуть порефакторив.

А якщо ці два цикли та декілька рядків коду після loop_break є логічною одиницею, то доведеться висмоктувати назву функції з пальця.
Інший варіант, якщо в нас в даній області видимості багато змінних (в даному прикладі, для простоти, їх немає), то доведеться передавати їх всі в функцію (можливо навіть як не константні посилання або вказівники), що є не дуже ок.

Тоді декілька рядків коду після loop break пхається замість goto break перед return, наприклад. Це — пошук чогось там у масиві, то назву можна придумати.
Багато змінних не так часто зустрічається, якщо про таке говорити, то непогано б конкретний приклад. Там часто якщо дофіга змінних, то швидкість не так критична і можна у лямбду іх закепчурити. А якщо потрібна швидкість, то може бути швидше не робити подвійний цикл, а обійти все у одному, бо там де потрібна швидкість двовимірні масиви звичайно щільно лежать у пам’яті.
Ну і я і такого пописав, але от не можу згадати приклад, де варто було б. Не кажу, що такого взагалі нема.

От знайшов «бойовий» приклад: github.com/...​upport/spine/Skeleton.cpp
Рядки 164-192

Не ну тут вообще жесть с выпрыгиванием перед цикл

Але в цілому суті не змінює

От ще один кейс github.com/...​rt/spine/Triangulator.cpp 85 рядок.
Хоча складається враження, що місцями цей код пишуть повні неадеквати.
Навіть якщо взяти коментар в цьому ж рядкові

Там можна було через && ці 3 виклики написать. Чи врятувало б від goto — не знаю, вже не можу серед ночі такий код розпарсить)

Пару примеров с моего проекта:

	if(src_codecs[0] == dst_codec)
		selected = dst_codec;
	else if(src.PreferFirstCodec())
		selected = FindPreferredCodec(src_codecs, dst.GetClientSupportedCodecs());
	else if(dst.PreferFirstCodec())
		selected = FindPreferredCodec(dst.GetClientSupportedCodecs(), src_codecs);
	else {
		for(unsigned i = 0; i < SUB_LAST; ++i)
			if(src_codecs[i] == dst_codec) {
				selected = dst_codec;
				goto usedstcodec_selectsubcodec;
			}

		selected = FindBestCodec(dst.GetClientSupportedCodecs(), src_codecs);
	}

usedstcodec_selectsubcodec:
	// Apply selection
	if(selected < SUB_LAST) {
		subcodec_ = selected;
		return true;
	}
Здесь и во многих подобных местах goto используется как замена Питоновскому for ... else ...
#define READ_INT(name) 				\
	if(param == #name) {			\
		if(!value.IsDigits())		\
			goto not_a_number; 		\
		(name) = value.ToNumber();	\
		continue;					\
	}
Макрос для парсинга конфига. В парсере 100500 таких макросов подряд, которые все выпрыгивают в единый обработчик ошибки.
Также в парсере CLI команд — выпрыгивание из циклов поиска имени команды в разных таблицах на общий обработчик ошибки.
Исключения сильно раздувают код, поэтому отключены.
template <typename strategy>
void 	SingleIndex<strategy>::DeleteEntry(const unsigned entryid) {
	ASSERT(!IsEmpty());

	const unsigned 	index = FindIndexForEntry(entryid);
	ASSERT(index <= size_);

	int	delete_index;
	if(index_[index] == entryid)
		delete_index = index;
	else {
		// Search the equal range
		for(delete_index = index - 1; delete_index >= 0; --delete_index)
			if(index_[delete_index] == entryid)
				goto deleteentry_indexfound;
			else if(CompareEntries(entryid, index_[delete_index], entries_))
				break;
		for(delete_index = index + 1; delete_index < (int)size_; ++delete_index)
			if(index_[delete_index] == entryid)
				goto deleteentry_indexfound;
			else if(CompareEntries(entryid, index_[delete_index], entries_))
				break;
		ASSERT(false);	//The entry was not found in equal range
	}

deleteentry_indexfound:
	--size_;
	if(delete_index < (int)size_)
		memmove(index_ + delete_index, index_ + delete_index + 1, (size_ - delete_index) * sizeof(*index_));

	Validate();
}

тю, банальная рекурсивность: «если вот это вот найдено, то пожалуйста, перезапустить с самого начала»

Тільки проблема в тому, що в нас 3 точки виходу

А якщо ці два цикли та декілька рядків коду після loop_break є логічною одиницею, то доведеться висмоктувати назву функції з пальця.

Что-то у меня прям предчувствие, что там парой рядков кода не ограничиться, а в сумме будет весьма печально. Вообще за высокий cyclomatic complexity надо палкой бить.

for з іншого боку — це вже готова ф-ція з результатом (в данному прикладі — це і та j). Ніщо не завадить встановлювати ці значення як заманеться та порівнювати їх в циклі та за межами, якщо вони визначаються ззовні. Їх «екстемальні» значення можна визначити «промовистими» константами.
#define GETOUT −1;
int i = 0;
for (;i >= 0 && i < 1000; ++і){ if(something()) { i = GETOUT; break; } }
if(i == GETOUT) {...}

Я би в 100% випадків робив би на ф-ціях, але чисто теоретично можна і так.
PS Звісно, можна взагалі без break, якщо докопуватися.

А що має робити код? Обов’язково порефакторю, якщо буде задача

Поки не придумав що він має робити. Головне як він має це робити — без зайвих викликів, без зайвих змінних, та головне, не втрачати в читабельності.

Від виділення цього коду в функцію з return замість break все в будь-якому разі покращиться:
1. Батьківська функція стане меншою
2. Цій функції можна дати зрозуміле ім’я, що позбавить необхідності писати коментарі
3. Цю функцію можна зробити константною, що підвищить безпеку
4. Цю функцію можна буде перевикористати
5. Ми трохи наблизимося до «S» в SOLID, оскільки початкова функція «шукала нуль в матриці + робила ще щось», а от кожна з двох нових функцій буде виконувати рівно одну свою задачу.
6. Ну і ми позбавилися goto :)

І код стало гірше читати, бо раніше уся логіка була вкупі, а тепер — розмазана по кількох функціях, котрі разом з оголошеннями ще й більше місця займають

Код не стало гірше читати, бо він став краще структурований. 200 рядків логічного коду легше прочитати, ніж 150 намішаного. Пам’ятаю, Роберт Мартін якось пояснював, коли функція виконує рівно одну річ — це тоді, коли цю функцію не можна розділити на дві. Так от, базову (ту, де було два цикла і код після мітки) — можна було поділити. А оцю, де тупо пошук нуля — вже не можна (ну, не вдаваючись до ідіотизму). Більше того, ота базова функція теж стала читатися краще, оскільки дія «пошук нуля» логічно лежала на нижчому рівні абстракції, ніж інша логіка цієї функції, якій для чогось треба було про цей нуль знати. Ми не лише зменшили розмір тієї першої функції, а й наблизили її код до оперування сутністями одного рівня, що добре.

Правило розділення на модулі: маленька зв’язність між модулями та велика — всередині модуля www.hillside.net/...​020/videos/PaulRayner.mp4
Коли наша функція робить якусь логічно одну річ з точки зору класу — не треба цю одну річ дробить на атомарні кроки.

весьма спорное заявление. ваш код делает очень дофига вещей, «с точки зрения класса»

С точки зрения домена он делает что-то вменяемое.
Например, вот тут:
dou.ua/...​ign=reply-comment#1969673
В первом случае метод выбирает общий кодек, во втором — макрос читает настройку из конфига, в третьем — метод удаляет запись из индекса.
Когда методы такой гранулярности, во многих случаях в классе их не очень много. Если их начинать дробить — класс превратится в равиолли с сотнями методов. Это — загрязенение пространства имен и нечитаемо.

От знайшов «бойовий» приклад: github.com/...​upport/spine/Skeleton.cpp
Рядки 164-192

В ЯП в которых нет goto для этих случаев оставили break. С переходом по метке ессно.
и не часто, но встречается.

Дейкстра же писал во времена когда goto был нормой, и использовался не реже чем if и прочие операторы перехода

В ЯП в которых нет goto для этих случаев оставили break. С переходом по метке ессно.
и не часто, но встречается

Схоже на #define break goto
:-)

В скале например нету ни брейк ни континиэ, ни готу. (Ну вернее функ котрол для ниасиляторов добавили (как функцию а не часть яп!), но за его применине принято бить по лицу. )

В питоне есть else после цикла. Он один из основных юзов гото (различать выход из цикла через break и через завершение итерации) покрывает.

И зачем тут гото? Разбей на две функции

От знайшов «бойовий» приклад: github.com/...​upport/spine/Skeleton.cpp
Рядки 164-192

Знайшов ще один цікавий випадок застосування goto: github.com/...​etwork/Lua_web_socket.cpp
Хоча до самого коду дуже багато запитань =)

Можна ще скобочки прибрати. Але тоді набіжить інша категорія хейтерів.

Можу помилятися, але скажімо, MISRA C/C++ забороняє подібну конструкцію:

if(condition)
    operation;

Я сам матерюсь коли так роблять у складних, і не дуже, випадках, але іноді, в простих випадках так робити зручно, там де це дозволяють стандарти. Хоча краще взагалі в один рядок if(condition) operation; а ще краще if(condition) {operation;}, коли таких конструкцій багато, наприклад флаги.

Для любителей в один рядок есть ternary: result = !condition ?: operation;

коли таких конструкцій багато, наприклад флаги.

Для большого количества флагов есть

switch(bitfield & ALL_USED_FLAGS)
{
    case FLAG1:
                        break;
    case FLAG2:
                        break;
    case FLAG1 | FLAG2:
                        break;
    default:
                        break;
}

Згоден, але бувають і такі випадки:

 if (!strcmp(command,"clear")) clear();
  else if (!strcmp(command,"echo")) echo();
  else if (!strcmp(command,"if")) ifthenelse();
  else if (!strcmp(command,"include")) include();
  else if (!strcmp(command,"jump")) jump();
  else if (!strcmp(command,"label")) label();
  else if (!strcmp(command,"log")) log();
  else if (!strcmp(command,"next")) next_command();
  else if (!strcmp(command,"partition")) partition();
  else if (!strcmp(command,"print")) print();
  else if (!strcmp(command,"python")) python();
  else if (!strcmp(command,"quit")) quit();
  else if (!strcmp(command,"shell")) shell();
  else if (!strcmp(command,"variable")) variable_command();

Вообще это уже таблицей делать надо бы

Тим не менш зробили так, щоб не паритись. Це як з goto, загалом погано, але іноді корисно і зручно, оскільки просто.

у «ти код свій покажи» є один великий недолік
не видко історії його створення.

а вона частенько вказує що
не
зробиЛИ так
а
зробиЛОСЬ так

Shit it! %)

Ну можно ж массивчик там создать или мапу на худой конец, типа xarrays в ядре линукса.

Shit it! %)

Да, науковий код він такий, і це ще елегантно порівняно)

Я щось не розумію, що робить strcmp?

сравнивает строки, если == то возвращает 0, в остальных случаях либо больше либо меньше 0. Просто в C своя особая логика с нулями и булевой алгеброй.

если == то возвращает 0

И эти женско-логичные будут нас учить как не надо в GOTO? Действительно, если строки равны, почему бы не вернуть FALSE — охудивительно ж код читается. Вместо того чтобы тупо переопределить оператор сравнения для строки.

Потому что strcmp возвращает три значения, а не эквивалент true/false.

Но в коде это потом читается как false

Ну предложи что должна вернуть функция, разбирающая какая из строк больше, в случае, когда строки равны.

50 оттенков нуля %)

а это надо? Это совершенно контр-интуитивно. как, собственно и весь сишный код.

— здраствуйте, это прачечная?
— ***чечная! Это топик про оператор goto!

потому что это string compare а не string equals
strchr можно подсунуть в качестве компаратора при сортировке

А чем функциональность отличается?

А как ты строки сортируешь?

При помощи тайпклассика Ordered.

А он как сортирует?

Вжуууууух, и готово!

Кстати, намного более prolific подход чем все эти SOLID-ы и прочие голубцы с протёкшим обстракциями

Как напишешь так и будет сортировать.

Это скорее претензии к контексту, вернее автору, который применяет контекст. В контексте strcmp("blabla", something) == 0 это уже не читается как false.

Оно хуже читается (длиннее строка, пробелы)

что лучше, табы или пробелы? :)

Смотря куда их совать

ох, паруччик, вы такой шутник

Табы явно травмоопаснее пробелов.

Табы. Или пробелы. И это «или» исключающее.

Синтаксически правильнее было бы переопределить оператор сравнения. Даже если язык не позволяет переопределять операторы, можно было именно для стринга сделать переопределение прямо в компиляторе.

Почему так: стринг крайне распространённый вид инфы у людей, можно сказать основной примитив. Да, он не оптимален. Но при современной скорости вычислений проще пожертвовать десятком операций, чем пытаться переделывать людей.

Для начала нужно отметить что стринг в C совсем не какой-то особый тип, а по сути разновидность интерпретации некоего непрерывного участка памяти и это как часть универсальной работы с указателями одна из парадигм этого языка. Поэтому даже отбросив технические нюансы делать такое в C было бы просто концептуально неправильно.

Всё сложнее ассемблера концептуально неправильно. Да и ассемблер тоже. Давай писать в машинных кодах.

Всё сложнее ассемблера концептуально неправильно.

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

Это уже демагогия. Когда мы говорим о концептуальности элементов языка ми имеем в виду соответствие ими неких внутренних для языка критериев.

Ты прав глобально и не прав конкретно. И ужас в том, что можно сказать и наоборот. Все парадигмы программирования жестко привязаны к архитектуре процессора. Сначала появился адрес возврата. Так появились функции. Затем появились классы опираясь на функции. Затем java унифицировала синтаксис обнаружив общность. Prolog не вписывался никуда с экспоненциальным распуханием. Функциональное программирование казалось волшебной палочкой, но зашло в тупик инициализации задачи. Императивное программирование рулит по праву диктатора. И все это в тупике перед реальностью физического мира с его параллельностью и реакцией на события. Что никак не гармонирует с принципом последовательного выполнения команд. Тупик!

Еретик! Есть только один бог и имя ему J.H.W.H. Conway и он изобрел абсолютно все числа из пустоты за семь дней!

Сначала был бог и имя ему Тюьринг, затем было слово его, затем машина имя его.

С богом нет противоречий. Как минимум из полноты МТ. Просто Дейкстра говорит о детерминированной МТ. Даже прерывания у него вызвали небольшое разочарование. И я его в этом поддерживаю. На то время, это шаг вперед. А я говорю совсем о не детерминированной машине. С распараллеливанием. Это совсем другое мышление.

Когда мы говорим о концептуальности элементов языка

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

Не согласен. Человеческий мозг хочет упорядоченности, ему сложно адаптироваться к взаимно противоречивым понятиям. Концептуальность в основном об этом и имеет вполне реальную экономическую составляющую. Читаемость это производная. Если у тебя в голове целостная картина мира, то и читаться будет проще. Пример с strcmp довольно показателен, потому что ! в C мире имеет несколько отличную семантику от, скажем, ! в Java мире при том что есть сценарии где она (семантика) пересекается, т.е это вещи из двух концептуально разных миров и, несмотря на все их сходства, читаться они должны по разному.

Мышление заложено в архитектуре процессора. Язык это вариации на тему архитектуры.

Да куда б ни было заложено, лишь бы не приходилось головой работать. Не только потому что это тяжело и муторно, так ещё и медленно, и ошибок дохрена, и результат не гарантирован.

Сумеешь работу на компьютер переложить — молодец. Не сумеешь — значит ты создал генератор убытка. Зачем — знает лишь мудрец лохматый.

Сумеешь работу на компьютер переложить — молодец. Не сумеешь — значит ты создал генератор убытка. Зачем — знает лишь мудрец лохматый.

Не вижу противоречия. Концепции это стандарт мышления. И как любой стандарт служит для снижения расходов.

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

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

Поэтому снобствующие всегда будут бухтеть в сторону мейнстрим языков и массовых бест практик.

Мне понравилось в одном обсуждении фпшников какого-то супер фп:
Не взлетит: ЯП для работы с которым требуется чтение нескольких научных монографии в год -не годится для продакшена.

Было и будет — концепции в ЯП являются следствием стандартов чел мышления а не наоборот.
Вернее только те приживутся что соответствуют.
Либо не требуют огромных усилий для понимания.

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

Если бы «обыденное мышление» определяло концепции, то мы бы до сих пор считали землю плоской. Концепции должны соответствовать реальному физическому миру. Именно это соответствие делает концепцию актуальной и формирует «обыденное мышление». И никак не наоборот. Понятно, что процесс восприятия не мгновенный, но необратимый. Так что я не волнуюсь за свою работу. Жаль только, времени.

Программирование не является наукой, и решает не вопросы соответствия физическому миру, а вопросы удобства ручки молотка.
для руки хомо сапиенеса а не парнокопытного сферического коня из вакуума. В котором по мнению Дейкстры обитают теоретики

Концепции должны соответствовать реальному физическому миру.

Сейчас всё более моден «Data-oriented design». Согласно которому ООП-концепты (создание в коде сущностей, соответствующих реальному миру) дело, конечно, хорошее — но на существующих аппаратных архитектурах тупиковое.
Т.к. не предоставляет возможности увеличения быстродействия кода (а оно нужно).

Само ООП, и его разные трактовки и способы употребления появилось как раз потому что в целом начхать на быстродействие кода а важнее -скорость разработки.
За исключением узких областей,и системного ПО

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

Но теперь ситуация изменилась. «Закон Мура» мёртв — а софту нужно продолжать расти.

А понятный для человека код — приводит к уменьшению скорости разработки?
Или вы нетнули на автомате?

Про код тоже уже писал.

Могу добавить что вы все же не договариваете. На работу с таблицей адресов вирт методов все же какие-то такты уйдут.

Но мне как давно не пишущему на на си и плюсах нередко и разница в сотни мс безразлична. Потому что не влияет ни на что

Вообще увеличению.

перечитываем мое, на что вы написали — Нет:

... а важнее -скорость разработки.

Про старт ООП, и причины, можно привести Алана Кея, зачем он придумал Smalltalk.
Потом добавились и методы разработки, о том же, для того же
скорость разработки!!!
читать кент беков и прочих отцов аджайл

но вы пишите — Нет.
ну ок. не скорость разработки — цель всего развития что ЯП, что инструментария, что подходов в разработке

Обычное предложение реализации права людей на лень.

нет, лень вообще слово пустышка, ею можно объяснять что угодно, и будет «правильное объяснение»

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

Это то, что самое важное для людей.

не-а.
кратко проблема описана в пунктах Сутры запуска колеса Дхармы от Будды Шакьямуни.
:)

И это рекламная байка.

да, на самом деле, как в «Блеске и нищете айти технологий» показано
Выигрывает — второй.
матросовым достаются почести посмертно :)

но суть та же, третий уже врядли выиграет, а четвертый — точно проиграл.
так что

скорость разработки.

Не читал и не буду.

там пару абзацев всего-то.
но, все, ушел.

(создание в коде сущностей, соответствующих реальному миру)

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

Т.к. не предоставляет возможности увеличения быстродействия кода

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

декомпозиции, с лучшей локализацией данных.

В том и проблема, что с худшей локализацией данных. С лучшей, с точки зрения кодерков — но худшей, как для конвейерных обработчиков/кэша процессора.

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

Проблемы у ООП с кешами процессора обычно в рантайме — обход коллекции объектов, вызов метода у каждого, который формирует коллекцию которую обходит, вот и опа.
На этапе компиляции никак не соптимизировать. Хотя руками — вполне, если надо.

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

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

Тогда остаётся ембедед, системное ПО некоторых видов, и те самые оптимизированные библиотеки перемножающие матрицы.

Но насчет всего эмбедед я не уверен, то как обычно тормозит на планшетах в автомобилях приводит к мысли, "а может там тоже уже на ангуляр перешли, а на беке микропайтон?
не вникал, в чем там проблема

Да, и я об том, что
Где-то с 70ых программирование перестало быть «разделом математики», а стало инженерной дисциплиной
А где-то с 80ых начался процесс ухода и из инженерных дисциплин куда -то в лингвистику филологию

Математики и инженеры в негодовании, да кого это волнует на деле.

ну я математику считаю специальным случаем философии, но то такое. Пуанкаре считается последним математиком И философом, так что кто уже помнит то об этой родственности.
тут не помнят уже что было 20 лет тому, в собственной профессии, и откуда ноги растут

Математики и инженеры в негодовании, да кого это волнует на деле.

С одной стороны да, но с другой это создало благодатную почву для религий, догм и карго культов, особенно учитывая вливание новых неокрепших умов (подверженных влиянию подобных вещей) в связи с постоянно уменьшающимся порогом входа в отрасль.

Design and programming are human activities;
forget that and all is lost.
Bjarne Stroustrup

Именно — педагогический приём обучения ООП, «стал» в умах многих обучаемых а то и самих педагогов теоретиков основной бест практикой.

Ну типа — арифметика нужна чтобы палочки по кучкам на парте раскладывать, а потому без палочек — это неправильная арифметика!

Действительно, если строки равны, почему бы не вернуть FALSE — охудивительно ж код читается. Вместо того чтобы тупо переопределить оператор сравнения для строки.

1. Возвращается не false, а 0 (для равных строк).
2. В C нет строк. И перегрузки операторов тоже нет.

Кажется, в С99 добавили. Но всем пофиг.

else if (!strcmp(command,"if")) ifthenelse();

Этот вкус шампанским не перебить

бгг

bool still_running = true;
for(int i = 0; still_running && i < width; i++)
{
    for(int j = 0; still_running && j < height; j++)
    {
        still_running = array[i][j] != 0;
    }
}

Це не краща аналогія, так як більш складна, більше додаткових перевірок, а якщо 2-3 перевірки то повіситись можна. Але цікава.

а скорость работы?

Пару дополнительных JNE инструкций?

да. Они могут быть во вложенном цикле высоконагруженного куска. А если там еще часто бывает выпрыгивание — то начнет пыхтеть бранч предиктор.

  'outer: for i in 0..width {
    for j in 0..height {
      if array[i][j] == 0 {
        break 'outer;
      }
    }
  }

Не все языки так умеют

do
{
    for(int i = 0; i < width; i++)
    {
        for(int j = 0; j < height; j++)
        {
            if(array[i][j] == 0)
            {
                break; // goto loop_break;
            }
        }
    }
} while (0);
loop_break:

На форуме для кода таг pre

for(int i = 0; i < width && !q; i++)
{
	for(int j = 0; j < height && !q; j++)
	{
		if(array[i][j] == 0)
		{
			q = true;
			break;
		}
	}
}

У тебя лишняя проверка во внутреннем цикле %(

Или break не нужен. Это для общих случаев, например меня бесят множественные mutex unlock:

		pthread_mutex_lock(&mutex);
		if(array[i][j] == 0)
		{
			q = true;
			pthread_mutex_unlock(&mutex);
			break;
		}
		pthread_mutex_unlock(&mutex);

А вот это выглядит более структурированно:

		pthread_mutex_lock(&mutex);
		if(array[i][j] == 0)
		{
			q = true;
		}
		pthread_mutex_unlock(&mutex);

Ну как бы — или готу и/или деструкторы

for(int i = 0; i < width; i++)
{
	for(int j = 0; j < height; j++)
	{
		if(array[i][j] == 0)
		{
			i = width;
			j = height;
		}
	}
}

Шах и мат. 😁

ПС: как на этом долбанутом форуме вставлять код, чтоб он не поплыл?
ПСС: получилось

Я пробовал — код выводится одной строкой, без переносов.

Споримо на кусок баксів що для мого і твого коду, я підберу такі дані (при однаковому об’ємі), що моя реалізація буде працювати в тищщщу разів швидше?

width=height=1?
Навряд чи в тищщу. Перевір десь.

Мої дані — мої правила :-)
width = height = 10000; //так щоб з запасом
array[0][0] = 0;

І що?
спрацює

i = width;
j = height;

І цикли зразу завершаться

Різниця в ваших реалізаціях — в одне порівняння. Де там тисяча разів?

Уууф, точняк. Ледь не лишився косаря :-B

Точно, то я помилився)

Власне кажучи, лише заміна слова «goto» на «break» зробить код більш читабельним. Хоча, суть від того ані трохи не зміниться.

Смотря где. В жабе может. Но по сути тот же самый goto получается.

Так, по суті локальне використання goto. Тільки goto більш інтуїтивно зрозумілий. Бачиш мітку — перебігаєш на неї. Але краще вже так, в Пайтоні аналогічний код тільки через break на кожному рівні, try — except костиль, або ж через функцію пишеться, що ще гірше.

бряк не может ходить дальше одной области видимости. Вот такой он кривой.

В нормальных языках может

Иногда нам открываются неприятные истины:
Программирование — одна из наиболее трудных областей прикладной математики; чистым математикам в ней делать нечего — пусть лучше занимаются чистой математикой;

Простейший вид приложений — это технические и научные вычислительные задачи;

(«Numerische Mathematik», 1959, Эдсгер Вайб Дейкстра
itc.ua/...​sger_vajb_dejkstra_11696)

Программирование — одна из наиболее трудных областей прикладной математики; чистым математикам в ней делать нечего — пусть лучше занимаются чистой математикой

знатно у человека от чистой математики полыхало.

Да, тупень он. Всё ж знают о необходимости математики. Как можно программировать не будучи математиком? Никак. Загибается отрасль, понаслушались всяких дейкстр

У него ещё о computer science есть. Но точно неприлично на форуме математиков цитировать

І скоріш за все під чистими математиками розуміє далеко не той рівень, про який зазвичай йдеться в діалогах треба/не треба математика.

Для цього треба знати трохи Дейкстру(а в мій паперовий час був тільки він та Вірт з Кнутом, Керніган та Річі то вже інженерія була) та розуміти математику як засіб міркування.

А зазвичай її розуміння на рівні ООП головного мозку

Именно. Вопрос только что восторгаются ею обычно те кто её не знает. И настолько, что им аж дыхание им спирает от любых пренебрежительных её оценок

Найпростіший вид програм — наукові обчислювальні задачі)) ну ну, у мене від цього куска коду до сих пір полихає: github.com/...​/MANYBODY/pair_airebo.cpp До речі там жодного goto.

у мене від цього куска коду до сих пір полихає

да, воно такє :)

А ще дивитсь треба на код на пайтон від науковців та датасаєнтистів.
ну там де зазвичай тисячі рядків копіпасти — і всі в одної функції.
і не подумайте що то для швидкодії. Пайтон же.
«індуській код» буде взірцем якісного :)

Взагалі Дейкстра був одним з перших, хто перевернув мій світогляд на стосункі математики та програмування.
Коли він помер, то я сказав товаришу, «шкода, Дейкстра помер, а криза програмного забезпечення залишилась»

І з коду «наукових розрахунків» можна зробити багато висновків.
Наприклад: якщо науковці, зазвичай практикуючі математики, пишуть код гірший за індусів, то мабуть тому що математика цьому аж ніяк не вчить, і мислення практикуючого математика працює зовсім по іншому чим практикуючого програміста?

А його вислів про найпростіші програми я переклав би так

Якщо тобі не подобаються завдання про сім паралельних між собой ліній, і парочка з них прозорого кольору, а одна — котенятко, якщо ти вимагаєш ТЗ яке не буде змінюватись хоча б з місяць,...
то обирай те що тобі по силах,та йди там де пишуть модулювання клімату та згортання білку.
Ну а як і там важко — то може тобі тра у чисті математики?

А контекст першого його вислову такий.
У ті часи, і потім довго, і може й зараз, відношення тру математиків до прикладної було приблизно такє як програмістів до PHP, а до прикладників як тру інженерів до програмістів
Як хаскелісти-функціональщики до джавістів-імператившикив — точно.

Науковій світ — такє ж доу.

А ще дивитсь треба на код на пайтон від науковців та датасаєнтистів.
ну там де зазвичай тисячі рядків копіпасти — і всі в одної функції.
і не подумайте що то для швидкодії. Пайтон же.

Пайтон насправді дуже хороша мова якій бракує більш строгої типізації, хоча є cython. І python вимагає більше відповідальності чим C/C++ і тим більше Java/C#, так як в ньому можна робити все, як повну дічь так і цікаві рішення.

У мене таке враження що раніше ці люди посали на С, а потім пересіли на пайтон. Рішення Нвідії часто так заговнокожені: github.com/...​ing/networks_stylegan2.py , 396-407 для прикладу. ще дуже цікаво, наприклад, строки 307-324, тобто людина навмисно не використовує класи. Але попри такий прекрасний код рішення біло проривним і дає просто офігенні результати.

    # Recursive structure: complex but efficient.
    if structure == 'recursive':
        def cset(cur_lambda, new_cond, new_lambda):
            return lambda: tf.cond(new_cond, new_lambda, cur_lambda)
        def grow(x, res, lod):
            y = block(res, x)
            img = lambda: naive_upsample_2d(torgb(res, y), factor=2**lod)
            img = cset(img, (lod_in > lod), lambda: naive_upsample_2d(tflib.lerp(torgb(res, y), upsample_2d(torgb(res - 1, x)), lod_in - lod), factor=2**lod))
            if lod > 0: img = cset(img, (lod_in < lod), lambda: grow(y, res + 1, lod - 1))
            return img()
        images_out = grow(x, 3, resolution_log2 - 3)

Насправді поганих мов у перших 50 позиціях TIOBE немає.
якось бачив у справі пакет на VBA. Такої фунціональності і виконання я нечасто бачив і на рейтингових мовах. Може тому що авторами були програмісти з Dell, а пакет розроблявся для партнерів, ділєрів,представництв.

А ОО так,не панацея.

На С за таке руки повідривають

У мене э така підозра, що у драйверах NVIDIA не кращий код на С. А от в комюніті ядра лінукс за таке влаштували б публічну страту і послали б куди подалі. А в науковому коді на С/Fortran буває ще більша дічь. Можу, якщо цікаво, пошукати в заначках, те від чого текли очі. Там як раз часто goto, там де цього не хочеться бачити.

Ну лямбд в С нема, а тягнуть стільки вказівників на функції в одне місце — то хоч поназивали б їх якось нормально. Бо ж таке читать не можна. І рядки страшенно довгі.

Є магічний (void*) з якого можна склеїти все) в тому числі те, що не дуже добре пахне

Все клеят сейчас с uintptr_t, который кастится куда угодно, включая в void*.

У мене э така підозра, що у драйверах NVIDIA не кращий код на С.

У них слишком windows style — куча капитализаций, длиннющие стринги (это то, что есть в публичных SDK/DDK) — читается очень тяжело.

Там заміть, в тому куску функція, в яку передаются лямбди, вона повертає лямбду. І потім все це рекурсивно використовується. Краще вже структурно розписати, хай і буде більше коду.

«goto» это стрела: куда хочу — туда лечу.Только из лука сейчас не стреляют

... сказала обезьяна с гранатой, натягивая на проект React

Все равно ваш код будет преобразован в команды процессора где будет jmp (goto).

Кто б спорил. Особенно весело выглядит такой код после декомпилляции, когда эти goto приходится связывать вручную в сколь-либо читабельные конструкции.

Проблема кода не в том, чтобы правильно работать. А прежде всего, чтобы правильно читаться. И простым прочтением кода можно было убедиться, что он делает задуманное. Если эта задача не выполняется — код плохой, и должен быть выпилен из проекта. Если это невозможно, он нуждается в массивных комментариях на естественном языке — в первую очередь для цели переписать код, если он подозревается в ошибках (и это невозможно проверить без тестов, равно как и написать тесты, покрывающие все вариации данных).

Самым дебильным с точки зрения программирования являются регулярные выражения. Вот уж где можно разгуляться, закладывая какашку в работу программ. Особенно весело, когда они выносятся в конфигурации, и уже пользователь должен быть спецом в энтих краказяблах. Куда уж тем скромненьким GOTO.

Особенно весело выглядит код после декомпиляции когда он был скомпилен майкрософтовским компилятором. Он такие макароны набрасывает на все инструкции.

людям, которые не понимаю разницу между адресом в архитектуре фон Неймана и безусловным переходом в ЯВУ — да, «все равно»

Господа, все по каретам — у нас эстет в треде.

Просто оставлю это здесь
web.archive.org/...​l05/papers/p261-knuth.pdf
(Structured Programming with goto Statements)

Для истории:

www.cs.utexas.edu/~EWD — индексированый архив набросов Дейкстры

в современных языках нет goto

Везде есть goto. Просто, людишки не видят его сквозь «синтаксический сахар» из if, else, for, while.

Везде есть goto.

goto нет, есть всякие j** (JE, JNE etc.). Да и собсно так можно много о чем сказать.
Да и вообще все в электрические импульсы сводится.
Тут речь о том что goto не катит для высокоуровневых языков.

Тут речь о том что goto не катит для высокоуровневых языков.

Еще как катит. Его часто используют. А Throw Exception с логикой Goto так вообще маст хев стандарт.

Некоторые вещи для embedded всё же лучше писались бы с GOTO. Это куда более понятно, чем пытаться городить функции и зачем-то сношать стек. Особенно, там где скорость кода важна, а потребление память должно быть предсказуемым.

Да, а ещё старые добрые деструкторы...

Некоторые вещи для embedded всё же лучше писались бы с GOTO.

Они сейчас так и пишутся. :)

Умными — да. Тупые пытаются тянуть С++ с библиотеками, удивляясь что оператива внезапно «всё»

в эмбеддед практически все с++ библиотеки кастомные

Компилер все стерпит.
А вот читать без гото — жестко.

с goto не сильно лучше, особенно если метки писаны мудаком.

чем пытаться городить функции и зачем-то сношать стек

эээ. inline?

Не имеет никакого значения сколько там логики на джампах будет в опкодах, пока гарантии выдаваемые ЯП и компилятором выполняются. В «а как оно там в опкодах будет» смысла совсем немного.

в современных языках нет goto
Везде есть goto. Просто, людишки не видят его сквозь «синтаксический сахар» из if, else, for, while.

Посыл статьи, не верен, goto сам никуда не делся. Без if/for.
Есть он в языках, но используют редко.

developer.mozilla.org/...​eference/Statements/label
docs.microsoft.com/...​e-reference/keywords/goto

И главный goto, это не if/for, а вызовы методов.

Помоему Дейкстре пытаются приписать славу итальянцев.

ru.wikipedia.org/...​ki/Теорема_Бёма_—_Якопини

Он просто продвигал тему со структурным программирование. Вот полная его статья — hosting.vspu.ac.ru/...​ul/dijkstra/goto/goto.htm

Но первый то был не он. Где бы он был, если бы итальянцы не подогнали нужную теорему, которая дословно гласит что можно писать код без goto

Первый не был. Но продвинул эту тему как раз он...

Ну двигать он мог что угодно, его личное дело. Но гоуту жив здоров. Вот пример, 3600 гоутушечек в дотнет репозиториях. github.com/...​org:dotnet goto&type=code

от пример, 3600 гоутушечек в дотнет репозиториях

И это, кстати, довольно странно. Легитимный способ применения goto — выход из вложенного цикла наружу. Обычно, применяют в C, для оптимизации (чтобы не заменять цикл с goto вызовом функции и/или не делать дополнительных проверок после циклов, при выходе по break).

В жабах/шарпе таким заниматься повода нет, т.к. исполнение заведомо гораздо более тормознутое, чем на C. Соответственно, не зачем так оптимизировать.

исполнение заведомо гораздо более тормознутое

Дот нет уже давным давно не тормознутый. Для этого нужно просто понимать кухню джит компиляции.

Джит-компиляция — это (слабенькая) попытка заставить тормознутое и жрущее память г., хоть как-то шевелиться.

Сильное заявление. Проверять конечно его я не буду ©

Проверять нечего, т.к. вещь общеизвестная.

chart.apis.google.com/...​1,10|N*f*,D06A34,10,-1,10

тормознутое и жрущее память г., хоть как-то шевелиться.

Как обычно в таких случаях — тест делал хипстер, не умеющий в C/C++.

ну чувак, для этого надо руками менеджер памяти в С++ написать.
поэтому из него все и перебежали в хипстерщину, что руками много делать надо.

ну чувак, для этого надо руками менеджер памяти в С++ написать

Менеджер памяти — лишнее. Как правило, если речь идёт о всяких стандартных контейнерах — достаточно в сетапе (перед стартом таймера) сделать «резерв».

Накрайняк, пользовать плэйсмент нью (если это плюсы).

После этого, любые бенчмарки где шарп/жаба опережает плюсы (не говоря уж о сях) — превратятся в тыкву.

Но в реальности у тебя не будет placement new, и оптимизировать надо ручками. Поэтому в реальности жаба не настолько проигрывает, как в руками оптимизированном тесте. Зато кодить быстрее.

Но в реальности у тебя не будет placement new, и оптимизировать надо ручками.

Почему не будет? Если нужно быстродействие — нет особых проблем лепить инстанcы на пре-выделенной памяти.

нет особых проблем лепить инстанcы на пре-выделенной памяти

Я вот удивляюсь как в Оракле и МС до этого не догадались ;)

Им лом оптимизировать руками, наверное.
Нормальные люди юзают всякие EASTL или самописное
ithare.com/...​sdoms-and-common-wisdoms

Дяка за посилання! Блог выглядит очень интересно

У чувака десятки статей в Overload (в основном это они на сайте лежат), сейчас пишет девятитомник по многопользовательским игрухам, и очень крутая презентаха по высоконагруженным системам ithare.com/...​-threading-with-a-script

Потому что они будут выделяться где-то в другом месте системы, присылаться к тебе по указателю, а потом их надо будет запихнуть в мапу.

Это ты зря тратишь время. Как тут не вспомнишь классиков «...Если б Остап узнал, что он играет такие мудреные партии и сталкивается с такой испытанной защитой, он крайне бы удивился. Дело в том, что великий комбинатор играл в шахматы второй раз в жизни».

А нужно оно гоооооораздо реже чем скорость разработки.

То же что вы написали — написано в дев гайдах NASA (в тех что встречал в инете) и используется не для быстродействия (на котором помешан любой уважающий себя джун) а для того чтобы избежать фрагментации памяти аллокатором, которая может привести к out of memory, а перезагрузка ПО на спутнике может запросто привести к его потере.
Но в дев гайдах NASA много дивного, из-за весьма специфичных требований.Да и сроки на разработку у них просто райские.. .

То же что вы написали — написано в дев гайдах NASA (в тех что встречал в инете) и используется не для быстродействия (на котором помешан любой уважающий себя джун) а для того чтобы избежать фрагментации памяти аллокатором, которая может привести к out of memory, а перезагрузка ПО на спутнике может запросто привести к его потере.

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

К написанному мною (как и к быстродействию) отношения не имеет.

К написанному мною (как и к быстродействию) отношения не имеет.

может быть, ок

просто недавно встретил регулярный пост
об открытии, и предстоящем перевороте в мире хайлоада

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

ну и подумалось, что может это ваш друг был.
обычное ж дело, писать такие бенчмарки, и делать великие открытия.
мужики то и не знали, надо открыть им очи.

сам писал в студенчестве, сверяя оптимизации компилеров quick C, Turbo C и Watcom C
даже недавно, на одну системную функцию написал, чтобы не возвращаться к вопросу.

так что да, просто не понял о чем вы.

просто недавно встретил регулярный пост
об открытии, и предстоящем перевороте в мире хайлоада

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

Снова ковырялся на рашкованских хабро-помойках?

Наковырлял себе г. — и ладно. Но незачем его демонстрировать в культурных местах и приписывать окружающим.

ну ок, друг не ваш.
вы сделали действительно Открытие, о котором сообщили мужикам.

ну а то что вы упрямо тягаете аргумент
когда человеку нечем гордиться — он гордиться принадлежностью к нации, это да. показательно.

ну а то что вы упрямо тягаете аргумент
когда человеку нечем гордиться — он гордиться принадлежностью к нации, это да. показательно.

Мой аргумент прост. Не ковыряй г. на африканских помойках, а если уж ковыряешь — не тащи его в культурные места.

такой аргумент можно принимать только от человека от которого не разит той же самой помойкой :)

а аргумент о «нации» — ух ядрена вонища

Менеджер памяти — лишнее. Как правило, если речь идёт о всяких стандартных контейнерах — достаточно в сетапе (перед стартом таймера) сделать «резерв».

В шарпе тоже можно передать в конструктор capacity.

В шарпе тоже можно передать в конструктор capacity.

Можно. Но это не изменит общей шарповой тормознутости.

В дот нет сам по себе менеджер памяти получше написан чем в С++. Хотябы потому, что он инкрементально быстро отдает новые и новые куски памяти и уже потом, отдельным потоком, базируясь на поколениях обьектов, подчищает хвосты.

Все что можно в С++ сделать руками, это написать свой пулл обьектов под задачу. Но это еще нужно заморочится.

Да, и после этого скорость будет не хуже, вероятно — лучше. Если сам контейнер не тормозной. Но обычно заморачиваться лом.
То же самое с С++ против С. В С++ меньше заморачиваются, но в результате код на С, где не заморачиваться нельзя, работает быстрее. То же самое с STL — он тормозной, но его юзают чтобы быстрее писать.

Да, но в схватке дефолтовый STL vs дефолтовый .NET, нужно отдавать предпочтение последнему. Хотябы потому что, это не надстройка над языком, а это синтаксис и декларации встроенные в язык. Это немного развязывает руки среде выполнения и позволяет внедрить интересные оптимизации, которые недоступны в языках где все прибито гвоздями, надстройками над надстройками.
Собственно поэтому С++ при попытке писать на нем в высокоуровнем стиле вполне себе может фейлить по производительности перед тем же .NET

Да, но в схватке дефолтовый STL vs дефолтовый .NET, нужно отдавать предпочтение последнему.

«Дефолтнго СТЛ» не существует — т.к. есть куча различных реализаций. Есть очень тупые реализации, с «брут форсами» повсюду — там шарп с его оптимизацией и использованием SSE, AVX, итп, на некоторых сценариях (типа работы с большими блоками данных) может быть быстрее.

Но есть реализации, которые уделают шарп без вариантов.

P.S. Но редкая программа состоит лишь из добавления или там поиска элемента в контейнере. Когда функциональность разрастается — шарп отдыхает.

Как раз наоборот — на очень больших проектах отдыхает С++.
Потому что тогда его будут 100 лет писать и отлаживать.

Как раз наоборот — на очень больших проектах отдыхает С++.
Потому что тогда его будут 100 лет писать и отлаживать.

«шарп отдыхает» в сравнении с C/C++ по скорости, понятно.

Очень большие проекты на шарпе заканчиваются тем, что все кодеры сидят в профайлерах и занимаются оптимизациями (в т.ч. при помощи unsafe кода).

Нет, серверов докупают. Если есть деньги. А чтобы были деньги — надо быстро отрелизиться.

Нет, серверов докупают. Если есть деньги.

Я о деcктопах. Там особо ничего не докупишь — т.к. софт должен работать на клиентском оборудовании.

Сервера то вообще отдельная история.

На десктопах очень больших проектов не бывает.
Просто большие писаны на С++ в течении 15-20 лет.

На десктопах очень больших проектов не бывает.

хорошая шутка :)

Для инференса не нужен комп за 30 кусков. И Two Stage в реальных решениях уже все реже используют.

one-stage Object Detection или one-stage Instance Segmentation(для границ(точнее масок)). Например CenterNet, CenterMask, SSD.... и прочее.

Конкретно как аналог maskRCNN я имел ввиду CenterMask. Пересмотри ещё раз комментарий. SSD как и CenterNet понятно что только детекцию делает.

Код проще читать при выпрыгивании через goto чем когда там 100500 проверок какой-то переменной которая в одной или двух ветках выставляется

Это обычно обходят запихиванием всех циклов, кроме внешнего, в отдельную функцию — где вместо goto делается return. И во внешнем цикле проверка того, что вернулось и если нужно break.

Получается читабельно, но тормознутее (что в жабе/шарпе пофиг).

5 функций по 3 строчки часто не читабельнее, чем одна функция на 15 строчек.
Особенно когда там десяток аргументов гоняется.

А ещё лучше не выпрыгивать вовсе, как и не использовать голые циклы. Есть комбинаторы, примитивы рекурсии и рекурсивные схемы, производительности этих вещей вполне хватает чтобы писать не «затобыстро» приложения.

Если оно под капотом уходит в итерацию — то может быть.
Настоящая рекурсия на больших данных выедает стек и валится в ООМ.

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

Підписатись на коментарі