Pull to refresh
51
0.2
Valentin Nechayev @netch80

Программист (backend/сети)

Send message
Тут всё-таки лучше быть практичным и не рассматривать события с очень малой вероятностью — а именно таким сейчас можно считать ошибку в процессоре или компиляторе. Очень малой — это меньше миллионной того, что баг у автора кода. В 50-е, да, было иначе, но сейчас не 50-е.

Кстати, уже чисто интересно с исторической точки зрения — где и когда существовала терминология, что порядок вещественного числа назывался «ординатой»? Я такого не нагугливаю, хотя времена, когда ЭВМ были большие, ещё застал лично.
> распространение этого синтаксиса и на if является вполне логичным продолжением даже без влияния go.

Для меня тут колоссальной разницей является то, что в for три части присутствуют обязательно (даже если пустые), а в if первая может отсутствовать. Именно конкретный метод решения был взят в конкретном месте. Альтернатива, в виде названного в том же пропозале with(), присутствовала в других местах.

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

> There are three statements in C++, if, for and while, which are all variations on a theme.

И он тут же исключает из рассмотрения else для if… мне эта логика ой не кажется корректной.

К слову, else для for и while (по образцу Питона) иногда тоже очень полезно. :)
Тут возникает ряд существенных граблей.
Например, обязан ли язык различать Á (U+00C1) и Á (U+0041 U+0301)? Python различает, но приведение всех идентификаторов к NKFC может быть дороговато (в компилятор втягивать что-то размера ICU, причём на этапе, где лексер и так отрабатывает много специфики языка — см. например Clang — где есть лексический парсинг обычного кода, строк препроцессора, кода внутри блока `#if 0`, и т.п.) А вот Go ничего не делает с этим — и можно получить злобные проблемы от внешне одинаковых идентификаторов в разных местах, так, что редактор этого не покажет.
А когда апдейтится стандарт Unicode — менять таблицы вслед?
Требовать ли от внешних средств типа линкера поддержки таких идентификаторов, и что делать, если не поддерживает?

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

Ведь даже наличие ASCII, считаем, стало обязательным только с C++17 — я имею в виду отказ от триграфов, которые применялись для возможности написания на C++ в странных местах типа zSeries с локализованными вариантами EBCDIC…
А Вы где-то ещё видели именно такой же синтаксис — две части через точку с запятой, первая необязательна, но должна что-то инициализировать? Я — только в одном источнике, и его тут уже назвали.
Был бы другой образец — взяли бы его, потому что ничто не мешало, например, создать отдельное ключевое слово и блок за ним (что было бы как-то более понятно при отсутствии такого образца), или сделать другое построение блока (хм, а почему if и switch, но не while?), перетащить GCC вариант ({...}) с уточнением блочного контекста, и т.п.
Ну вообще-то концепция, по которой у функции всегда предполагалось только одно значение-результат, выглядит устаревшей. Она была хороша в период ранней «математизации» понятия функции (особенно по сравнению с subroutine в Fortran, где функции обязаны были быть «чистыми»), но сейчас нет смысла добровольно вжиматься в прокрустово ложе. Тем более что примеров, когда реально передаётся несколько значений, но все кроме одного идут косвенными каналами — полно в любом системном API.

А с чем сравнивать возврат нескольких значений — с Python, Go, Swift, Erlang, Haskell, чем-то ещё — вопрос персонального опыта. В данном случае второй ok это ближе к тому, что я видел по Go. Был бы он первым — был бы стиль Erlang :)
Упускаете главный момент.
Новая форма аналогична созданию блока, в котором определены новые переменные, а после этого вложен собственно if. Пример автора статьи:

if (auto it = m.find(key); it != m.end())
{
  ....
}


аналогичен

{
  auto if = m.find(key);
  if (it != m.end())
  {
    ....
  }
  // кстати, тут может быть else-ветка, или даже цепочка else if ... else,
  // в которой эта переменная будет видна
}


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

Потому — это чисто «сахар». Но очень практически полезный, раз ввели.

Кстати, насколько я понял final draft, несколько отдельных init-statement ввести нельзя. Немного жаль.
Он может протащить набор клиентских библиотек, но (при нормальных зависимостях) никак не xorg-server и тому подобные собственно отображающие части.
А всякие libX11 может потянуть за собой тот же vim, если собран в «полном» варианте с графической мордой.
Слышал такое мнение, и интересно, кто и почему его поддерживает.
У меня получается 4-6-пальцевый и не совсем слепой метод (надо видеть краем глаза контуры клавиатуры), но предпочитаю vim всем прочим консольным.
Использую IDE только там, где нужны её специфические возможности типа рефакторинга между несколькими файлами или тыкания в 500 ошибок, и то не уверен, что мне просто не хватило терпения найти плагин для этого.
Ну то есть они были практически бесполезны.
А вот именно в такой удобной форме (и с блоком на весь if/switch) — образцом послужил Go.
Очень интересно с исторической точки зрения — о чём люди фантазировали при проектировании концепции (и как оно потом преобразилось). Спасибо.
Возможность «инициализатор в if и switch» — это как раз если не впервые в таком виде появилось в Go, то по крайней мере там стало хорошо известно — и доказало свою полезность.
Или Вы знаете другой язык из популярных, где это было раньше?
> Речь исключительно о том, что с использованием режимов пользователям вима работать удобнее и приятнее. Или, по крайней мере, они в это искренне верят.

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

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

У меня было именно с разделением. Договор уже не найду, это было в 2006-2007.
Возможно, ваш банк сейчас так не делает. Но учитывайте, что другие могут работать по другим правилам.

> Раз в месяц сумма задолженности умножается на (1 + rate/12).

Это не относилось к процентам, начисленным в прошлые разы, а только на тело.

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

Правило было именно таким, как я описал.
Разница есть, и проявляется она в тех случаях, когда платишь не ровно ту сумму, которую должен был заплатить в положенный период.
На моём кредите было правило, сколько бы ни было долга, если я принёс деньги, с них вначале снимается начисленный процент от тела (за текущий и прошлые пропущенные периоды) и уже из остатка этого погашается тело кредита.
Опередив срок выплаты, я мог после этого приносить только за проценты, но не погашать тело, и пока не начинал отставать от графика погашения тела кредита — никого это не волновало. Но проценты должен был приносить ежемесячно, иначе бы сразу сработала тревога на неплательщика, и не погасив прошлые проценты — не мог погашать тело.
Из повышенного взноса — излишек шёл на тело кредита.
Подозреваю, большинство банков имеет такие же правила.
> typedef int (*(*fun1)(int))(int);

Вы определили fun1, а не fun2. Похоже, это опечатка — если написать fun2, то получится то, что ожидается (?)

Вот об этом я и говорю — если в спокойной обстановке тут путаешься в таких определениях, то что же будет в нормальном рабочем цейтноте?

А ещё — сколько времени прошло, прежде чем хоть кто-то заметил, где я ошибся?

> Вот здесь дан очень хороший ответ:

Угу, с тремя слоями вкручивания в определение…

> typedef typeof(typeof(int(*)(int)) (*)(int)) fn2;

и ещё одна путаница, и уже другого стиля (!) Итого — два разных стиля.

Спасибо за исправление моего примера. И всё это считаю безусловными примерами в пользу того, что синтаксис определений в том порядке, как Pascal/Ada/Go/etc., работает на пользу написания/чтения/сопровождения, а синтаксис C — против.
> Вот список, там есть и те примеры, которые написали тут
Симпатично. Когда я в последний раз активно гуглил эту тему, статья эта, видимо, была кривая и мелкая, а потом не возникло мысли поискать именно в википедии. Это уже заклин сознания.
> но есть несколько примеров слов общего назначения.
Очень мало :(
Эта логика начинает резко хромать, когда определения усложняются:

typedef int (*fun)(void*);


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

А вот такое компиляторы уже не осиливают, выдавая ошибки:

typedef int (*fun1)(int) (*fun2)(int);


хотя, казалось бы, чего сложно — определить fun2 как указатель на функцию с int параметром и указателем на функцию int->int в результате…
ан нет, случился зашкал сложности, и без промежуточных typedefʼов не выкрутиться.

Стиль таких определений в Pascal, Go (*) и многих других — читаемее и не страдает такими ограничениями. Цена же за это — что надо, например, явно писать слова var — для переменных, func — для определений функций. Как по мне, цена вполне разумная, польза перевешивает.

(*) Хоть я его и громко ругаю за кучу прочего.
> После ухода с проекта людей, изначально написаваших код, проект на Python, как правило, «рассыпается». И довольно быстро. Рекорд, кажется, 3 года с момента ухода с проекта его инициатора.

Софтсвич, в котором я участвовал несколько лет, скоро отметит 13-летие. Начальный автор ушёл через полтора года после старта, и меня там уже года три как нет (но я в курсе общей картины). Никаких особых усилий по форсированию крепости проекта не делалось.
Что там у вас за специфика дружбы с питоном — непонятно, но где-то вы катастрофически перегнули…

> а Python (и даже связка C++/Python) — не годится. Причём не годится категорически!

;)
Горутина — это как раз не LWP, а его «клиент». Только вместо явных LWP там обычные системные нити.
А так — да, M:N в полный рост. Как и у Erlang, и у многих других реализаций стиля акторов.

> как офигенную инновацию.

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

Information

Rating
2,677-th
Location
Киев, Киевская обл., Украина
Date of birth
Registered
Activity