Как стать автором
Обновить

Комментарии 338

а теперь заканчивайте

Слежу за статистикой. Результаты неутешительные. Только треть проголосовавших за качественные материалы на Хабре… :-( Еще один довод в копилку, что Хабр стал "не торт". Хотя мы можем попробовать все еще все изменить :-)

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

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

что мне не влом написать в личку автору

А ведь всего то достаточно выделить момент с ошибкой и нажать Ctrl+Enter. Даже никуда ненадо в прфоиль лесть и тд.

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

Если вы про то, что пропадает кнопка «отправить» — отправляйте вторым нажатием ctrl+enter (проверено, работает). Я всегда так делал и глюк с пропадающей кнопкой заметил сильно не сразу. :)
Кстати, в бета-версии хабра кнопка не пропадает. Но там и ctrl+enter не работает на отправку.
Ни разу не сталкивался с тем чтоб не работало.

ну, вот я такой везучий

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

<< Вы издеваетесь? Я ни разу не грамарнаци, но на этой фразе у меня кровь из глаз потекла.

В этой статье я расскажу о том, почему в качестве опорной точки вместо Python следует использовать C.

Правильно читать "приведу ничем не подтвержденные аргументы".

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

Примеры:
1) variable scope: видимость переменных на чтение и на запись разная

вот этот код напечатает 10 10
i=10
def foo():
    print(i)
foo()
print(i)


вот этот код напечатает 2 10
i=10
def foo():
    i = 2
    print(i)
foo()
print(i)


а вот этот откажется компилироваться
i=10
def foo():
    print(i)
    i = 2
foo()
print(i)



2) списки и ссылки на них
вот этот код напечатает [13, 0]
a = [0]*2
a[0] = 13
print(a)


а вот этот НЕ напечатает ожидаемые [[13, 0],[0,0]]
b = [[0]*2]*2
b[0][0] = 13


А всё потому, что двумерный массив нужно декларировать не так
b = [[0] * 2 for i in range(2)]
b[0][0] = 13



И даже когда начинающий поймёт, где баг, и скопирует со стэковерфлоу [[0] * 2 for i in range(2)] вместо [[0]*2]*2, он вряд ли поймёт, почему это так.

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

В итоге получается картина, схожая с вот этой карикатурой

C интуитивнее?

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

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

Чтобы выбор был информированным, рядом неплохо бы иметь сопоставимый список слабых мест C.

список слабых мест C.

Указатели

Управление памятью

Никаких exception, упали значит упали ;)

Строки, хнык, хнык

Никаких встроенных списков и словарей, все вручную

Никакого разнообразия встроенных модулей, libc хватает всем.

Указатели и управление памятью не факт, что слабое место. Как раз тот факт, что питон прячет ссылки-указатели (хотя они у него есть), я и считаю слабым местом питона (опять же, для начинающих).

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

Хотя обвинить си в малом количестве библиотек это сильно :)

Библиотеки в С не являются частью языка. Их много, да.

Ну какой-нибудь matplotlib или numpy тоже отдельно устанавливать надо.
НЛО прилетело и опубликовало эту надпись здесь
Учли ли вы контекст дискуссии, и приводите ли слабые места языка при знакомстве с программированием?
НЛО прилетело и опубликовало эту надпись здесь
Видимо, мы с вами по-разному понимаем знакомство с программированием. Для меня знакомство — это программы по пять строчек. Через некоторое время пятьдесят. Указатели на функции приходят гораздо позднее. Ну и про UB — не так страшен чёрт, как его малюют. Поймать UB на описанном мной уровне не так просто (нет, я понимаю, что написать i++ + ++i; можно и в одну строчку).

Я не сомневаюсь, что человек, который уже заморачивается вещами уровня указателя на функцию и всяких полиморфизмов, разберётся с тонкостями питона. У меня претензии к питону до этого уровня.
НЛО прилетело и опубликовало эту надпись здесь
Этап пятистрочных программ проходит очень, очень быстро, практически за пару занятий.

Ох. Вы уверены? Знаете, в нашем провинциальном вузе (кстати, учат на питоне), за весь первый семестр нет ни одной программы длиннее пятидесяти строк.

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

Ну так 50 ≫ 5 вообще-то :)

Для меня знакомство — это программы по пять строчек. Через некоторое время пятьдесят.
НЛО прилетело и опубликовало эту надпись здесь
Надо лишь убедиться в том, что опыт не избирательный. Все ли ваши одноклассники писали код длиннее ста строк в седьмом-восьмом классе?

Ну а языков нужно давать в профильном вузе сильно больше одного, и C/C++ рано списывать со счетов, поэтому про ставки трудно сказать. Ещё раз напоминаю, не предлагаю выбирать си первым языком. Первое знакомство imho должно происходить с программируемым калькулятором.
НЛО прилетело и опубликовало эту надпись здесь
Начинайте с турбопаскаля! Отличный язык для реализации алгоритмов школьного уровня! С с классами или плюсы — это уже профориентация.
НЛО прилетело и опубликовало эту надпись здесь

Ни одно решение на традиционном паскале нельзя позаимствовать. Может оно и правильно, пусть руками пишут, а не с интернетов копируют.

У TP есть шикарная библиотека - Turbo Vision (800kb). Там и учиться и заимствовать есть что. Плюс шикарные по своей глубине примеры.

" Может оно и правильно, пусть руками пишут, а не с интернетов копируют." - да, написанное собственной дрожащей рукой на школьной доске как-то надежнее усваивается. А если еще и правильно, то гордости полный дневник :)

Я до сих пор считаю Паскаль, Модулу, Оберон лучшими языками для обучения. Старик Вирт шарил в этом. Сам я начинал с Бейсика на zx-spectrum и потом долго переучивался не писать спагетти-код. Плохо, что в школе не давали кодить на калькуляторах, хотя в курсе алгебры они были, но учителя их игнорировали и я игрался сам. Зато после них ассемблер и форт легко дались. Ну, а Си уже совсем просто. Вот С++ до сих пор недолюбливаю - уж чересчур усложнили. Делфи был интересней, но после продажи его Борландом - закис. Хотя есть free Pascal и Lazarus. Но это уже не то. А питон мне очень понравился как скриптовый язык. В общем ИМХО начинать то можно с любого языка, но лучше многие перепробовать, и да с Си всё же стоит ознакомиться.

Я сам не щупал этот Кумир, но народ хвалит.

НЛО прилетело и опубликовало эту надпись здесь
Мне вот совершенно неочевидно, что оно там нужно.
во-первых, некоторых программирование заинтересует еще в школе — у меня много таких знакомых плюс я сам. Во-вторых, программирование в том или ином виде (матлабы там, ексели) требуется во всё большем числе профессий, и с этой точки зрения оно даже лучше подходит для общего развития, чем, скажем, химия или обществознание.
НЛО прилетело и опубликовало эту надпись здесь
Тогда ничему не мешает, условно, преподавать полгода питона, полгода плюсов, полгода хаскеля, полгода пролога
едва ли в школьную программу влезет хотя бы пара языков
Тогда надо преподавать то, с чем, с большей вероятностью, встретится будущий ученик. Хотя что там будет через 10 лет — поди предскажи
10 лет назад было понятно, что программисты нужны. Более того, судя по популярности буткемпов, даже если сейчас спрос начнет падать, университеты всё равно еще долго его не закроют
В последнее время как-то слишком много говорят о хаскеле. А вот в документации написано, что и в питон, и в хаскел отступы обязательны. Это противоречит понятию «текстовый формат данных», и не только является примером дурного тона, но и опасным источником ошибок. Изучать такие языки первыми точно не стоит.

Си, лисп и пролог в некотором смысле образуют базис — то есть это максимально разные подходы к программированию, у которых минимум общего. Остальные более-менее раскладываются по этому базису и от себя добавляют лишь небольшое количество уникальных особенностей. Вот эти три вещи и надо преподавать в общеобразовательных школах. А остальное по специальности.
НЛО прилетело и опубликовало эту надпись здесь
Да, похоже это только питоновская проблема.
А что не так с лисп?
НЛО прилетело и опубликовало эту надпись здесь
Тогда однозначно включаем хаскелл в школьную программу вместо лиспа. Этот язык развивает чувство юмора. Ещё его можно использовать в паре с си: на хаскелле описывать, что нужно вычислить, а на си описывать элементарные алгоритмы, которыми будет оперировать вычислитель хаскела.
НЛО прилетело и опубликовало эту надпись здесь
Потому что хорошо, когда каждый язык решает свой круг задач и не претендует на универсальность.
Вы можете определять сложение как:
instance Num Nat where
  (+) a Zero = a 
  (+) a (Succ b) = Succ(a+b)

но вряд ли вас устроит такое определения для сложения 734211040 и 610489189. Впрочем, и оно ссылается на сложение, определённое в строенном типе. А его иначе как
(+) a b = ({
  long ADD;
  register long _a asm("rdi") = a
  register long _b asm("rsi") = b
  asm("mov rax,rdi\nadd rax,rsi":"=a" (ADD));
  ADD;})

и не определить.

Где-то внутри компилятора оно так и записано, но можно было вынести это в файл, чтобы любой мог по своим потребностям что-то добавить или изменить, а не проклинать разработчиков и строить костыли. Иначе, подозреваю, не так много лет пройдёт, и хаскелл станет «ещё одним универсальным языком».
НЛО прилетело и опубликовало эту надпись здесь
Такой пример предлагается в учебнике по хаскел, какой-то смысл для автора значит был.

Нашёл пример интеграции хаскел и си:
github.com/mgrabmueller/rdtsc

А теперь вопрос: можно ли считать, что любая функция в хаскел либо имеет определение на хаскел, либо импортирована подобным образом? Если да, то это в точности то, о чём я писал в предыдущем комментарии, и хотелось бы посмотреть, каким образом из GMP сделали Integer. Если нет, то странно, и непонятно, где проходит граница.

К си претензия непонятна, ибо в нём граница очень чёткая: список синтактический конструкций задан стандартом, и это встроенное, а все функции — это определяемое (в исходном си вроде бы перегрузки операторов нет). Это вопрос не морали или идеологии, а того, как быстро находить исходники каких-то понятий, если они есть, или понять, что их не нет.
А теперь вопрос: можно ли считать, что любая функция в хаскел либо имеет определение на хаскел, либо импортирована подобным образом?

Нет, нельзя так считать.


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

Касательно оптимизации. Поигрался с кодом:
prime :: (Integral a) => a -> Bool
prime 1 = True
prime x = and [ x `mod` y /= 0 | y <- [2..(x-1)] ]

Выглядит красиво, не поспорить,
а теперь запускаем:
> prime(1999993)
True
it :: Prelude.Bool
(0.85 secs, 816,057,504 bytes)

> prime(3997859)
True
it :: Prelude.Bool
(1.64 secs, 1,631,185,144 bytes)

> prime x = and [ x `mod` y /= 0 | y < — [2..(div (x-1) 2)] ]
prime :: Integral a => a -> Prelude.Bool
(0.01 secs, 0 bytes)

> prime(1999993)
True
it :: Prelude.Bool
(0.41 secs, 408,056,872 bytes)

> prime(3997859)
True
it :: Prelude.Bool
(0.81 secs, 815,620,928 bytes)

Я, конечно, не ждал чуда с y^2, но на /2 от платформы, занимающей 800МБ на диске расчитывал. Но ладно.
Код на си:
int try_div(int a,int b)
{
	return a%b;
}

int test_prime(int arg)
{
	if(arg<2) return -1;
	if(2==arg) return 0;
	if(!(arg%2)) return 2;
	for(int i=3;i<arg;i+=1)
		if(!(try_div(arg,i)))
			return i;
	return 0;
}

int main(int argc,char**argv)
{
	int j;
	for(int i=3997850;i<3997870;i++){
		j=test_prime(i);
		WriteI(1,i);
		WriteC(1,"\t");
		WriteI(1,j);
		WriteC(1,"\n");}
	return 0;
}


Результат 0.01 сек
3997850 2
3997851 3
3997852 2
3997853 29
3997854 2
3997855 5
3997856 2
3997857 3
3997858 2
3997859 0
3997860 2
3997861 7
3997862 2
3997863 3
3997864 2
3997865 5
3997866 2
3997867 47
3997868 2
3997869 3

Process returned 0 (0x0) execution time: 0.010 s

Алгоритм точно такой же наивный с полным перебором. Но в 160 раз быстрее. Так что оговореннная архитектура наносит какие-то ограничения, но и без неё у хаскел оптимизатор упирается в намного более серьёзные ограничения. Он ещё 1.6 ГБ памяти потратил. Даже 4 млн по 8 байтному bool — всего 32 МБ промежуточных данных. Честно, нет идей, откуда такие большие числа.
НЛО прилетело и опубликовало эту надпись здесь

Погодите, а разве в том примере есть полиморфизм в рантайме? Вроде же компилятор должен всё раскрыть...

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

Нет. Про скобочки?

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

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

Меня когда-то впечатлил вот этот ted talk - https://www.youtube.com/watch?v=60OVlfAUPJg (транскрипт - https://ted2srt.org/talks/conrad_wolfram_teaching_kids_real_math_with_computers), tldw: если изначально интегрировать компьютер в процесс обучения (в данном случае - в процесс обучения математики), то можно достичь намного более интересных результатов, чем сейчас. Действительно, подружить школьников с wolfram/matlab/etc, а не заставлять 11 лет учить, как решать очередной вид уравнений на бумаге - мне кажется намного полезнее с практической точки зрения.
Наверное (экстаполирую), практическую часть любого другого STEM-предмета можно преподавать не как "читаем учебник, решаем задачки в тетрадке", а как "читаем учебник, пишем программы, которые что-то считают, моделируют или визуализируют". В таком процессе обучения, программирование (в каком-то виде), понадобится изучать весьма рано, и программировать нужно будет много и часто. Но от воплощения в реальность все эти мечты, конечно, довольно далеки.

И да, и нет. Да — действительно, пускай пользуются и осваивают. Нет — должен быть достаточно прочный фундамент, чтобы человеку позволить пользоваться благами цивилизации. Знаете, люди уже настолько разленились, что не могут двухзначные числа складывать в уме. Это вызывает не то что боль, а полный ступор. То же и с более сложными материями — те же производные. Я знаю алгоритм как их брать, вероятно возьму любую. Но как только я умею это делать — не зазорно пользоваться тем же Матлабом (мне, кстати, больше Maple нравился), чтобы перепроверять свой результат. Именно так работает обучение. Иначе будет… Как пример.
Девочка 27 лет. У нее apple Watch. С цифровым дисплеем. И она жалуется — как вы пользуетесь аналоговым циферблатом. Де, родители меня не научили, думали, что в школе научат, а в школе уже думали, что все это знают — как по стрелкам определять время. А признаться в незнании было стыдно… И это реальный уровень современного поколения. Куда мир катится :-/ Зато вот игрушки на айфоны ставят с закрытыми глазами (сужу по своим малолетним детям)

Чем больше всего в школе, тем лучше! Вот у меня была информатика в школе, крутые преподы из военного училища, в начале вообще были i386 и дос, потом олимпиады, тусовки, внеклассные занятия. Было классно! Турбопаскаль, ООП, оверлеи, память, изучали и делились знаниями друг с другом. Интернета тогда не было!
НЛО прилетело и опубликовало эту надпись здесь
Это вы уже наверное забыли приколы с форматным вводом, с памятью, с массивами.
В Паскале все это вводится постепенно исходя из назначения. В Си — сразу и исходя из реализации.
Да банальный scanf требует задания форматной строки и ссылки на переменную.
Для седьмого класса средней школы С был всё же мутноват.

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

А какого возраста дети? Сколько часов занятий у них в неделю, есть ли домашние задания, и если есть, то какого объёма в часах? Понятно, что это посчитать сложно, но, наверно, есть приблизительные оценки?

И можно ли где-то посмотреть программу обучения (мне это очень интересно)?

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

макросы еще есть. В том числе function-like macros. Если научиться их готовить, можно относительно сносно жить.

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

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

В том-то и дело, что чтобы говорить об отказе от исключений, надо обсуждать Раст с must_use и оператором ? — или Хаскель с монадами и HKT.


В языке Си обработка ошибок устроена ещё хуже чем позволяют исключения.

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

Не могу согласиться с этим тезисом. Потому что на уровне Си Вы можете заигнорить все коды ошибок и никто этого не узнаёт при компиляции. Только если самому глазками смотреть код и в документацию на используемые функции

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

в С нет исключений, так что неактуально.
в С++ — вроде были способы это пофиксить, но тут лучше 0xd34df00d подскажет

в С++ — вроде были способы это пофиксить, но тут лучше 0xd34df00d подскажет
тут ключевое слово «были» — спецификатор throw в с++11 депрекейтнули, а к с++17 удалили из стандарта. Самое явное что можно сделать — навесить noexcept(false), что по сути является значением по умолчанию

Ну, я не говорю, что С++ идеал. Но вот в Растра ты же пишешь Option? Значит, ты уже заранее знаешь какие варианты exception может кинуть конкретная функция??

только не Option а Result, это я и назвал явностью — возможность увидеть все типы ошибок из объявления функции
НЛО прилетело и опубликовало эту надпись здесь

Во‐первых, warn_unused_result в стандарте нет. И в заголовочных файлах libc я его что‐то тоже не особо вижу. Не знаю, как в других libc, но ag -i unused $(qlist glibc | grep include) нашёл мне кучу комментариев, несколько идентификаторов, определение атрибута и целых две функции, которые им всё же аннотировали.


Во‐вторых, если функция в случае ошибки возвращает NULL, а без неё — указатель на что‐то, то warn_unused_result ни разу не поможет: вы же результат используете! А то, что fwrite не может записать строку в NULL, полученный от провалившегося fopen компилятор не знает. (Вообще, есть атрибут nonnull, но он вроде не заставит вас доказать компилятору, что вы не передаёте NULL в функцию, он просто не даст его молча передать в явном виде.) Ошибки, возвращаемые в виде специальных значений используемого типа ещё хуже: под них даже атрибутов нет.

Во‐первых, warn_unused_result в стандарте нет
это такая же категория компилятора языка С, как и категории документации компилятора rust (стандарта то у него нет)
Во‐вторых, если функция в случае ошибки возвращает NULL, а без неё — указатель на что‐то, то warn_unused_result ни разу не поможет: вы же результат используете!
тут вы конечно правы. Но я всё еще утверждаю не то, с чем вы спорите
это такая же категория компилятора языка С, как и категории документации компилятора rust (стандарта то у него нет)

извините, но это чушь. Почему? Потому что Си — это промышленный язык и он стандартизирован. Возможно, это пережитки прошлого и на текущем этапе развития нам не нужные специальные стандарты ISO/МЭК и прочие на ЯП. Но Rust/Python etc. являются стандартом де-факто. Т.е. референсный компилятор + референсная оригинальная документация. На ней нет штампа "стандарт". И она меняется согласно времени. Но поведение компилятора версии от вчерашней даты детерминированно и это всех устраивает :-/

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

Во-первых, «референсная оригинальная документация» (как будто бывает фальшивая документация) написана для пользователей, а не для разработчиков компиляторов. Она может быть недостаточно точной в определении требуемого от компилятора поведения.
Во-вторых, если rustc и mrustc расходятся в поведении, кто из них будет прав? Правильный ответ — никто, ведь нет однозначных требований, которым должна удовлетворять каждая из реализаций.

Да, для языка с одним «кошерным» компилятором и одним подражателем такое положение дел может казаться нормальным, но это только до тех пор, пока мы не вспоминаем что rustc это лишь один из многочисленных фронтендов llvm, гарантии миддленда которой «сильно коррелируют» с требованиями стандартов си/плюсов…
кажется, вы не понимаете, зачем нужен стандарт.

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


Во-вторых, если rustc и mrustc расходятся в поведении, кто из них будет прав? Правильный ответ — никто, ведь нет однозначных требований, которым должна удовлетворять каждая из реализаций.

очевидно тот, который принят как референсный. В случае Python — рискну предположить, что это будет CPython, а не что-то еще. И в этом случае все неоднозначности будут решаться в пользу "делай как в CPython" (либо заводи ишью на багу)

Вы же помните — сколько было стандартов С/C++ со всеми их расширениями и все равно компиляторы реализуют что-то отличное?
тем не менее компиляторы стремятся к соответствию стандарту. Стандарта нет — каждый делает как хочет и забивает на остальных, а пользователи пытаются обходить все эти различия, как с джаваскриптом в браузерах…
очевидно тот, который принят как референсный
а если референсный в этом месте вообще крашится? Или его поведение больше похоже на баг? Или если его поведение не реализуемо для архитектуры, под которую писался не-референсный?
(либо заводи ишью на багу)

this. Спецификация С++ — тоже боженька, в которой (я это гарантирую) — это UB, это UB и это UB. Но по факту выясняется, что интерпретация этого UB у конкретного компилятора или его семейства вполне конкретная. И что хуже — народ на это поведение завязывается. Ну, и как с этим можно работать? :-)


Типичный https://www.hyrumslaw.com/

this
а если мейнтейнеры референсного компилятора не считают это багой, то вы должны внести в свой компилятор то, что считаете багой?
И что хуже — народ на это поведение завязывается
точно так же, как народ завязывается на поведение компилятора раста, которое может поменяться в любой момент любым образом по желанию мейнтейнеров?
Типичный www.hyrumslaw.com
ну вот стандарт и нужен для того, чтобы народ мог завязываться на документированное и гарантированное поведение, нежели на текущее обозримое.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Ну ничего, обсудят и выпустят какой-нибудь текст (пусть даже в виде ишшуе на гитхабе), разъясняющий поведение
вопрос банально в другом. Если вы видите что поведение компилятора неочевидно, в с++ вы можете проверить это в стандарте, и убедиться в наличии баги либо у вас, либо в компиляторе. А в расте вы нигде не сможете перепроверить ни себя, ни компилятор
в с++ вы можете проверить это в стандарте

наивно


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

тоже наивно.


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

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

точно так же придется топать к разрабам компилятора или писать тест кейсы...
Да, конкретно у вас в программе поведение является неожиданным независимо от того, кто там прав а кто виноват. Однако не забывайте что вы не наступили на некоторое число багов компилятора только потому, что N лет назад кто-то до вас их отрепортил и их не дропнули с аргументацией «wont fix lol», а пофиксили, потому что «нипастандарту».
список слабых мест C.
Указатели
Управление памятью
Никаких exception, упали значит упали ;)


Извините, как указатели могут быть «слабым» местом? Если управление памятью — это как раз сильное место Си.

Никаких exception, упали значит упали ;)

Это шутка ??? То есть в языке Си нету инструмента для обработки ошибок да?
Упали значит упали, да ??
По моему скромному мнению, самое слабое место в C/C++ — это огромное количество ситуаций с UB, но оно не влияет на начало обучения. Но опять же, если бы мне предложили выбирать подобный язык для начала обучения, я бы выбрал паскаль (и я по-прежнему считаю, что в школе нужно показывать программирование на калькуляторе).
По моему скромному мнению, самое слабое место в C/C++ — это огромное количество ситуаций с UB, но оно не влияет на начало обучения.

Дело даже не в UB напрямую. Вот вы перемножили два intʼа равных миллиарду, а почему вместо произведения вдруг мусор? Нормальное ожидание новичка — или точное значение, или явная ошибка. От UdB он вообще в шок выпадет, но и "тут мы урезали до 32 бит, а что было в реале — сами разбирайтесь" не понравится, мягко говоря.
Python: попытался вызвать метод у None? Вот тебе чётко определённое, понятное исключение. Строка вместо числа? То же самое. Целые числа? Ну вот они тебе до (кажется) 2^1016-1. А если таки вылезешь за границу — привет, опять же понятное исключение.
Это не однозначный аргумент за выбор Python — у него масса других недостатков — но и заметно против C.
Вообще из более-менее массовых языков лучше всего, IMHO, Swift — только надо аккуратно его отвязывать от специфики Apple. Следом — C# и Java. Не-процедурные тут не рассматриваю, это отдельная тема, хотя идея начинать с LISP была не худшей...

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

ответ на вопрос для самопроверки
Стандарт предписывает минимальный размер для int в 16 бит (при этом он не обязан быть кратным восьми)


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

Что насчет golang? Статическая типизация плюс минималистичный синтаксис.

Что насчет golang?

Может, у меня перекошенное впечатление, но:
Отказ от наследования — по многим представлениям чуть ли не высочайшая доблесть в ООП, но с современной практикой приводящая к чудовищной плотности бойлерплейта. Писать в таком стиле сильно сложнее, чем с наследованием, и не оправдывает себя.
Невменяемое комьюнити, выросшее во многом на противопоставлении себя другим по принципу "Учение Пайка истинно, потому что верно". Даже споры типа Linux vs. Microsoft не приводили в последние лет 10-15 к такому накалу.
Компиляция статическая, но реально слабая (все средства сборки самопальные и применить туда лучшие мировые практики тупо нет ресурсов).
В сумме, это пока приводило к "не нужно и ещё долго не видно потребности".
"Минималистичный синтаксис" для обучения далеко не всегда полезен.
В общем, может, в десятку и попал бы, но в самом конце.

Зависит от точки зрения.
«Урезали до 32 бит» — я считаю, что это огромный плюс языка С. Новичок хотя бы должен/обязан понять, что существуют биты и байты. А то развелось много программистов, которые даже не знают об их существовании.

Ну вот когда новичок при попытке умножения 1000000000*1000000000 получит ArithmeticOverflowException — это чему-то научит положительному.
А если он получит 2808348672 — при обучении по "бразильской системе", может, 10% и пойдут дальше, но 90% поступят как здесь.
Ваша лично цель какая — обучить, или уменьшить количество возможных конкурентов?

Можно подумать, разница между "ой, моя программа почему то упала" и "ой, моя программа почему то неправильно считает" есть разница.

Можно подумать, разница между "ой, моя программа почему то упала" и "ой, моя программа почему то неправильно считает" есть разница.

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


Вы своим акцентом на "почему-то" пытаетесь, как я понял, намекать не просто на непонимание причин, но и на незаинтересованность ученика в их исправлении. А вот тут и начинается существенное различие. Критически важно при обучении программированию — формирование привычки к тому, что проблемы такого рода будут возникать и их надо исправлять (и что это нудно — даже в самой интересной работе только ~10% того, что отличается от скучной рутины). Но если рабочая среда способствует выявлению ошибок, это лучше, чем если она их тщательно прячет, а для ученика — у которого нет ещё набитых шишек и съеденных собак в поиске предполагаемых проблем — это критически важно.

Упала — это легко обнаруживаемое событие


Не всегда. Для падения по целочисленному переполнению нужно подать на вход алгоритма те самые данные. Unit test поможет, скорее всего. Но он точно так же поможет, или не поможет, в программе на С.

на непонимание причин


Да. Когда всё спрятано глубоко под капотом — причину понять может быть сложно. КМК.
Не всегда. Для падения по целочисленному переполнению нужно подать на вход алгоритма те самые данные.

Да. И в этом случае он явно откажет, а не напишет чушь.


Unit test поможет, скорее всего. Но он точно так же поможет, или не поможет, в программе на С.

Нет. Как только мы выходим в область undefined behavior, начинаются полные непонятки.


Вот одна из знаменитых дискуссий по этому поводу (а вообще их сотни). Заметьте: очень сложно предсказать факторы, которые повлияют, и в какую сторону. Опции компилятора влияют, будут 10 или 112 итераций, а лёгкое изменение кода, которое 1:1 сохраняет семантику, приводит к 3 итерациям. Потом вы взяли чуть обновлённый компилятор, у него что-то иначе по мелочи — сработало первым другое правило, и будет вполне законно 4 итерации или 30, имеет право.


Unit test? Вы протестировали функцию отдельно, но компилятор в реальном коде её заинлайнил и из-за общих оптимизаций после инлайнинга сработали другие оптимизации — и вот ваш unit test превратился в тыкву.


Потому я и говорю: ~95% кода даже на C/C++ все эти высокие оптимизации тупо не нужны и должны быть запрещены по умолчанию. Сложение чисел? Исключение по переполнению. Алиасинг? Считать, что происходит всегда и везде. Пустые указатели? Не выкидывать проверку. И прочая и прочая. И включать разрешения не по какому-то глобальному debug/release, а с управлением по контексту (может, и управляемо от debug/release, но по месту). Вот где программист подумал (и хорошо подумал), там и явно разрешит.
Быстро C к этому не придёт, но "дорога в 1000 ли начинается с одного шага".


Да. Когда всё спрятано глубоко под капотом — причину понять может быть сложно. КМК.

Но когда оттуда прибежит исключение — оно будет видно. А если просто другое значение — и не увидите.
Особенно этим чревата математика. Пусть если X>0, мы идём на ветку "отрабатывать градиентный спуск вниз", а на X<0 — симметрично, вверх. Результат — просто координата вероятно оптимальной точки. Когда вы найдёте, что при определённых достаточно редких условиях реализация грубо лажает?

Есть разница. Потому что, как абсолютно верно заметил netch80, ошибки могут жить годами и быть необнаруживаемыми. Пока не случится катастрофа. Как с боингом или тераком. Лучше уж явное падение, чем неявное ковыляние. Лучше fail fast, чем наоборот. Лучше покрывать код тестами, но тогда, когда разрабатывался Си — это только в проекте было. Сейчас же в том же голанг юнит тесты вообще одно удовольствие писать )

Само по себе понятие exception еще более сложное, чем понятие о битах и байтах. Примерно как сказать, пишите программы как получится, но знайте, что есть «бог», который вас рассудит и наверное протянет руку помощи, если что-то пойдет не так.
Вы еще попробуйте объяснить, как на самом деле работают исключения.
Примерно как сказать, пишите программы как получится, но знайте, что есть «бог», который вас рассудит и наверное протянет руку помощи, если что-то пойдет не так.

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

Я видел вот такие программы написанные новичками:

int real_main()
{

}

int main()
{
try {
real_main();
}
catch( int e)
{}
return 0;
}

Это все, что они могут делать с исключениями.

Ну, есть принципиально два разных подхода — исключения и проверка кодов возврата на все возможные ошибки. Они оба имеют свои недостатки. В принципе, можно комбинировать, но аккуратно. Выглядит так, что второе ок больше для своего кода. Первое лучше для библиотечных вещей, потому что любое исключение своего рода goto и нарушает прямолинейный flow выполнения программы. Но в Python исключения реально структурные и достаточно удобные. А не вот это вот, что написано в С++ style. Кстати, в Си исключений нет и не было (!) Там была история с setjmp/longjmp и какой-то второй механизм, но я забыл.
Ну, и исключения должны быть исключениями, а не штатным поведением… На самом деле дискуссионная тема до сих пор
Например, первое, что выдается с хабра https://habr.com/ru/company/ruvds/blog/533332/

Ладно, не будем спорить. Во многом вы правы.
Все, что я хотел сказать — когда учишь язык C, начинаешь понимать, как на самом деле работает компьютер.
Уча язык Python можно научиться многим правильным технологиям, но трудно понять, как физически работает компьютер.
Все, что я хотел сказать — когда учишь язык C, начинаешь понимать, как на самом деле работает компьютер.

Вообще-то уже давно нет: например, никакой C не позволит понять, например, переименование регистров в Tomasulo algorithm (на котором стоит вся современная out-of-order обработка команд) — это даже ассемблер уже не даёт. Или, например, C ничего не скажет про переключение режимов и почему в x86 через task gate это дорого, а через syscall дёшево.


И вы наверняка не знаете, например, как именно ваш чипсет общается с модулями DRAM: как их память замаплена на адресное пространство, как переставляются адресные линии при выходе на конкретные модули (и почему именно такая перестановка помогает распараллеливанию доступа при типичных шаблонах потребления), что именно делает южный мост (даже если в нёт Management Engine) при старте компа, как выбирается стартовое ядро, и ещё 1000 подобных мелочей… и это разве мешает вам программировать на C, который по сравнению с этим всем примерно так же абстрактен и высокоуровнев, как JavaScript?


Да, какую-то часть C даёт: что есть память с организацией по байтам… да в общем-то и всё. Остальное 1:1 по всей цепочке через Java к Python.


Уча язык Python можно научиться многим правильным технологиям

Они для 99% и не нужны. Им нужны качественные средства для реализации их задач плюс понимание каких-то азов, типа, почему методы с O(N^3) становятся неэффективны при росте N — ну это одинаково что для ассемблера, что для LISP.

Вообще-то уже давно нет: например, никакой C не позволит понять, например, переименование регистров в Tomasulo algorithm (на котором стоит вся современная out-of-order обработка команд) — это даже ассемблер уже не даёт. Или, например, C ничего не скажет про переключение режимов и почему в x86 через task gate это дорого, а через syscall дёшево.

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


Отдельная история — это нюансы с быстродействием. Почему какой-нибудь цикл for (… ;--i) не эквивалентен for (…; i++) или for (…; ++i)

НЛО прилетело и опубликовало эту надпись здесь
Это все, что они могут делать с исключениями.

Всё что они могут нормально сделать — это просто не ловить, и программа вылетит. А тут уже кто-то сделал грубый хак. Кстати, скорее не catch(int e), а catch(...).
И вот тут дело учителя — за такой хак бить по виртуальным рукам точно так же, как за любые другие диверсии.

НЛО прилетело и опубликовало эту надпись здесь

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


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

так как stack unwinding при отсутствии обработчика исключения — implementation-defined, и gcc, например, делает это не всегда.

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

НЛО прилетело и опубликовало эту надпись здесь

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

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

Не "рука помощи от бога", а опознание ошибок и репорт их. Вот, например, вы открываете файл по некоторому пути на запись, а он оказался каталогом. Все ОС скажут "иди нафиг". А надо было заранее проверить, а иначе ОС накидает туда кучу мусора, так? Или чтобы писалось в пустоту?


Вы еще попробуйте объяснить, как на самом деле работают исключения.

Для объяснения для того, кто только учится программировать, достаточно, что управление безвозвратно (вот это я в 96-м или около того, когда читал про исключения, понял ой не сразу) передаётся в ближайший адекватный catch (местами except).
А как оно внутри реализовано — это уже ближе к "сеньору".

Не "рука помощи от бога", а опознание ошибок и репорт их. Вот, например, вы открываете файл по некоторому пути на запись, а он оказался каталогом. Все ОС скажут "иди нафиг". А надо было заранее проверить, а иначе ОС накидает туда кучу мусора, так? Или чтобы писалось в пустоту?

Надо, чтобы вы не могли использовать открытый файл при наличии ошибки. Этого добиваются и исключения, и алгебраические типы данных вида Result<File, IOError>, но из этих двух альтернатив только одна показывает, что ошибка может возникнуть именно здесь и заставит обработать её программиста, а не компилятор.


Для объяснения для того, кто только учится программировать, достаточно, что управление безвозвратно (вот это я в 96-м или около того, когда читал про исключения, понял ой не сразу) передаётся в ближайший адекватный catch (местами except).

Только оно передаётся не туда, точнее, не сразу. В C++ есть деструкторы. В Python есть finally и __exit__ (который, кстати, ещё может отменить исключение, так что до «ближайшего адекватного except» дело не дойдёт). Объяснить RAII или использование with придётся, если вы хотите, чтобы программы могли адекватно обрабатывать исключения, а не просто падали с другим сообщением об ошибке.

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

То есть вы за принуждение к обработке ошибок на месте, я правильно понял? Я вообще-то говорил немного о другом. Тот же случай открытия каталога на запись в обычном Unix* libc вернёт -1, и дальше уже обязанность программиста проверить (может, сгенерировать исключение, если хочет), но по крайней мере не пустит сделать диверсию. Как именно ловить и обрабатывать ошибку уже следующий вопрос. Вон в Python есть connect(), который генерирует исключение, а есть connect_ex(), который возвращает числовой код. Жаль, что таких мест в нём мало, и почему-то некоторые решения странные (например, поиск в строке выдаёт -1 по ненахождению, а в списке — исключение).


Только оно передаётся не туда, точнее, не сразу.

То, что вы пишете, уже следующий уровень понимания. Он нужен, но вначале надо понять первый уровень — что исполнение завершается тут на throw (raise) и продолжается на подходящем catch (except).

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

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


Я вообще-то говорил немного о другом. Тот же случай открытия каталога на запись в обычном Unix* libc вернёт -1, и дальше уже обязанность программиста проверить (может, сгенерировать исключение, если хочет), но по крайней мере не пустит сделать диверсию.

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


С тем, что ошибки случаются вроде никто не спорил. Ранее спорили с тем, что считать ошибкой конкретно при перемножении целых. А тот ваш комментарий, на который ранее в этой ветке ответил я, был ответом на комментарий с содержанием примерно «при исключениях непонятно, что происходит» без продолжения спора о том, что считать ошибкой при использовании целых. Логично, что ответ вида «ошибки случаются, нужно ли при возникновении ошибки воспринимать её как UB» на комментарий «исключения непонятны» воспринимается как «ошибки случаются[, значит, нужно выбросить исключение, потому что UB это плохо]».


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


(А в реальных программах мне кажется лучше иметь, на выбор, возможность использования * как panicing_mul/checked_mul/wrapping_mul/…, или способ доказать компилятору, что здесь переполнения не может произойти — с ошибкой компиляции, если доказательство некорректно. У Rust пока есть только первый вариант в не слишком удобном виде (но, возможно, кто‐то сделал более удобный макрос).)

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

Вот почему "всё ещё лучше исключений", непонятно.
Варианты Option, Nullable, и т.п. — это, да, удобнее и чётче всяких "(size_t)-1 как признак ошибки", но абсолютизировать их тоже нет причины. Лучше всего они как раз на нижних уровнях интерфейсов, где сейчас имеем тупые костыли типа "получил INT_MAX — загляни в errno".


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

Это уже усиление моего тезиса, а не его парирование.


Логично, что ответ вида «ошибки случаются, нужно ли при возникновении ошибки воспринимать её как UB» на комментарий «исключения непонятны» воспринимается как «ошибки случаются[, значит, нужно выбросить исключение, потому что UB это плохо]».

Я уже в вашем ответе перестал понимать — вы согласны с этим (что исключение в общем случае лучше UB) или нет?


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

Что именно вы называете такими практиками?
Моя позиция достаточно проста и прямолинейна:
1) Бо́льшая часть кода требует поддержки компилятора/среды/etc. для защиты от любых ошибок, включая те, которые программисту сложно отловить в силу его специфики человеческого мышления, даже если опознаются заранее. И только малая часть кода должна писаться с расчётом на "мы тут проверили всё и разрешили компилятору максимум свободы".
2) Средства реакции на ошибку должны как можно раньше давать её вскрытие и переключение на обработку.
3) Для большинства современных языков механизмами для (2) являются исключения (в Go, Rust — паники), тем более что они за счёт неявного побочного канала позволяют писать в духе a+b*c вместо даже sum(a, product(b,c).unwrap()).unwrap() (или как там в более новом Rust, не помню).


Что из этого списка у вас конкретно вызывает возражения, почему и какие?


И почему вы называете "доменом математических вычислений" арифметику в языке? Даже если это с какой-то точки зрения формально правильно, для данного вопроса это неоптимально.


Я лично с идеей не согласен: от перехватываемой ошибки тут толку намного меньше, выбрасывание паники с понятным сообщением вполне подойдёт для обучения

Вы за то, чтобы паника была, но перехватывать её было нельзя? Тогда — почему?
И как тогда учиться тому, что ошибки надо тоже уметь обрабатывать?
И как учиться тому, что ошибка может быть обязательной частью нормальной работы? Например, множество программ ищут свои конфиги в порядке: ./foo.conf, ~/.config/foo.conf, ~/.foo.conf, /etc/foo.conf, и отсутствие части из них это норма для 100% случаев — что, нельзя такое вообще ловить? Где предел вашей позиции по запрету ловить ошибки?


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

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

Вот почему "всё ещё лучше исключений", непонятно.

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


Я уже в вашем ответе перестал понимать — вы согласны с этим (что исключение в общем случае лучше UB) или нет?

Исключение действительно лучше.



Что из этого списка у вас конкретно вызывает возражения, почему и какие?

Из этого списка возражения не вызывает ничего, кроме того, что у Rust механизм для 3 — это Result, а не паника (если вы, конечно, хотите переключаться на обработку).


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


Вы за то, чтобы паника была, но перехватывать её было нельзя? Тогда — почему?

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


В меньшинстве случаев есть checked_….


И как тогда учиться тому, что ошибки надо тоже уметь обрабатывать?

Учиться обрабатывать ошибки на других функциях? Если хочется обязательно на ошибках в арифметике — checked_….


И как учиться тому, что ошибка может быть обязательной частью нормальной работы? Например, множество программ ищут свои конфиги в порядке: ./foo.conf, ~/.config/foo.conf, ~/.foo.conf, /etc/foo.conf, и отсутствие части из них это норма для 100% случаев — что, нельзя такое вообще ловить? Где предел вашей позиции по запрету ловить ошибки?

Это другой домен. Я не вижу причин, почему ошибки в арифметике должны работать так же, как и ошибки в IO. Причин делать обработку по‐разному же полно:


  • производительность;
  • удобство — при АТД вам будет нужно делать .unwrap() или другую обработку на каждое арифметическое выражение, у исключений тут правда преимущество: вам не нужно будет делать больше телодвижений, учитывая, что вам уже нужно везде применять RAII или аналог просто по факту существования исключений;
  • разные причины их возникновения — файл может пропасть, потому что пользователь решил почистить /etc, отправил его в NFS и отвалился сервер, …, в общем если это не опечатка в названии файла, то это не баг в программе, а переполнение — это обычно либо баг в программе, либо некорректный ввод (что тоже часто баг вида «недостаточно проверили ввод»).
НЛО прилетело и опубликовало эту надпись здесь

Ну-ну. Простейшая формула вида (a+b)*(c-d) в
этой вашей do-нотации в такой кошмар превратится...

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

а еще компьютер могут обесточить )))

Изучал C, потом C++. Как работают исключения почему-то понял сразу и без «надрыва» мозга. Дело было ещё в школе, если правильно помню. Оказалось, что всё просто, если понимать, как всё работает на уровне стэка, а эту часть я успел разобрать, когда изучал C.

Тем не менее, например, Windows SEH умеет возвращать, если попросят, управление обратно (может исправить условия для корректного выполнения кода), а исключения C++/Java/Python/etc. — нет, только безвозвратная передача. Всякие бейсики с on error resume next тоже дают другие варианты.
Почему легче поняли — не знаю, может, этот момент прямым текстом был описан. Я это учил по Страуструпу, а он много где откровенно так шифруется (о чём явно пишет).

С Windows работал очень мало, а тамошним скриптовым движком вообще не работал. Пробовал разобраться и понял, что не окупится. Я изучал по какой-то книжке, которую, возможно, ещё получится найти. Для понимания механизма мне хватило упоминания развёртки стэка и вызова деструкторов для всех объектов, созданных в стэке, до точки, где ловится исключение. Возможно, я лучше понимал механизм работы стэка. Правда, я начинал изучать программирование довольно странным способом и среди прочего, что я изучал ещё до начала полноценной работы с Си, были ассемблер процессора i8080, а так же продирался через книжку, в которой разбирался компилятор Small C. В общем, шёл от железа.

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

Оно как раз не позволяет программисту абстрагироваться от того как устроен компьютер

Увы, не так.


Если вы читаете доку по команде умножения, например, на x86, там будет сказано, например (IMUL трёхоперандный)


The intermediate product (twice the size of the first source operand) is truncated and stored in the destination operand (a general-purpose register).

"все слова несущие" © — про обрезание результата сказано явно, и кодеру подсказано думать "а может ли быть переполнение? должен ли я его проверять?" и средства даны:


The CF and OF flags are set when the signed integer value of the intermediate product differs from the sign extended operand-size-truncated product, otherwise the CF and OF flags are cleared.

Можно аналогичное поискать для ARM:


result = UInt(operand3) + (UInt(operand1) * UInt(operand2));
X[d] = result<destsize-1:0>;

пусть и не столь явно, но про урезание сказано.


Это всё чётко определённые операции. Тут утечки нет.


А что в C? Пусть даже стандарт:


The result of the binary * operator is the product of the operands.

учебники скажут примерно 1:1 про это же. Каким образом получается произведение, а не результат его усечения или вообще что-то левое? Где средства получить данные, получилось умножение или нет? Их не просто нет — проблема вообще не названа. Да, это и есть дырявая абстракция в полный рост.


В GCC и Clang, слава всем богам, добавили __builtin_mul_overflow(). Одно из того, что я хочу видеть в стандарте — это его же, пусть и с другим названием. (Но это только первый, базовый, уровень, а надо идти дальше.)
Вот с ним уже будет честная абстракция.


Если же вы предлагаете, чтобы обучаемый набил шишек на том, что стандарт тут не улучшился за 50 лет, и был готов к подобному на будущее… не спешите. И без C/C++ будут тысячи таких проблем, но вначале они могут только организовать "выученную беспомощность".

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

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

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

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


и режимы сборки не ограничиваются релизом/дебагом…

Я где-то предлагал ограничиться? Мой "поинт" совсем о другом: контекстное управление тем, что позволено компилятору, важнее общего режима сборки (хотя может корректироваться под последнего).

если не генерируется исключение
а если гарантируется? Стандарт с++ ведь должен учитывать даже такие платформы, а не только парочку общего назначения

что такое исключение на уровне ассемблера, простите?

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

System/Z: при установленном бите 20, команды знаковой арифметики (те, что не имеют logical в названии) генерируют прерывание при обнаружении целочисленного переполнения.


MIPS: команды знаковой арифметики (например, add, в отличие от беззнаковой addu) генерируют прерывание при обнаружении целочисленного переполнения.


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


Ну и into в x86, очевидно — аналогично.

Специальная инструкция, выбрасывающая в ядерный обработчик исключения. Раньше int 21h использовали (ну и другие) для функций DOS'а, сейчас чаще встречаются ошибки по делению на ноль, по доступу к памяти и т.д.
а если гарантируется?

Имеется в виду "генерируется"? Простите, специфика контекста требует уточнения. Пока буду полагать именно такое прочтение.


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

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


Если смотреть с практической точки зрения, то сейчас компиляторы даже при таких возможностях платформ их стараются не использовать. В System/Z, флаг PSW о генерации исключения по переполнению не ставится в известных мне ABI. В MIPS, есть add и addu, но GCC, Clang генерируют addu даже там, где однозначно операция со знаковыми. И я очень плохо представляю себе платформу, где исключение тут неотключаемо…
X86 с его исключением от деления на 0 здесь скорее исключение (не каламбур).

Ну вот они тебе до (кажется) 2^1016-1.

В cPython длинная арифметика для целых чисел. Только что сделал print(2**1000000), напечатало оооочень длинное число.

огромное количество ситуаций с UB, но оно не влияет на начало обучения

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


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

Но зачем? Программирование уже давно не (только) про вычисление.

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

Не согласен. Например, область видимости переменных очень быстро становится важна.

Я преподаю в ВУЗе, и на первый курс у нас приходит множество студентов, которые компьютера дома не имеют, и программирования в глаза не видели. В первом семестре они знакомятся с программированием, причём на питоне. И я вижу изрядное количество проблем (две из которых я привёл), которые случились исключительно из-за неинтуитивности языка.

Но зачем? Программирование уже давно не (только) про вычисление.

Да, но первый цикл всё же проще написать, когда магии вокруг нет, и понятно всё происходящее. Другой вопрос, что с калькулятором надолго не надо оставаться :)
А вообще (один раз) написать какой-нибудь морской бой на калькуляторе — почему нет?
Да, но первый цикл всё же проще написать, когда магии вокруг нет, и понятно всё происходящее

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


А вообще (один раз) написать какой-нибудь морской бой на калькуляторе — почему нет?

Потому что зачем? Какую задачу решает это обучение?

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

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

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

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

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

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

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


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

А это преимущество? Я вот не уверен.


А для тех, для кого это преимущество, есть Code Перцольда, кстати.

(В самом начале) не надо учить языку программирования. Надо учить основам. Чем интуитивнее инструмент для изучения основ, тем лучше.

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

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

Подождите, а в браузере что загружено-то?

Обучающий сайт.

а в браузере что загружено-то?

JavaScript же.

Простите, а какой программируемый калькулятор вы имеете в виду?
Советский МК-61? Какой-то из современных, какой именно?

Ой, я не имел в виду какой-то конкретный. В местных школах широко распространены Casio fx-3650P II, для первых опытов вполне пойдёт.

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

Вот для того, что бы таких «проблем» не было у новичков — я всем (кто хочет «войти в ИТ») рекомендую нормальные курсы смотреть, например базовый курс на русском по Python для начинающих на 35 (!!!) часов или Python Complete Masterclass for Beginners на 30 часов
. Там все такое разбирается.
Так же можно всегда почитать официальный туториал на английском.

Дом без геологоразведки же не строим? Так почему к Python мы относимся как к чему-то «простому»?
Дом без геологоразведки же не строим? Так почему к Python мы относимся как к чему-то «простому»?

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

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

У меня на Паскаль строгая аллергия. Уж не знаю. Язык сам, наверное, неплохой. Но хочется, чтобы учили чему-то практически полезному. И здесь пайтон выигрывает 100 очков вперёд. С другой стороны, действительно нет разницы на чем писать алгоритмы ) надо провести опыт и попробовать жене (которая вообще нуб в программировании) показать голанг )))

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

При обучении всегда встаёт вопрос про полезность и эффективность для группы обучающихся, и не всегда ответ на него очевиден. Конечно, если речь не идёт о личной образовательной траектории. Много людей здесь и на других ресурсах пишут свой личный опыт развития, чаше всего по линии программист. Но он слабо применим к массовому процессу обучения. Причём надо ещё отличать обучение в школе и институте — разное всё: и мотивация, и подход, и углублённость, способность усваивать.

Списки можно распаковывать звёздочкой.

Если кого-то пугает scoping rules, то можно вспомнить, что Питон таки ООП, и не писать голые функции, а прятать всё в объектах.

И это если не стоит задача просто слоёв в керасе накидать для тензорфло.

Если кого-то пугает scoping rules, то можно вспомнить, что Питон таки ООП, и не писать голые функции, а прятать всё в объектах.

А теперь расскажите, как это объяснять тому, чей опыт программирования — пара месяцев.

Никак )

А надо?

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

Бомбануло с примера после 2 10!!! По приколу бывает балуюсь на своём питоне, но так вымораживает бывает. Вроде всё правильно делаешь, но оно не заводится. Чуточку перефразируешь код — работает… Думал у меня галюники и чертовщина какая-то в этом питоне, а оно вон как!) ууу. Так а в чём там проблема в 3 примере? Или для питонистов это не объясняется?)
Ну всё просто (когда знаешь правила видимости переменных в питоне): по умолчанию на чтение переменная глобальная, на запись локальная.

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

Но у меня регулярно сносит мозг от того, что есть переменные локальные, есть глобальные, а есть НЕЛОКАЛЬНЫЕ! См. ключевые слова global и nonlocal. Я знаю далеко не все языки программирования, но такую логику видел только в одном месте.

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


И, вообще говоря, я не вижу причин использовать ключевое слово global, можно от него отказаться и использовать только nonlocal. Тогда ничего мозг сносить не будет.

И, вообще говоря, я не вижу причин использовать ключевое слово global, можно от него отказаться и использовать только nonlocal. Тогда ничего мозг сносить не будет.

nonlocal не даёт доступ к глобальным переменным, проверяется банально.


$ cat t1.py 
a = 1
def f():
    nonlocal a
    print(a)
f()
$ python3 t1.py
  File "t1.py", line 3
    nonlocal a
    ^
SyntaxError: no binding for nonlocal 'a' found

Хм, даже так? И правда "хороший" язык, однако...


Впрочем, изменяемые глобальные переменные всё равно не нужны.

Как-то особенно и аргументов не увидел…
Во всяком обучении важна мотивация. На Python очень простые и классные библиотеки для всего, которые осваивает даже ребенок. То же самое касается языка программирования.
Когда можно с минимальными знаниями уже написать игру или еще какую-то программу, которая нравится, то это очень мотивирует к изучению принципов программирования.
А дальше доизучать низкоуровневые вещи, которые видны в C и стиль типизированного программирования — это не сложно.
Сама идея о том, что можно что-то испортить начав не с того — она довольно абсурдна. Можно наверно неправильно научиться держать музыкальный инструмент а потом долго переучиваться, это да. Но истины можно познавать в любом порядке. Здесь нет опасность испортить себе стиль, начав не с того.
Сама идея о том, что можно что-то испортить начав не с того — она довольно абсурдна

почему? На самом деле в этом есть некий смысл. Как у нас устроен процесс обучения в учебных заведениях? Что-то изучаем, а потом "дети, забудьте все, чему вас учили, потому что на самом деле так..." И так несколько раз. Если человек запоминает что-то неправильное или формирует неправильные привычки — потом гораздо сложнее перебить это, чем сразу учить правильно. Та же история с языками программирования. Есть дилемма. То ли изучать это все сверху вниз (от python к Си и ассемблеру). То ли наоборот — от каких-то фундаментальных вещей (регистры процессора, виртуальная память — к более высоким слоям абстракции). В первом случае мы действительно можем сразу получать практические результаты. Во втором — мозг раньше закипит, чем получишь что-то осязаемое, зато сразу понимаешь что и как работает.
С третьей стороны — алгоритмы вообще инвариантны к ЯП. Какая разница на чем писать пузырьковую сортировку?

Если человек запоминает что-то неправильное или формирует неправильные привычки — потом гораздо сложнее перебить это, чем сразу учить правильно.
Вот это вообще не верно, если вы только не задаетесь целью надрессировать обезьяну. На самом деле есть некая скрытая истинная картина, которую в конечном итоге нужно понимать. Эта картина может приоткрываться с любой стороны и в любой последовательности. Лишь бы был интерес к обучению. Если часть картины открыть не совсем верно, это тоже лучше чем вообще ничего — исправить знание всегда проще чем понять с нуля.
Если у человека недостаточно ума, чтобы эту картину понять, то в какой последовательности его не учи, он все равно не будет эффективен. Если достаточно, то все равно в итоге у него будет вся картина.
Если вы изучили нечто, что выглядит как магия, то тем интереснее и проще изучать что находится внутри этой магии и как она работает. Потому что сразу будет понятно зачем существуют те или иные базовые вещи и сразу есть полигон для отработки.
И наоборот, если вы изучили сначала базовые вещи, еще не понимая что из них можно слепить, то дальше проще изучать как из них получается эта магия.
Никакой из этих путей ничего не портит, можно выбирать любой, если он нравится.
ИМХО, все рассуждения о том, чего нельзя изучать в начале — это оправдания лентяев, которые не хотят начать с неправильного, а в итоге не начинают ни с чего.
Или еще бывает другой вариант — в программисты попадает человек с гуманитарным складом ума и он все время позорно не понимает базовых вещей, хотя обучается оперировать с высокоуровневыми. В итоге окружающие специалисты делают вывод, что он был испорчен тем, что начал с высокоуровневых вещей. Но на самом деле, если бы его начали учить с C и ассемблера, он все равно ничего не запомнил а только возненавидел бы все программирование. А уже когда он программирует, то заставить его понять низкоуровневые вещи будет даже легче, потому что теперь он хоть понимает зачем это ему.

У меня был знакомый, который создал компанию, нанял программистов и вывел на рынок продукт. При этом попутно немного вник в веб-программирование и изучил основы одного ЯП. А потом прочитал книгу для детей об основах информатики и был от нее в страшном восторге, типа теперь ему стал понянен смысл всего программирования. При этом то что он прочитал в этой книге он читал с детства на каждом заборе, но это все не имело для него никакого смысла, поскольку он не программист по складу ума и его мозг не видел зачем это все, а когда он уже видел зачем, то сумел понять и базовые концепции.
Как у нас устроен процесс обучения в учебных заведениях? Что-то изучаем, а потом "дети, забудьте все, чему вас учили, потому что на самом деле так..."

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

НЛО прилетело и опубликовало эту надпись здесь
Сама идея о том, что можно что-то испортить начав не с того — она довольно абсурдна.

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

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

Ммм? Неэффективное обучение == недостаточно уверенные знания и отсутствие уверенности в своем коде == никакой программист.

Стиль мышления скорее зависит от решаемых задач чем от языка. И от них же зависит выбранный язык.

Мы говорим о том, какому языку учить неопытных студентов, а не о выборе языков профессиональным программистом.
Мы говорим о том, какому языку учить неопытных студентов, а не о выборе языков профессиональным программистом.
Вообще-то нет. Мы говорим о том, какому языку учиться, если учишься сам и у тебя есть выбор: такому, который больше нравится и больше соответствует задачам, которые нравится решать.
Если говорить о системе образования, это отдельный вопрос. Студентов кормят насильно и они вообще часто не могут быть программистами в итоге. Там важнее объем усвоения материала. Профессионализм появляется в реальных проектах а не во время обучения.

Что касается выбора первого ЯП для будущего профессионального программиста, то это вообще вопрос неважный. ЯП — вообще не проблема и изучаются очень легко, если это не Хаскель. Сложности начинаются когда надо написать десятки тысяч строк кода и не утонуть.
Вообще-то нет. Мы говорим о том, какому языку учиться, если учишься сам и у тебя есть выбор: такому, который больше нравится и больше соответствует задачам, которые нравится решать.

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

А вот если взять сферического в вакууме неофита, у которого глаза горят заняться программированием — за какой язык ему схватиться, если он ни одного из них в глаза не видел? Из чего ему исходить, если он еще не знает, какие ему задачи нравится решать — ведь он еще не решал задачи программно? Спросишь такого — так он и игры писать хочет, и блокчейны, и сайты неземной красоты…

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

Ну как сказать… Есть чудесные языки (например, С++), в которых подводных граблей больше, чем блох на Бобике. А если их еще и изучать задом наперед, как это у нас принято (от С к С с классами), то изучение первого ЯП может закончиться той самой картинкой «буду проституткой».
Вы это сейчас говорите исходя из своего нынешнего опыта и ставите вопрос, фактически, повышения квалификации.

У меня другой опыт, в другое время. Сначала не программировал, потому что компьютеры еще вообще не продавались не теоретически прекрасно представлял как это делается по статьям в журнале «Юнный техник», потом программировал на бейсике, потому что ничего другого на касете не было, потом программировал на ассемблере, потому что удалось найти транслятор и потому что он позволял сделать диггера или пакмана, который работал быстро. Потом в институте — на фортране, потому что задачи на кафедре были только на фортране. Потом дельфи, потому что он был лучшим и так далее. Бейсик и фортран были изначально созданы для спагетти-кода, а ассемблер в совокупности к кассетным магнитофоном — это вообще ад кромешный. Но это же не значит, что я до сих пор пишу спагетти код или возненавидел программировать. Когда появился CBuilder, я практически рыдал от счастья, созерцая совершенство, мощь и простоту C++ (а вы говорите много граблей).
Сейчас время другое, но принцип тот же. Сейчас школьник открывает питон и сразу может написать кучу очень занимательных приложений для себя, если ему интересно. Или начитает писать моды на java для майнкрафта. Все это прекрасные пути развития навыков IT.
Что касается людей, которые реально начинают изучать свой первый язык программирования в институте — не знаю. Я пока не встречал ниодного такого, кто в последствие стал бы сколько-нибудь ценным специалистом. Однажды собеседовал автослесаря, который пошел программисты (успешно) в 45 лет. Но даже он признался, что впервые научился программировать подростком, купив компьютер «Вектор». Как можно дожить до взрослой жизни в мире, заполненным компьютерами, не попытаться программировать, не понимать ничего в ЯП, а потом вдруг начать учиться я с трудом представляю.
У меня другой опыт, в другое время. Сначала не программировал, потому что компьютеры еще вообще не продавались не теоретически прекрасно представлял как это делается по статьям в журнале «Юный техник», потом программировал на бейсике, потому что ничего другого на кассете не было, потом программировал на ассемблере, потому что удалось найти транслятор и потому что он позволял сделать диггера или пакмана, который работал быстро.

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

Я вот тоже начинал очень похоже. Сначала программируемый калькулятор и программы из журнала «Наука и жизнь» (даже свою программу им отсылал — но было уже поздно, они как раз прекратили публиковать программы на ПМК и перешли к компьютерным). Потом заимел один из вариантов ПК8000 (аж целых 64 килобайта памяти!) — сам разобрался с тамошним бейсиком (писан по мотивам MSX Basic), потом на том бейсике написал свой ассемблер, используя таблицу мнемоник из бумажной инструкции… Методом научного тыка разобрался с перестановкой байт в операндах и со значением многих команд. Тут помогли статьи в «Юном технике», кстати. Потом переписал свой ассемблер на ассемблере (помнится, даже простенький строковый редактор к нему прикрутил). Жаль, что все это уже, скорее всего, не восстановить — я писал на бобинный магнитофон, который уже тогда дышал на ладан…

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

На практике же детям это все давно не интересно. А студентам, которые по идее должны уметь программировать, лучше все-таки давать язык, в котором не придется 90% времени бороться с «особенностями».
Потом заимел один из вариантов ПК8000 (аж целых 64 килобайта памяти!) — сам разобрался с тамошним бейсиком (писан по мотивам MSX Basic), потом на том бейсике написал свой ассемблер, используя таблицу мнемоник из бумажной инструкции…
Ага, давайте меряться у кого детство было ужаснее. У меня был Радио-86РК с 24 кБ памяти. Звук издавался установкой и снятием запрета прерываний, дисплей был только алфавитно-цифровым без графики. Но зато ассемблер самому писать не пришлось — отец нашел через знакомых готовый.
Почему ужаснее? Зачем чем-то мериться? Я вообще о другом.

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

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

Да хоть Бейсик !

Я бы даже сказал иначе - вооон тот древний бейсик или самый ранний паскаль. Проще них найти сложно :)

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

Самых шустрых учеников, которые самостоятельно ищут и находят (ну пусть Питон), можно и НУЖНО "мучить" вопросами, которые "питон" прощает.

Ну и "напиши вот эту штуку тремя разными способами" помогают молодому человеку оценить важность пословицы "семь раз отмерь - один раз отрежь"

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

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

Например, Жак Арсак в своей книге «Программирование игр и головоломок» сокрушался, что ученики, изучавшие Бейсик, склонны потом на любом языке писать путаные программы безо всякой структуры и стиля. Просто потому, что Бейсик не требует никакой структуры, а «машина и так меня понимает».
Книжка, кстати, сама по себе интересная, даром что писана в 1980-х — посмотрел на обложку и вышибло ностальгическую слезу. :)

Бейсик — это, конечно, пример крайний. Но вот я, скажем, на работе ревьюил довольно большой объем кода, и уверенно могу определить, откуда пришел программист в С++. У бывших сишников свой очень узнаваемый стиль, у бывших джавистов — свои заморочки… А ежели человек, не приведи аллах, с функциональных языков начинал — о-о-о…

Бейсик, кстати, Бейсику рознь. Он, вероятно писал, про классический Бейсик с логикой на GOTO и GOSUB. Но уже в QBasic были функции, и учеников можно было учить писать более-менее приличный структурированный код. (Не призываю начинать с QBasic, если что.)


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

Но уже в QBasic были функции, и учеников можно было учить писать более-менее приличный структурированный код. (Не призываю начинать с QBasic, если что.)

Он преподавал во Франции в начале-середине 80-х. Тогда там в ходу были микрокомпьютеры а-ля советский «микроша» с убогим классическим бейсиком. Впрочем, еще у них был какой-то свой язык с ключевыми словами на французском… нашел: LSE (Langage symbolique d'enseignement)/

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

Даже через пять лет безошибочно определяются. Разве что с джавистами чуть посложнее — они за это время уже достаточно наполучали по рукам за new без delete и научились пользоваться умными указателями. :)
Даже через пять лет безошибочно определяются.

Я "начинал" с асма, паскаля и бэйсика (qb). Си не зашёл, хотя приходилось и с ним дело иметь. Плюсы и шарп уже из-за пропавшей актуальности не трогал. Можно сказать, давно уже серьёзно не "пишу" (ну, иногда что-то на php или 1С, да скрипты от cmd до ps и bash)… но моя школьная информатичка всё равно "узнала по почерку" программу, которую я, спустя 15 лет по окончании школы, набросал племяннику бывшего одноклассника. И да, свой код я стараюсь никому не показывать (ну, кроме кода 1С, который у меня не сильно хуже франчей получается)

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

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

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

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

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

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

Думаю, много что мешает.
Во-первых, обычно дают один язык на выбор (или один обязательный, второй факультативно). Это заложено в учебных планах и это спускается сверху из министерства. Два языка сразу могут посчитать ненужной самодеятельностью и перегруженность — а оно преподу надо?

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

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

Контрпример — в некоторых школах одновременно учат несколько иностранных языков. Греческий и латынь. Немецкий и французский. В крайнем случае — учат одновременно родной и один иностранный (английский). И ничего. Низкая эффективность обучения иностранного точно не связано с параллельностью изучения. А скорее с квалификацией педагогов и их низкой заинтересованностью в реальном обучении учеников


Во-вторых, преподаватель должен сам понимать, что он преподает и зачем.

Это да. Но настоящие программисты, которые пишут продакшн код, легко пишут на нескольких языках… Тот же 0xd34df00d наверняка знает более двух ЯП

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

Так-то оно так, да есть нюансы:
— Язык программирования — это все-таки не язык человеческого общения.
— Учат все-таки не одновременно, а на разных уроках. Еще и учителя обычно разные. Это создает четкое разделение в мозгу, и ученики полностью «переключаются» на другой язык.
— учебная программа по каждому из языков составляется так, чтобы дать требуемый минимум учебных часов.

Если же давать сразу несколько языков программирования на одном уроке — они неминуемо перемешаются в незрелых умах. Да и времени на изучение может не хватить: вместо худо-бедно полного изучения минимума по одному ЯП будет скакание по верхам для двух.
Впрочем, это лично мой скептицизм. Может, не все так плохо, как мне кажется. :)
В РФ в школах сейчас с 1го класса +английский, с 5го класса +немецкий. В некоторых школах экспериментально добавляется киатйский.

У нас в вузе небыло каких то прям требований к используемому ЯП, у нас были последовательно Pascal/С/С++/С#/SQL (по семестру), в рамках которых делали те или иные лабы. На других же предметах не связаных с изучением конкретного ЯП, сдавали кому как и на чём удобнее. И на соседних факультетах ± было так же. Разве не везде так?
Но настоящие программисты, которые пишут продакшн код, легко пишут на нескольких языках…

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

П.С.: поглядывая на ютуб, мне попалось, что в МФТИ так же, сначала питон, потом Си подмножество Плюсов. И один курс продолжает другой.

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

Хотя можно просто не выходить из "мира Питона", где нужна, допустим, производительность. Не-не-не, NumPy не предлагать - он-то Си-шный :)

НЛО прилетело и опубликовало эту надпись здесь
Мотивация — да!
Но в чём она? Быстрый красивый результат без знаний? Дети такое с руками оторвут! Урааа…
Только есть загвоздка — «дальше доизучать низкоуровневые вещи, которые видны в C и стиль типизированного программирования это ...» никому не нужно! В принципе. За нас написаны уже все библиотеки! Просто их надо найти и поставить в правильном порядке.

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


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

Но надо сначала определиться, является ли «питономан» приемлемым результатом обучения. Для меня и нашей компании учителей — нет. А рынок сейчас говорит «да» любому, кто написав программу в 10 строк пишет о знании языка.
НЛО прилетело и опубликовало эту надпись здесь
Да в общем-то не важно с чего начинать. Куда важнее не останавливаться: выучили один ЯП — выучите второй, третий. Профессионализм идёт из кругозора.
НЛО прилетело и опубликовало эту надпись здесь
начинающий не будет всем этим заниматься. А вот написать свой калькулятор или текстовый квест — достаточно для понимания что к чему, причем достаточно близкого к железу (н не слишком чтобы отбить желание). Правда, я бы не назвал эти достоинства аргументом в пользу того, чтобы не начинать с питона. Это скорее аргументы для того, чтобы в процессе обучения рано или поздно прийти к С.

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

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

Что то жирновато. Особенно о системе сборки и менеджмент зависимостей :)
Вообще то стоит сначала решить ехать или шашечки. Если ехать — пройти хотя бы базовый курс булевой алгебры, компьютерной логики, ассемблера. В общем, всего что лежит в основе. А то что начал с Python, что с С, а под капотом магия, любая внештатная ситуация введет в ступор и непонимание.

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

C отображает истинную картину того, чем является программирование.

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

Лучше вообще писать "Си".

Автор прав — чем больше людей учат не то, тем дороже я буду стоить. Учите С, ребят. Не мешайте мне)
Без обид, но вряд-ли «программист на питоне» может много стоить
Есть у меня знакомый, давно пишет на ++, офигенный прогер, золотая голова, но зарплата всего 1500. Правда если уходить, то можно рассчитывать на чек побольше, но лень. Есть и другой — питонист. Вчерашний джуниор, но поднатаскался в модных докерах и нейросетях. Зарплата 2000. Если уходить, то тоже подрастет чек, но тоже пока лень. Это не Москва, провинция.
Докер к программированию отношение вряд-ли имеет, если он его не разрабатывает. Ну а то, что питонист вклинился в хайповую область, где юзают готовые либы и вся подкапотная работа спокойно списывается на магию, так это уже вопрос рынка. С таким же успехом мы можем и девопсов подтянуть, что скриптики на питоне пишут и получают и того больше, только вот они не программисты. На нормальную зарплату от 4-5к по профилю программиста попасть зная только питончик и не понимая как он работает (ты же не видел С который у него под капотом) я не вижу перспектив.
Питонист это оператор, а Сишник — инженер. Задачи разные, разные и способы их решения.
Водитель тоже оператор, но разве кто-нибудь даст фуру дальнобойщику который даже простую поломку починить не может и не в курсе как у него что под капотом работает?

Вообще так оно и есть. Пилоты самолётов, к примеру, их не чинят. И лучше бы и не чинили.

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

А какое фундаментальное ограничение мешает "программисту на одном фреймворке и языке" починить что-то в этом самом фреймворке или в стандартной библиотеке своего языка?

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

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

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

НЛО прилетело и опубликовало эту надпись здесь

Возможно, оно вам и не нужно, решать ваши задачи на питоне.

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

Конечно, когда идёт сложная бизнес-логика, с исключениями, ветвлениями и т.д., тут наш внутренний QA становится раком, пока мы все пути не проверим вручную. И это дико долго + дико тяжело по сравнению с Хаскелем/Ocaml.

Но в тех же Notebook статически типизированные языки, кмк, подходят плохо — нам ведь даже не нужно, чтобы вся программа (все клетки) была компилируема!
Но в тех же Notebook статически типизированные языки, кмк, подходят плохо — нам ведь даже не нужно, чтобы вся программа (все клетки) была компилируема!

Компиляция не обязательна для статической типизации (хотя вторая и сильно помогает первой) — вспомним классический Бейсик с его A$ A! A%…
Но с современными средствами можно и интерпретировать код, который в финальной версии будет компилироваться, и при этом проверять на ходу на сотни проблем. Было бы желание...

НЛО прилетело и опубликовало эту надпись здесь
а иначе я начинаю чувствовать себя очень неудобно.


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

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

То есть, все эти рейтинги «безопасности языков» скорее показывают планку внутреннего QA у сообщества, сформированного вокруг конкретного языка.
-fdefer-type-errors :]


Я, если честно, не уверен, что даже в таком виде формат Notebook будет хорошо сочетаться с Хаскелем. С другой стороны, туда просится функциональщина (Wolfram language) и иммутабельность (чтобы делать undo-redo, но её никто не реализовал, кмк).

То есть, нужен язык вроде Хаскеля, но не совсем. Классы типов, естественно, нужны — это мука писать вычислительный код на Ocaml (сплошные float_of_int и *.)
НЛО прилетело и опубликовало эту надпись здесь
синтаксису, напоминающему английский язык
А не Smalltalk ли?
НЛО прилетело и опубликовало эту надпись здесь
Удивлённо: Вы разве не открываете вечером избранные прошивки микроконтроллеров и не любуетесь этим чудесно написанным кодом, отдахая душой от рабочих ужасов?
НЛО прилетело и опубликовало эту надпись здесь
Не начинайте учиться кодингу на языке, провоцирующем написание говнокода, построенного на побочных эффектах и UB (почему-то дающего правильный результат в компиляторе, который использует обучающийся, и потому обучающимся незамеченного).

Качественный код — это, прежде всего, самодисциплина кодера. И языки C, C++, JavaScript, Python, PHP и т.п. не в состоянии привить эту дисциплину.

Хотите учиться — на начальном этапе берите язык, удобный именно для обучения: маленький, ортогональный (не имеющий множества способов сделать одно и тоже), не позволяющий никакого своеволия, не имеющий кучи правил по умолчанию, особых случаев, исключений из правил, максимально жёсткий к допущенным кодером ошибкам и неточностям. В порядке уменьшения предпочтительности: Oberon-07 (другие языки линейки Oberon тоже прекрасно подходят, но они немного больше и сложнее), Modula-2, классический виртовский Pascal.

N.B. Язык C вполне маленький, но по остальным критериям для обучения категорически не подходит.

Если же учится сразу на модном промышленном языке, то, ИМХО, единственный современный вариант — Go: язык, основанный на C, но вычищенный от всех артефактов конца 60-х годов, не позволяющих писать на C чистый и надёжный код. Эти механизмы языка C имели смысл в 70-е годы (позволяя писать быстрый и компактный код ценой полного отсутствия какого-либо контроля со стороны компилятора), но 2021 году они выглядят совершеннейшим анахронизмом.

N.B. Go — практически единственный маленький современный популярный язык с очень сильной статической типизацией. Большинство модных языков — монстры, разбухшие от совершенно ненужных рюшечек, позволяющих написать код на несколько символов короче.

P.S. Раз статья про обучение кодингу, то и комментарий об этом. Если же говорить не про кодинг, а про программирование, то начинать надо не с языка, а с качественно учебника программирования — который будет учить не приёмам написания кода в конкретном языке, а базовым свойствам алгоритмов (начиная с O алгоритма и того, как именно это О связано с реальным быстродействием) и умению выбирать для данной задачи оптимальный алгоритм её решения.
начинать надо не с языка, а с качественно учебника программирования

У вас есть примеры таких учебников? Которые, в отличие от книг Кнута, сможет прочитать и понять средний человек.
Вирт, «Алгоритмы и структуры данных» (есть 3 с половиной редакции учебника, лучше последнюю).
Кормен, «Алгоримы. Вводный курс».

Ну, "Структура и интерпретация компьютерных программ" попроще будет. Есть ещё HtDP, она говорят ещё проще.

«Структура и интерпретация компьютерных программ» проще Вирта? Насмешили, однако. Может быть, вы Вирта с Кнутом перепутали?

Конечно же проще Кнута, Вирта я, увы, не читал. Думаете, стоит прочитать?

«Алгоритмы и структуры данных» — учебник для начинающих. На мой взгляд, все книги Вирта заслуживают внимания. Но, «на вкус и цвет»…
НЛО прилетело и опубликовало эту надпись здесь
Большая часть современного кода пишется на императивных и декларативных (SQL) языках. Да и воспринимать алгоритм новичку проще именно как последовательность действий, а не как взаимодействие частично рекурсивных функций.

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

Но совершенно необязательно изучать именно ML-языки: классический учебник «Структура и интерпретация компьютерных программ» использует Scheme.
НЛО прилетело и опубликовало эту надпись здесь
В Ocaml код выглядит как императивный:

let () =
   let x = 8 in
   let x = x * x + 2 in
   let y = x + 9 in
   let y = 2*y + x in
   Printf.printf "Hello ";
   Printf.printf "world!\n";
   Printf.printf "I got %d\n" y
N.B. Язык C вполне маленький,

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

Иногда таки надо показать машине, кто тут хозяин, и использовать магию манипуляций с памятью за пределами стандарта. Не каждый же день что-то в серьёзный продакшн пишешь, который должен работать помимо твоей машины. И как раз именно Си позволяет быть владельцем железа, не снисходя до уровня ассемблерных инструкций в памяти ядра.
Я ведь двумя абзацами раньше специально написал: «на начальном этапе». И всё, что я говорю, относится к C, как языку начального обучения. Язык C — прекрасный инструмент для профессионала, прекрасно понимающего границы применимости «магии», но пулемёт для стрельбы по собственным ногам для новичка. Это как человека, не умеющего водить, посадить за руль болида Формулы-1.

Проблема «магии» C в том, что она используется повсеместно — даже там, где низкоуровневая работа с памятью и близко не требуется. Хотя, по факту, эта «магия» реально нужна — относительно всего объёма современного софта — крайне редко: подавляющее большинство современного кода — прикладной софт, не требующий манипулирования с памятью и железом на низком уровне.

Современные языки тоже умеют на низком уровне, но только явно используя unsafe или аналогичные механизмы. Программист прямым текстом указывает в коде, что здесь и сейчас будет использовать неконтролируемые компилятором низкоуровневые механизмы. По сравнению с С такой подход на порядки уменьшает и локализует ненадёжный код.
Да, вот этот unsafe — это чудесная штука! Но, к сожалению, C — это lingua franca, Rust уже слишком сложен, а остальные замены С малоизвестны.
А за счёт чего сейчас в коде не требуется низкоуровневая работа? Не потому ли, что как раз вот это всё взаимодействие с железом на Си написали? На формулах-1 кстати любой человек научится водить крайне быстро. При учете, что запас этих машин формулы-1 у нас бесконечный, а время ограничено.
НЛО прилетело и опубликовало эту надпись здесь
А пробегала замечательная статья «What every compiler writer should know about programmers». Если программа рассчитана на конкретную систему с конкретным компилятором, то значительная часть UB становится вполне defined.

Например, на AIX/POWER обращение по адресу NULL даёт страницу, заполненную нулями. Соответственно, вы можете написать совершенно легальный код

struct Node {
    Node * left;
    Node * right;
};

Node * find_10_left( Node * start) {
    Node * 10_left = start;
    for( int i = 0; i < 10; i++) {
       10_left = 10_left -> left;
    }

    return 10_left;
}


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


Сейчас, в нашей области, это категорически не нужно. Но оно само так получается.

Вы путаете нулевой адрес и нулевой указатель. А ещё вы путаете unspecified behavior и undefined behavior. Второй ни при каких условиях не становится defined.


К примеру, если вы делаете вот так:


Node *left = node->left;
if (!node) {
    printf("Node is null!\n");
}

То компилятор имеет полное право выкинуть весь условный оператор при оптимизации. Даже на AIX/POWER.

Когда сразу известно, на каком железе работает код, когда половина этого кода вообще на плисках висит, которые чуть ли не интегрированы в материнку, когда как раз будут искать через 20 лет конкретную плату на S2011 соккете за бешеные деньги, потому что на других оно скорее всего будет работать не так, прямо как сейчас мейнфреймы поддерживают. Когда миллисекундная задержка в работе системы скорее всего скажет «всё, весь станок списываем в утиль». И ещё целая куча примеров, кроме юзверского софта, который неуклюж как кит на хоккейном поле, зато безопасен, да.
НЛО прилетело и опубликовало эту надпись здесь
С тех пор рассказы про станки и миллисекунды на меня производят чуть меньшее впечатление.

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

А что скажет косячный хак, когда в процессе демонстрации своего превосходства машине вы таки ошиблись?

А что скажет любой другое более защищённый от действий пользователя язык, когда машине уйдёт не та команда на исполнительные механизмы? Ровно тоже самое. Вердикт — ошибайтесь пореже. Тестируйте каждую команду на кошках либо на полуживых девайсах с предыдущих испытаний.
НЛО прилетело и опубликовало эту надпись здесь
Которое тоже вполне себе конвертируется в деньги.

Если б вы там на тыщу-другую долларов торговали — да, это ерунда. Но там циферки чуть больше :)


Если оборудование не серийное, то не конвертируется, как и люди которые умеют с ним работать. А деньги всегда одинаковы, всего лишь абстракции для удобства оценки, это не реальные объекты, которые сложно заменить новыми.

если перед SEC не получится доказать, что это просто хак умный

Если дело доходит до общения с SEC значит вы таки сделали что-то крутое и хорошо работающее, иначе бы они не заинтересовались. «Я просто тестировал фондовые рынки на устойчивость к каскадному обрушению»))

А если я статически докажу, что туда уходят только те команды, которые нужны?

А это не понял: кому, зачем? Если железка выполнила задачу — значит команды были правильные (даже если там были ошибки, которые не разрушили её и не прервали выполнение задачи), если нет — не так уж важно, команды были не те, код баганул, или просто ЭМИ наводка попала не на тот провод.
НЛО прилетело и опубликовало эту надпись здесь
Открою небольшую тайну: Все люди разные.
У всех разные предпочтения, и способы достижения результата.

Как убить желание изучать программирование в корне?
Начать с языков, на которых в принципе очень сложно что то сделать новичку.
Можно 2 года убить на изучение си, булевой алгебры, регистров процессора, типизации и алгоритмов сортировки, и не написать НИ ОДНОЙ своей программы. (вывести строку и отсортировать список за таковые не считаем, прикладная польза от такого стремиться к нулю)

Или написать на питончике СВОЕГО бота для телеги за 1 месяц.
Разница и подход очевидна. Возможно, найдутся те, кому ппц как зайдёт изучать алгоритм быстрой сортировки, и обмазываться изобретением велосипедов на си.
Но далеко не всем.
На Си пишешь хелло ворд, сортируешь битмап, подключаешь OpenGL выводишь 2D графику, считаешь фракталы, визуализируешь фотографию в 3д спектре, а там и до фотограмметрии с орбитальных спутников недалеко (если датасеты добудешь, благо сейчас с ними уже несложно) и это всё за пару недель реально с нуля по манулам освоить при нормально подготовленном курсе. Потом уже появится понимание происходящего и освоится базовый функционал языка. А на питоне получится всё тоже самое, только потом понимания происходящего уже не появится — механика шестерёнок там закрыта, если прям специально не ковырять.
и это всё за пару недель реально с нуля по манулам освоить при нормально подготовленном курсе.

Хочу увидеть пример такого курса. А то пока что мысли только в сторону такого.

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

Нууу, "херак-херак и в продакшен" еще никто не отменял. А Вы тут про учебники, О и другие сложности :)

" маленький, ортогональный (не имеющий множества способов сделать одно и тоже), не позволяющий никакого своеволия, не имеющий кучи правил по умолчанию, особых случаев, исключений из правил, максимально жёсткий к допущенным кодером ошибкам и неточностям " - отличная формулировка ! С Вашего позволения "украду" :)

Python — язык программирования по умолчанию для «самой сексуальной профессии 21-го века». Да, громкие слова о данных по-прежнему сохраняют за data science репутацию «сексуальной работы», хотя современные обстоятельства уже не полностью поддерживают это утверждение.

Какой тонкий эвфемизм для обозначения куколдинга и бетабаксинга. Особенно для разведенок с 3 детьми такие разработчики «самые сексуальные».

Для обучения программированию лучше всего подходит Go, Си слишком специфичен.

А почему именно C, а не C#, Java или Rust, например? Почему не cpp?

Думаю, что поэтому:

За свою жизнь я поработал более чем с пятью языками программирования, первым был C

Поддержу C# и Java, но не поддержу Rust — он еще более сложен с точки зрения и знаний про устройство программирования и сложности организации абстракций.
cpp ощутимых преимуществ не имеет.
Речь про начало обучения — когда нужно понять прежде всего структурное программирование и базовые элементы — flow и структуры данных.

Rust видится крутым после c и cpp
C: близко к железу, но чтобы научиться не стрелять себе в ногу потребуются годы
Rust: сразу покажет, где, что и как, после него даже на C (какое-то время) будешь писать, аки святой Кармак.

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

А по теме статьи — я, всё-таки, за питон, так как он, что называется, «подсаживает». А именно: создаёт в мозгу зависимость код -> успешный результат -> дофамин. И это главная задача языка для обучения. На других языках это будет пытка -> код -> фрустрация -> ещё фрустрация -> отказ от этого занятия в пользу чего полегче.
Мы же не даём детям сразу раствор и арматуру для постройки игрушечных домиков, нет, сперва даём деревянные кубики или лего, так им проще втянуться.
Потому что чистый Си ближе всего к машинной душе.
НЛО прилетело и опубликовало эту надпись здесь
Это для занятий по микропроцессорной технике.

Там лучше в кодах писать, самостоятельно адресуя память

Адресация памяти в кодах и адресация памяти в мнемониках отличается лишь наглядностью.

Кроме того, довольно многие пакеты Python, допустим, NumPy, написаны на C и его младшем брате C++ для устранения недостатков эффективности, потому что по сравнению с ними Python ужасно медленный.

«Младшем брате» :)

Ну "родился" позже — значит младший, всё правильно. (:

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

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

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

  • описывают методику обучения или просто хотя бы приводят план изучения языка,

  • приводят список методических материалов (потому что язык может быть классным, но если о нём написано полторы книги, рассчитанные на профессионалов, то учить его будет трудно),

  • не учитывают зависимость результата о того, учится человек сам или его учит кто-то знающий.

Вот буквально какую статью ни возьми, там «учите язык X, так как там есть Y».

А всё потому что это демагогия, которая формализована ещё во времена древнегреческих старцев. :D

Вы про постановку целей перед тем, как начать что-то делать?

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

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

Они ж вроде давно определены и существенно не меняются?


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

В 99.9% случаев это знание математики на уровне 6 действий арифметики+алгебры (вплоть до квадратного корня) и умение работать с компьютером на уровне запускать программу, набирать на клавиатуре и тыкать мышкой куда надо.
Если этой базы нет, её надо организовать заранее. Если есть уже какой-то выученный навык программирования, надо его дорабатывать, а не учить с нуля.


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

Первое реально существенное в этом списке, что стоит обсуждать.
Но реально все более-менее идут по примерно одинаковой методике, в которой:
1) "Не боги горшки обжигают" на примере условного helloworldʼа и создания какой-то минимальной программы с прохождением квеста по написанию, компиляции/линковке (где нужно) и запуску.
2) Базовые понятия программирования (пусть и неявно): система команд исполнителя (неважно, сложение двух чисел или отдача черепашке команды пройти вперёд); пред- и постусловия каждого действия, зависимости между действиями и оформление их в виде отношения раньше-позже для процедурных языков и зависимости по результату в функциональных; условные выполнения (if) и циклы (while/for/etc., если не рекурсия).
3) Значения, переменные (тут очень важно помочь не путаться в обозначениях — и для процедурных надо понять что такое x=x+1, а для функциональных — почему в вызывающем gcd(b, b-a), а в вызываемом gcd(a, b), и как это совмещается).
4) Формальное понятие алгоритма и его отображение на реальный мир.
5) Типы данных сложнее одиночного значения (массивы, структуры) и практика работы с ними (у кое-кого из моих подопечных, например, основные затраты ушли на формирование привычки типа "надо перебирать значения — начинаем думать как писать цикл" и выбора, какой цикл по каким итераторам).
6) Усиление типов данных на современные структуры типа хэш-мап.
7) Практика, практика и практика...


Улучшение методики может быть agile-методами, например, написанием всё более хитрого кода в игровой среде, но это уже очень индивидуально.


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

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


не учитывают зависимость результата о того, учится человек сам или его учит кто-то знающий.

Обычно таки книги дают такого "знающего" в виде автора книги, а дальше есть какая-то обратная связь в комьюнити или с выбранным ментором.
Для части примеров тут — организованные курсы.


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


Из того, что вы не назвали, стоит вспомнить создание интересных задач для учащихся — вот это сейчас наиболее сложная и требующая индивидуального подхода часть. Обычно даже опытные преподаватели дают 10-20 типовых задач на выбор. Но это по любому не формализуемо.

Они ж вроде давно определены и существенно не меняются?

Да, и какие они?

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

Цели очень разные могут быть.

В 99.9% случаев

Откуда статистика? Да и как я уже сказал, мы не уточнили даже, о ком именно идёт речь.

Первое реально существенное в этом списке, что стоит обсуждать.

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

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

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

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

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

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

И много вы видели книг, скажем, по спортивному программированию на JavaScript? Видите, как важно формулировать условия и цели? :)

Разработчики на C известны тем, что кропотливо создают упорядоченный, чистый код

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

есть альтернативное мнение — что ассемблер намного проще, потому что в нем нет лишних абстракций и UB…
Чистый код.
У ассемблера основная проблема — это взаимодействие с внешним миром. Вот берешь ты Си — у тебя и математическая библиотека, и работа с файлами, и более-менее человечный input/output… В ассемблере — это все платформо-зависимо. И каких-то готовых шаблонов нет

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

Боюсь повторить банальности, но C и Python — два крайних и потому неудобных варианта, но в противоположных направлениях.
Если вообще рассматривать процедурные языки (начинать ли с функциональных — отдельная тема, в которую не хочу влезать), то требуется 1) автоматическое управление памятью, 2) сильная статическая типизация почти везде, но с возможностью легко уйти от неё в особых случаях, 3) минимизация всяких undefined behavior в пользу умолчательной явной защиты от ошибок. Для меня это приводит к Java, C#, Swift...

Жаль, Delphi скорее мертв чем жив.

Вот уж что, а Delphi мне не жаль. Костыльность Паскаля я описывал много раз (типа такого), а Delphi недалеко от него ушёл. По состоянию на сейчас C# его перекрывает по всем параметрам, кроме зависимости от рантайма.

Вот читал я где-то, что наши сумрачные гении соорудили гибрид C# и Pascal ABC, вроде добротно выглядит, всем выгодно: ученики потом на шарп перелезут, а современные фичи сдобрены знакомым учителям синтаксисом.

ссылочка
Вся статья — это одна сплошная вода.
-Может все-таки Basic?
-Доктор сказал Python, значит Python!

Если под программированием понимаются структуры данных и алгоритмы, а не "байтоёбство", то Питон лучше для начинающих, чем С. По-моему опыту С/С++ сильно тормозят обучение т.к. вместо освоения темы студенты на каждом шагу спотыкаются об UB и тратят много времени на исследование "почему ничего не работает, хотя вроде всё написано верно". Если Питон слишком большой комбайн для неокрепшего ума, а хочется чего-то более простого и более низкоуровневого, но при этом без UB, то тут бы хорошо помог Go.

Я бы брал Scheme и SICP. Можно взять какой-нибудь современный диалект — типа Clojure.

Впрочем, это если прям качественно и долго учить. Если надо ПТУ-шный уровень — сойдет и Питон. Я бы только лучше JavaScript брал — он проще, системнее, и шире применим на практике.
Жду с нетерпением статью о том, что не нужно начинать с Си, а нужно начать с ассемблера и машинного кода (желательно для ЦПУ графических плат — доступно и весело для любого школьника). Автор, напишите, пожалуйста. Спасибо.
Если хотите отбить желание программировать — начинайте с СИ!

Я рекомендую учить C и Python одновременно, тогда не будет фразы «не могу это сделать, стандартная библиотека не работает»

Семилетний ребенок выучил Python и уже ищет работу. А чего добился ты со своим Си?

Такая реклама Питона весьмааааа специфична :)

Как по мне самому плохому чему учат Python/JS в любой не понятной ситуации делать pip install / npm install

никогда такого не встречал, но даже если и так, то нужно вставать и уходить от таких «преподов»

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

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


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

" Если финансовому директору нужно...", то ему пофиг на чем это будет написано. Вот что знаешь - то и пользуй :)

А вот когда встает вопрос эффективности/скорости/надежности/..., то нормальный финдир умолкает и просит совета у IT-директора. Но это нормальный :(

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

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

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

На питон наезжают исключительно из-за низкого порога вхождения.

Сейчас еще такое отношение к php, хотя хорошие специалисты на PHP — грамотные и востребованные люди.

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

"На питон наезжают исключительно из-за низкого порога вхождения." - нет. Иногда нужна производительность. И раскрученность Питона тут частенько не к месту :(

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

Самая популярная реализация Python написана на C. Поэтому определённые знания C точно пригодятся при расшифровке кода на Python.
Логика просто ошеломительная. При чём тут вообще на каком языке написан интерпретатор? Первый Бейсик, как и все старые языки, был написан на ассемблере, например. По идее, любой язык можно написать на любом другом языке. Но это никак не поможет понять второй через первый.

Кроме того, довольно многие пакеты Python, допустим, NumPy, написаны на C и его младшем брате C++ для устранения недостатков эффективности, потому что по сравнению с ними Python ужасно медленный.
Некоторые пакеты Питона, например SciPy, вообще написаны во многом на Фортране. Даже NumPy использует некоторые фортрановские библиотеки. Думаю, автор онемел бы если знал этот факт. Ведь подумать только, где Фортран и где Питон!
Кстати, фортран 2018 очень хорош, и учить его вполне может иметь смысл :)
(не первым языком)
Так он ещё не стандарт и компиляторов, насколько понимаю, ещё нет. А так да, уже Fortran 2008 вполне нормальный язык. Кстати, в SciPy используется Fortran 77. Да, стандарт почти 45-летней давности. Даже раньше, чем появился C78, первый стандарт C.
Не знаю про gfortran (вряд ли), но интеловский компилятор точно 2018 умеет.

GNU Fortran гарантированно поддерживает только стандарт 95 ( и обратно совместим с 77), и только некоторые фичи 2003, 2008, 2018.

Лично мы его юзаем только из-за поддержки легаси кода. Я то в ВУЗе его учил, а молодежь даже не слышала о таком языке. У нас кстати код ориентируется на 77 стандарт, т. к. основная часть написана ещё в 90-е. Мы с радостью перешли бы на Python, но переписывать кучу кода просто так никто не будет.

Переходить на питон в задачах, предназначенных для фортрана — это замечательная идея!
… а когда-то советовали не начинать изучать с Бейсика :)

Как начинавший изучение еще с Алгола — то, что написано о Python, как его плюсы —
Благодаря синтаксису, напоминающему английский язык, парадигме отступов и огромному количеству библиотек другие языки по сравнению с Python начинают выглядеть бесполезными.
В нём нет объявления переменных, используется автоматическое приведение типов.


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

А уж синтаксис, построенный на отступах — за это нужно давать отдельную медаль «никогда так не делай»…

Насчёт отступов — почему? На самом деле в наш век интеллектуальных сред это как раз один из минимальных минусов. Потому что отрефакторить кусок кода можно практически в один клик. Несомненно, что при массовых изменениях кода, идея с табуляцией создаёт повышенный риск ошибок, но код реально намного читабельнее, чем эти вот begin...end и {....} (которые ещё надо ловить глазами и все равно приходится код линтовать, чтобы он выглядел однообразно)

Насчёт отступов — почему?

Проблемы следующие:
1) Поиск противоположной точки блока (конец — для начала, и наоборот). Для {} он тривиален и работает везде начиная с базового vim. Для стиля Python возникает усложнение: например vim-indentwise надо ставить явно; в PyCharm тебе выводит по каждому Ctrl+[ на один уровень назад, потому что оно не может определить, какой из нескольких закончившихся тут уровней тебе нужен.
2) Вставка кода: для явных скобок вставил в любое место с предыдущим отступом и затем переформатировал дежурным форматтером. Для отступов надо или следить самому, доработав отступы, или чтобы IDE умело выравнивать сразу весь вставляемый кусок.
3) Сколь ни старайся передавать через среды, которые сохраняют пробелы в начале строк, обязательно найдётся что-то такое, что их ломает к лешим. Особенно это любят всякие форумы.


На самом деле в наш век интеллектуальных сред это как раз один из минимальных минусов.

Среды — не везде. Можно, конечно, говорить, что всё через деплой и контейнеры, но в реальности работа в удалённом vim вполне типична. Ну и не всем все среды годятся. Таки сохранить файл и напустить на него форматтер — сильно универсальнее. А где-то и vim поставить нельзя.


(которые ещё надо ловить глазами и все равно приходится код линтовать, чтобы он выглядел однообразно)

Ловить {} глазами IMO (и я думаю, большинству) проще, чем следить за отступами.
Линтовать надо всё — в Питоне тоже 100500 поводов, начиная с того, что где-то сделают отступ в 2 пробела, а где-то в 7 — я такое видел не раз.

Для {} он тривиален и работает везде начиная с базового vim

вообще-то нет. Потому что Вы вынуждены обрабатывать все токены. Ну, смотрите, например:


{ printf("blablabla"); print("}}}") }


наивный парсер, очевидно, неверно прокушает средние "}". И это мы еще не перешли к препроцессору Си, при помощи которого можно любой синтаксический анализатор запутать. Но это, конечно, ортогональная проблема :-)


в PyCharm тебе выводит по каждому Ctrl+[ на один уровень назад, потому что оно не может определить, какой из нескольких закончившихся тут уровней тебе нужен.

???? Можно конкретный пример, я как-то, наверное, невнимательно смотрел и на это особо не напарывался.


2) Вставка кода: для явных скобок вставил в любое место с предыдущим отступом и затем переформатировал дежурным форматтером. Для отступов надо или следить самому, доработав отступы, или чтобы IDE умело выравнивать сразу весь вставляемый кусок.

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


3) Сколь ни старайся передавать через среды, которые сохраняют пробелы в начале строк, обязательно найдётся что-то такое, что их ломает к лешим. Особенно это любят всякие форумы.

Это не очень аргумент. Потому что текст со скобочками можно обвинить в том, что в нем есть зависимость от строки. И CR+LF или просто CR его ломают ))) А проблемы возникают при переходе между Вин и Маком )))


Среды — не везде. Можно, конечно, говорить, что всё через деплой и контейнеры, но в реальности работа в удалённом vim вполне типична. Ну и не всем все среды годятся. Таки сохранить файл и напустить на него форматтер — сильно универсальнее. А где-то и vim поставить нельзя.

является ли это проблемой? Ну, во-первых, можно работать с удаленными файлами через локальную ИДЕ. Да что уж там — есть варианты запуска на удаленной машине графической IDE с пробросом графики на локальную машину. Во-вторых, не хотел бы я в vim заниматься правками кода в промышленных масштабах. Но, возможно, я его дао не познал — да


Ловить {} глазами IMO (и я думаю, большинству) проще, чем следить за отступами.

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


Линтовать надо всё — в Питоне тоже 100500 поводов, начиная с того, что где-то сделают отступ в 2 пробела, а где-то в 7 — я такое видел не раз.

да

Можно конкретный пример, я как-то, наверное, невнимательно смотрел и на это особо не напарывался.

Ну вот рассмотрим случайный пример с вложенными блоками:


def index(list, item):
    for i in range(len(list)):
        if list[i] == item:
            return i

Какой именно блок завершился на последней строчке — условный оператор, оператор цикла или объявление функции — и куда должна перейти IDE когда её попросили перейти к началу блока?

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


(я намеренно сделал бессмысленный код)


def blablabla(list, item):
  for i in range(len(list)):
    if list[i] == item:
      if i ==0:
        print("i==0")
        return i
      else
        return i
    else 
      return i+1
    do_something_else()

Т.е. повторю тезис, который я озвучил в соседнем треде про YAML/Json — вся эта история с отступами, как мне кажется, хороша для визуализации кода. Код действительно выглядит наглядно и чисто. Лаконично. Потому что нет лишних элементов. А вот удобство редактирования — да, в каком-то смысле хромает. И если бы существовал однозначный ответ как лучше (отдельный управляющие конструкции и {} или отступы) — мы бы тут не спорили ))))

И это мы еще не перешли к препроцессору Си, при помощи которого можно любой синтаксический анализатор запутать. Но это, конечно, ортогональная проблема :-)

Ну обычно IDE таки рассчитаны на варианты без #define FOO {
:))
С таким даже реформаттеры не справляются.
Поэтому я такие чудеса обычно в расчёт не беру.
(Были спец. случаи вроде _TRY в MFC поддержке, с ними сложнее, да.)


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


Это не очень аргумент. Потому что текст со скобочками можно обвинить в том, что в нем есть зависимость от строки. И CR+LF или просто CR его ломают )))

Этого не понял. Прошу объяснить подробнее.


является ли это проблемой? Ну, во-первых, можно работать с удаленными файлами через локальную ИДЕ. Да что уж там — есть варианты запуска на удаленной машине графической IDE с пробросом графики на локальную машину. Во-вторых, не хотел бы я в vim заниматься правками кода в промышленных масштабах. Но, возможно, я его дао не познал — да

Я не то чтобы дао, но привык, что он реально самый удобный из консольных.
Остальное — да, вес фактора заметно мал, но не 0.
Ремотно на рабочую виртуалку я и так почти каждый день через CLion хожу :)


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

Именно что заслуга — легко искаемые скобки (как и другие виды скобок, например if — then — else — end в модулоидах, Ruby и т.п.)


У {} в большинстве старых языков нет обязательности, это хуже. Сейчас это лечат.

до-до-до, особенно когда "в наш век интеллектуальных сред" перебросил колеге код в каком нибудь Тимсе :) (Тимс имеет свойство как-то специфически форматировать)

Мляааа, "begin...end и {....} (которые ещё надо ловить глазами и все равно приходится код линтовать, чтобы он выглядел однообразно)", а как же "в наш век интеллектуальных сред" ? Еще допотопный MultiEdit умел подсвечивать блок.

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

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

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

Спору нет. Правда когда нужна производительность приходится болезненно переучиваться. Или уходить и оставаться в "теплой ванне Питона".

Извечный спор о том, что же было первым: курица или яйцо? Пока у обучающегося не будет четкого понимания алгоритмов, в языки программирования лезть не следует. Хоть это будет ассемблер, хоть Си, хоть Джава, хоть Пайтон. Часто на "курсах" фактом разжевывают алгоритмы с применением того или иного языка программирования. От этого и беды, с последующей ломкой копьев о правильном языке программирования для обучения программированию. Представляете, как бы мы жили, если бы хирургов учили профессии опираясь исключительно на то, что скальпель должен быть не из вон той стали, а только из этой, и вот дескать если найти именно ту марку стали, то и резать станет ловчее, и процент смертей снизится.

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

Различия разных ЯП тут скорее сродни различию
1) скальпеля
2) станка с ЧПУ (разрежет любого, точно, как надо, но надо чтобы программа точно знала позиции всех тканей до 50 мкм и они не двигались в процессе)
3) что-то вроде многорядной бороны, но уменьшенной до пары сантиметров
4) электрического сверла
5) сварочного аппарата, который пришивает "молнии" из цианакрилата (первую неделю можно расстёгивать для контроля)


:))))


и да, они все совершенно разное дают и даже алгоритмы разные (на C пишите хэш-мапу сами, на Python она в поставке).

помню когда у меня только появился интернет меня потянуло програмки писать, загуглил «самый популярный язык программирования», выдало С, сел изучать, дальше hello world уйти не смог и ушел искать что полегче. В итоге нашел ассемблер, мне он тогда показался чем то более легким и дело таки пошло. А главное что потом, когда уже осознанно пришел к С операции с указателями и прочее не вызывали особых проблем с пониманием
НЛО прилетело и опубликовало эту надпись здесь

Скажите кто-нибудь "переводчику", что "сексуальная работа" — это не то что он думает.
И скажите кто-нибудь отделу маркетинга вдсины, что качество обратно пропорционально количеству. Особенно при предоставлении услуг VDS

Мой научный руководитель однажды сказал мне: «Всегда начинай с самого сильного. Первый удар определяет судьбу боя».


А в детском саду или в начальной школе «научный сотрудник» тоже посоветует с Си начинать? А почему не с ассемблера? Или не с машинных кодов? Не с архитектуры микропроцессоров? Ведь и Си понять сложно без понимания этих основ. Здесь всё упирается в то, что мы подразумеваем под «начинающим» и какие цели преследуются. Для начального изучения информатики/алгоритмов любой язык подойдет, даже псевдокод. Лучше попроще, а это и есть питон — он на псевдокод и похож.

Увы, одного идеального языка для обучения программированию нет. Потому что программирование само по себе состоит из множества дисциплин, каждая из которых в итоге играет роль в написании кода. Алгоритмы и структуры данных удобно изучать в С и С++. Низкоуровневое программирования и понимание подкапота хорошо идет с ассемблером. Современный ООП приятно изучать в C#. Для изучения разнообразных парадигм и типичных языковых фич нужны языки где они собственное есть. С азами программирования сложнее всего. С одной стороны есть академический Pascal, который не является перегруженным и при этом имеет базовый набор фич, с другой стороны синтаксис у него устаревший и неудобный. Остается Python или Lua какой-нибудь, хотя лучше бы какой-нибудь компилируемый язык с полноценной статической типизацией. Видимо нужен какой-нибудь новый академический язык, в котором упор на поддержку современных фич при минимальном объеме спецификации.

Боюсь повторить, что уже несколько раз писали выше, но ей Богу, ЯП - дело десятое (ёксель, при желании и настойчивости, можно и на сях, и на PHP распарсить). Не помню, в какой недавно статье на Хабре читал эту мысль, но программист и разработчик - это два разных мира, где, как правило, программист - это чисто кодинг, а вот разработка - это уже дзэн, где ЯП не играет особую роль.

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

Вот для решения любой бизнес задачи человек может знать все стандарты, всё тонкости конкретного ЯП и т.п., но вот если он не понимает алгоритма, не понимает как, что, когда сохранить в базу (а когда нет), когда не знает или не умеет пользоваться инструментами (да той же IDE) толком... Это просто беда. У меня за последние 20+ лет в разных командах, разных компаниях было много гениев в ЯП, но эти "гении" ну никак не помогали решению конкретной бизнес задачи, увы. А вот "середнячки", с точки зрения "гения", решали проблему в минимальные сроки и с минимальными затратами для бизнеса.

В общем, Кнут, Фаулер, Петцольд, Gang Of Four. ЯП - это уже религия (о которой в приличном обществе не спорят) ;)

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

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

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

На востоке есть мудрость - ищите не того кто лучше всех знает или умеет, но того кто лучше всех учит.