Pull to refresh

Comments 309

К сожалению, в голосовании отсутствует пункт: «Обучение программированию следует начинать с основ теории алгоритмов».
UFO just landed and posted this here
Вы о чем вообще? Какие абстрактные алгоритмы в вакууме? Знать что скрывается за std::sort() и как именно это работает, это задротство или нет?

Можетбыть, вы, конечно, собираетесь всю оставшуюся жизнь выводить в stdout банальное «Hello, world!», то претензий нет.

Если вам (или кому-то еще) сложно манипулировать в голове абстрациями типа стека или очереди, так может и вовсе не надо? Мне преподаватель в университете говорил, что много есть хороших профессий: танцоры, повара и т.д. Теория алгоритмов не подразуме
UFO just landed and posted this here
ИМХО Это проблема программы обучения, а не фундаментальной теории. Если изучать теорию без отрыва от практики, сами понимаете, всё будет нормально. Ну, а кроме того, кто мешал большинству людей сесть и самому написать на C всё то же самое руками сразу, не дожидаясь следующего семестра :)
Вернитесь в тот момент, когда вы еще не видели компьютера, возможно вам было тогда 7 лет. Вам надо начать изучать программирование. Теория алгоритмов как нельзя лучше для этого подходит. Вернитесь в то время когда вам 1 год, вам надо научиться ходить — теория анатомия как нельзя к месту.
Вы утрируете. Эдсгер всё-таки не про детей писал.
UFO just landed and posted this here
Согласен с вами. Некоторые, кстати, так и делают (касательно вашей последней фразы) :)
Хм.
1. Я не согласен с тем, что мне в 7 лет надо учиться программировать. Это высосано из пальца.
2. «Чем отличается студент, не умеющий кодить от ребёнка, не умеющего ходить?» — это, простите, софистика. К сожалению, у меня сегодня нет желания философстовать, сорри.
Заголовок: «обучение программированию нужно начинать с функционального языка»
Опрос: «Обучение программированию следует начинать с»

Ключевое слово НАЧИНАТЬ. Или нам придется вернуться ко временам наших праотцов, когда обучение начинали лет в 30-40? Если мы рассуждаем о реальности, то надо сразу ставить все по своим местам. В наше время начинать учиться программированию можно балуясь играми в пять лет. Теория алгоритмов в современном мире никак не может попасть на первое место в этой цепочке — это не возможно в принципе.

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

1. Вот вы так написали:

Заголовок: «обучение программированию нужно начинать с функционального языка»
Опрос: «Обучение программированию следует начинать с» Ключевое слово НАЧИНАТЬ.

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

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

Если это мой глюк, то тема исчерпана. Если нет, предложите реалистичный сценарий как начать целесообразное изучение программирования с теории (биоматериал, не связывающий свою жизнь с информатикой не рассматривается).
Я за гармонию :) Скажем так, за правильную подачу теории вкупе с практикой.
UFO just landed and posted this here
У вас какой-то озлобленный взгляд на всю ситуацию. Поясните, кто это «любому из категории «средняка»»? И вот это тоже «Остаётся кучка умников, которые всё в этой жизни знают, по себе меряют и всех за говно держат, которым только дорога в повара и танцоры :)»?
Я видел обратное когда учили языку. И в итоге люди не понимали даже для чего нужны функции, они знали как их описать. знали как вызвать но зачем они не понимали.
Бывали случаи и интересней когда студентов обязывали делать лабораторки по всяким способам сортировки которые по названию и в инете не на гуглишь с первого раза.
Так вот что первый, что второй случаи одинаково ужасны. Должен быть баланс, и вот найти походу до сих пор не смогли.
Нет такого человека, который бы искал, а если и есть, то до него никому нет дела:) Эффективность образования ни в каких единицах не измеряется, кроме набора на первый курс. Стыдно будет на показатели смотреть.
// комментарий с опозданием на год :)

Поддержу. Начинать стоит с создания собственных алгоритмов. Изучили язык, познакомились с массивами и прочим… Ставим задачу поиска. Как бы вы искали в массиве? А можно ли придумать более быстрый способ? А если данные отсортированы? И т.п.
Кстати, с математикой точно также, только там теоремы, а не алгоритмы.
Видимо, в Стэнфорде хуже вас знают, как надо преподавать алгоритмы.
Можно спокойно найти 20 авторитетов, мнения которых будут не совпадать. Кто-то из них точно ошибётся.
А весь Стэнфорд придерживается единого мнения? Вплоть до человека?
Да не надо, чтобы все придерживались одного мнения, достаточно, чтобы те, кто составляют программу, имели конкретное мнение.
Этого недостаточно: нужно, чтобы они имели ещё и правильное мнение.
Ну и, вообще говоря, странно выглядит наш спор: я, да и вы, подозреваю, тоже, не проводили каких-либо опытов, чтобы иметь возможность на их основе оценить, какой вариант лучше. Возможно, вы знаете два каких-либо университета, в которых именно это изучают по-разному, при прочих равных (т.к. сравнивать, например, Стэнфорд с вузом из российской глубинки — явно некорректно)? Я не знаю, так что возможностей сравнить у меня нет.
Но, тем не менее, своё мнение у меня сложилось на основе того, как знакомился с этим я. Ну а я научился создавать алгоритмы задолго до того, как познакомился с большинством классических. Я тогда не знал, что такое, например, бинарный поиск, зато спокойно мог создать и написать, скажем, алгоритм поиска подстроки в строке, алгоритм поиска в дереве, алгоритм создания бинарного дерева из массива (если бы мне объяснили, конечно, что такое бинарное дерево, что, впрочем, элементарно). Возможно, не самый быстрый и эффективный, зато свой и сходу.
Возможно, поэтому, когда я знакомился с классическими алгоритмами, каких-то больших трудностей не возникало. Именно поэтому я поддерживаю эту идею. Потому что нужно сначала выучить язык, а не сходу переводить на нём тексты.
Этого недостаточно: нужно, чтобы они имели ещё и правильное мнение.

Как определяется правильность?

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

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

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

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

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

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

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

Правильное мнение — то, которое принесёт наилучший результат. В данном случае.

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

Не отрицаю, что вы можете быть правы. Даже не пытаюсь вас убедить. Просто делюсь своим мнением.

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

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

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

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

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

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

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

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

Смысл элементарен: не под всё есть алгоритмы. Да вот элементарнейшая задача: массив линий, из которых состоит произвольный многоугольник, посчитать boundbox многоугольника. Насколько могу судить, это не похоже ни на разновидность поиска, ни сортировки. Возможно, среди алгоритмов компьютерной графики найдётся что-нибудь такое… Но чёрт, зачем? Зачем, если абсолютно очевидно, как это делается?

Очевидно человеку, умеющему разрабатывать алгоритмы. Очевидно, наверное, человеку, глубоко овладевшим классическими — стоит заметить, это элементарная задача для умеющего разрабатывать.
По большому счёту, вся разработка состоит из создания разной сложности и разного рода алгоритмов. А покажите мне алгоритм, например, побуквенного парсинга XML или JSON… А он относится к классическим?
А сможет ли такой алгоритм написать человек, умеющий создавать алгоритмы? А человек, знакомый с классическими алгоритмами?

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

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

Смысл элементарен: не под всё есть алгоритмы.

Я имел в виду именнно разработку своей версии уже существующего алгоритма.

Зачем, если абсолютно очевидно, как это делается?

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

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

Знаете в чём разница? Очень просто: я учился в матклассе, а вы, скорее всего — в обычном.

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

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

Очень просто: я учился в матклассе, а вы, скорее всего — в обычном.

Да, в обычном.

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

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

Вы серьезно считаете, что каждый студент способен придумать алгоритм Штрассена?
Почему студенты? Школьники, да. Мы же придумывали как-то! Причём я и сейчас легко смогу его «восстановить» если вы меня спросите не про алгоритм Штрассена, а про умножение матриц за O(Nlog27). Там нет ничего сложного. Ответ является очень сильной подсказкой сам по себе.

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

Математика постоянно упрощается, вводит новые термины, новый язык. Пользуясь которыми можно доказать всё то же, но только гораздо проще и быстрее. Теорема Пифагора в комплексных числах доказывается в 2 строчки, не говоря уже о том, что за всё время было придумано больше сотни (а то и двух, точно не помню) её доказательств. Так что же, школьник, догадавшийся до такого доказательства, умнее, *имя_исторического_математика*, который её не мог доказать в 2 строчки? Да нет, у математика просто не было комплексных чисел.
Это и есть те самые тропы, по которым нужно вести учеников.

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

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

Не все, конечно же, можно вывести самому. Но важно, чтобы выводилось буквально всё, что возможно. Зачем? Это гораздо более высокий уровень, это строит правильную модель размышления, которая будет использоваться дальше при аналогичных задачах. И размышлять самому, пусть и направляясь кем-то, гораздо, гораздо эффективнее, чем смотреть размышления другого.
Теорема Пифагора в комплексных числах доказывается в 2 строчки,

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

Не все, конечно же, можно вывести самому.

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

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

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

Внимание, вопрос: сколько на это уйдет времени?
Это неправильный вопрос. Примерно столько же, сколько и на обычное обучение математике, как ни странно.

Правильный вопрос: сколько на это уйдёт преподавателей (ну или, скорее, помощников преподавателей)… У нас в классе на ~20 человек их было 5-6 (студенты, понятно, но не в этом дело). К сожалению подобные вещи даже очень богатые школы могут вытворять только с «профильными» предметами.

Зачем нужно столько учителей? Для того, чтобы проверять выкладки, придумываемые учениками и указывать им на их ошибки. А иначе смысла нет — достаточно часто первое решение, которое придумывает ученик оказывается попросту неверным, а сам он этого не замечает. Если ему на его ошибки не указывать то ничего хорошего из этого метода обучения не выйдет.
Это неправильный вопрос. Примерно столько же, сколько и на обычное обучение математике, как ни странно. Правильный вопрос: сколько на это уйдёт преподавателей

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

У нас в классе на ~20 человек их было 5-6 (студенты, понятно, но не в этом дело). К сожалению подобные вещи даже очень богатые школы могут вытворять только с «профильными» предметами.

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

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

Так что с точки зрения затрат времени учеников этот метод не хуже обычного (но даёт, конечно, гораздо более глубокие знания: доказательство, которое ты один раз прочитал ты с лёгкостью неимоверной можешь и забыть — иногда буквально через неделю, а вот если ты его сам придумал — то и через 20 лет вспомнишь), а вот с точки зрения расхода времени учителей — это да… Всех таким способом математике обучать не получится… всё-таки за классы, о которых вы говорите, родители обычно платят дополнительно и не то, чтоб так уж очень мало…
У меня создается ощущение, что, все-таки, этот метод применим не к каждому ученику, а только к обладающим определенными способностями (это же, как уже неоднократно было сказано, не обычная школа). Что, вкупе с добротным расходом преподавательских ресурсов, вряд ли позволяет говорить о том, что аналогичная методика массового преподавания software engineering — правильная.
Почему нет? Если бы software engineer'ов нужно было бы столько же, сколько сантехников — то ваши доводы, может быть, и имели бы смысл. Но их ведь реально столько не нужно… имеется в виду людей, способных создавать реально сложные системы.

А для «кропателей формочек на PHP» этого действительно не нужно, тут вы правы. Это — вообще ремесло, которому за несколько месяцев на курсах можно обучить…
Не люблю я это пренебрежительное разделение на software engineer и кропателей формочек. В моей системе ценностей software engineering — вообще ремесло (в значении craftsmanship), вне зависимости от того, делаете вы микроформы или гигантские системы. Но образование (или опыт) для этого действительно нужны разные.
Не только образование. К сожалению это разделение — не моя прихоть, а объективная реальность. Как обычно эту банальность хорошо описывает Джоэл:
Многие программисты на Си просто не знают, как заставить работать указатели. Я, как правило, не отказываюсь от кандидата из-за отсутствия у него какого-то навыка. Однако я обнаружил, что понимание указателей в Си — это не навык, а способность. В начале первого курса на факультете кибернетики набирается человек 200 вундеркиндов, писавших в четырехлетнем возрасте игрушки для Atari 800 на BASIC'е. Они хорошо проводят время, изучая Паскаль, но в один прекрасный день профессор заводит речь об указателях, и они внезапно перестают понимать. То есть абсолютно. 90% потока переходит на отделение политологии, обьясняя это тем, что на кибернетике мало симпатичных студенток. На самом же деле, по неизвестной причине часть человечества просто рождается без того отдела мозга, который понимает указатели. Указатели — это не навык, а способность, требующая особого мышления, и некоторые люди им просто не обладают.
Есть довольно много вещей, которые бо́льшая часть часть населения этой планеты не в состоянии освоить (либо им для этого требуются какие-то просто сверхчеловеческие усилия): указатели, рекурсия, функциональный анализ, да и вообще работу с функциональными языками… это люди никогда не смогут строить большие системы. Формочки они при это могут клепать влёгкую.

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

Это, может быть, не так хорошо с точки зрения студента — но гораздо эффективнее с точки зрения ВУЗа и всего общества в целом.

P.S. Это ни в коем случае не ознаает что эти люди в чём-то неполноценны. Ну не считаем же мы неполноценнми людей без абсолютного слуха? Просто кому-то не повезло со слухом, кому-то — с распознованием цветов, а кто-то вот остался без понимания рекурсии. Просто последнее труднее заметить и протестировать…
Ну это очень старая запись и она примерно о том же.

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

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

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

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

Заодно, кстати, отсеем — правда, не в пользу экономического факультета, а в пользу CS — тех, кому нифига не даются указатели, зато всем мило лямбда-исчисление.

(Поясню, почему «абстрактные», а не «функциональные» языки: есть алгоритмы, которые в правильном своем виде не ложатся на функциональные языки. Их придется либо выносить из курса на позже — что нелео — либо писать нефункциональным образом.)
Вы не ошибаетесь. Вы ломитесь в открытую дверь. Вот было сказано:
Нужна тебе сортировка — возьми существующую.
Хороший совет. Есть только пара вопросов:
1. Какую из дюжин известных сотировок предлагается взять?
2. Почему разработчики, скажем, V8, потратили кучу времени на то, чтобы ответить на ворос #1? Они что — идиоты?

Хотя на самом деле, по традиции, вы правы оба, как я уже объяснял.

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

А Keyten — объясняет как выращивать инженеров, которых не страшно и к разработке сложных и ответственных систем допускать. Этим, собственно, и занимаются ВУЗы и как бы понятно что Дейкстра ровно об этом уровне и говорит!
Только lair описывает как за пару лет выпустить ремесленника, кодера — то, что в других специальностях получается через пару лет обучения в ПТУ. Клепать простые сайтики, подкручивать скрипты в бухгалтерии и прочее и прочее, прочее — вот их удел.

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

Языки программирования, дизайн, управление памятью, обработка ошибок, блаблабла. И problem solving.

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

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

И problem solving.
А это что вообще такое и как вы этому собрались учить людей, которые исходят из принципа нужна тебе сортировка — возьми существующую?

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

Поэтому, как я уже писал, эти дисциплины осмысленно запускать параллельно.
А смысл в этом какой? Прикладное программирование — это мода. Как-то освоить новые модные технологии можно за полгода, а «оттачивать мастерство» потом — всё равно придётся учиться всю жизнь. Так зачем им раньше времени мозги ломать?

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

Та же самая ситуация, что и с любой другой дисциплиной в любом другом ВУЗе: вначале идут фундаментальные знания, потом — их практическое применение. Почему вдруг программная инженерия должна отличаться?
Языки программирования — это вообще «наносное» (к моменту выпуска они могут измениться 10 раз),

Странно, я вот пишу на языке, который фундаментально за прошедшие 12 лет не изменился.

управление памятью — это, опять-таки, алгоритмы определённого вида

Не совсем. Это подходы и привычки.

обработка ошибок — этому вообще непонятно как учить без практических работ

Ну вот на практических и надо.

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

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

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

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

Прикладное программирование — это мода.

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

Как-то освоить новые модные технологии можно за полгода

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

Та же самая ситуация, что и с любой другой дисциплиной в любом другом ВУЗе: вначале идут фундаментальные знания, потом — их практическое применение.

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

А смысл в этом какой?

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

А вообще, забавно. Keyten предлагает сначала обучать программированию, потом теории алгоритмов. Вы — сначала теории алгоритмов, затем программированию. А я — одновременно. Кроме варианта «не обучать» перебрали все.

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

Ага, и с открытия своей таблицы Менделеева, и таблицы умножения, и решето Эратосфена (до н.э. разработан алгоритм, но нет же, нужно самому студенту до уровня Эратосфена дойте).

UFO just landed and posted this here
UFO just landed and posted this here
Так зачем насильно пропагандировать программирование? Качество обучения важнее. А кто хочет (на самом деле) этим заниматься, тот будет, и никаких проблем не возникнет.
UFO just landed and posted this here
Ваша логика не работает. Если вы хотите что-то добавить, то вы должны что-то выкинуть из программы. А выкидывать нельзя. Значит и добавить нельзя. Конечно, можно напичкать кучу всего в программу, так, чтобы ученик уходил утром и приходил вечером, но это уж точно будет насилие, вряд ли вы это подразумевали.
UFO just landed and posted this here
Возможно будет и лучше, но нужно быть осторожнее в рассуждениях что и для кого лучше. Я вот никакого отношения к школьному образованию не имею и не берусь утверждать что выкидывать а что нет. Иначе вы рискуете стать как Роскомнадзор — он ведь тоже хочет как лучше, запрещает вам всякие гитхабы и стимы, лишь бы вы ненароком марихуаны не попробовали, но почему-то всем он мешает жить и все его ненавидят за это. Вот и вы можете стать как Роскомнадзор для школьников, т.к. это проблема сложная, и тут нужно очень хорошо разобраться перед тем как что-то менять.
Вы не правы. В современном мире основы программирования, возможно, даже важнее, чем изучение физики и многих других классических школьных дисциплин. Качественное обучение школьника немыслимо без хотя бы очень приблизительного понимания им, как написаны те компьютерные программы, которые он каждый день использует. Причины, по которым точки зрения, подобные вашей, всё еще имеют место, в молодости программирования и, пока что, в отсутствии настоящего понимания у кого-либо, как именно его нужно преподавать.
Я уже написал по этому поводу — http://habrahabr.ru/company/hexlet/blog/248921/#comment_8246799. Вы наверняка айтишник и смотрите на это однобоко, конечно же программирование у вас важнее всего на свете.
AFAIK, программирование и так есть. У меня оно было, по крайней мере, причем отдельным предметом от «информатики». Я точно не помню, но, кажется, начиналось это в 7 классе и там был Pascal. Просто люди предлагают чуть ли не в начальной школе это давать. И уж точно это не важнее, чем база вроде математики. Тут не важно, в каменном веке мы живем или в цифровом — база есть база.
Не исключаю, что если бы в начальной школе у меня не было логомиров, я не был бы программистом сейчас. В то время я учился в обычной школе. Считаю, что мне очень повезло. С удивлением узнаю от ребят, кто сейчас учится в школе или недавно закончил, что почти у всех было только заучивание учебника и то в старшей школе. Понимание компьютера в современном мире не менее важно, чем умение читать и считать.
Одно неотделимо от другого, ибо любая программа есть воплощение некоего алгоритма. Не надо «курса по алгоритмам», можно просто ненавязчиво объяснять, что сначала надо понять, что и в каком порядке должна программа делать, а потом уже писать.
UFO just landed and posted this here
Например, простая робототехника — что-то типа LEGO MINDSTORMS EV3.
Лично мой путь начинался с противоположного — с олимпиадного программирования, с изучения и освоения алгоритмов. Но иногда вспоминаю, как я создал именно работающее приложение — и это было классным чувстов. Может быть именно создание первого приложения, легкие деньги и ложные мысли о том, что ты умеешь программировать, новичка улекут именно по этой стезе?

PS может быть нужно создать еще один опрос — с чего начинали вы путь программиста?
А когда Ваш путь начался? Просто как-то слабо себе представляю, как он сразу начался с олимпиадного программирования.
Это с точки зрения учителя хорошо, но ученики вряд ли на такое согласятся.
А почему нет? Тут вроде речь про университеты идёт.

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

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

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

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

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

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

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

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

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

> И концепт «оптимальности», там, насколько я понимаю, отсутствует — как компилятор скомпилирует, так и получится

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

> В реальной жизни оптимизировать придется.

Опитмизировать «под капотом»? Придется. Но изучать оптимизацию люди будут уже после того, как научились хоть какого-то результата достигать, а не после. Уже на втором-третьем курсе, например. Нет совершенно никакого толка от умения оптимизировать, если продукт не готов.

www.artlebedev.ru/kovodstvo/sections/167/

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

Вот за подход «магическая машинка» надо расстреливать на месте.
это основной подход практической бытовой функциональщины. У нас есть стандартная библиотека, которая по сути есть набор магических машинок. К этим машинкам дан удобный интерфейс для их настройки. Программа строится как использование готовых, но настроенных нами машинок. Язык и стандартная библиотека сдизайнены так, чтобы выходить из этой метафоры нужно было как можно реже. И если уж выходить, то писать новую магическую машинку. Это круто, это работает.
Это работает только если программист знает, что коробка не магическая и способен если не переписать ее, то хотя бы в общих чертах понять ее устройство.
Так это… В любом курсе по ФП реализацию, например, map для списков изучают вместе со списками
Функциональщина на первый вид может быть и сложна для чистых императивщиков. Это может выглядеть сложно: collection.Where(r => r.Date > DateTime.Now). Еще более сложно то, как оно на самом деле работает. Но это просто. И чертовски упрощает жизнь.

Теперь, по поводу концепта оптимальности. Вы хотите выжрать весь ресурс CPU с максимальной эффективностью? Не делайте этого на Haskell. Не делайте этого на Java. Делайте это на C/C++.

Я тут занимался давеча оптимизацией — переводом работы кривого императивного кода написанного с помощью Entity Framework на декларативный sql. Расскажи мне теперь про понятие оптимальности и необходимости знания архитектуры процессора, чтобы понимать с какой скоростью выполниться запрос к моему REST-сервису.

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

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

Хочешь я расскажу про настоящий бич производительности? У меня система постоянно держит загрузку CPU на 5-15 процентах. И полностью не отзывчива. Я доставляю 8 гигабайт оперативы — и оп-па, уже можно работать. Я доставляю еще 8 гигабайт оперативы — и оп-па, лагов практически нет. Никому не интересно, почему понижая процент занятости ОЗУ с 50% до 25 мы резко увеличиваем отзывчивость системы и софта? Я немного размышлял на эту тему, и мой текущий вывод — все механизмы работы с памятью, начиная от аллокации являются полностью кривыми и протекают.

Увы, я сейчас не могу найти ссылку на демонстрационный патчер, который улучшал работу с памятью для программ написанных на C/C++. И тут тебе не помогут никакие супер-ухищрения при написании императивного кода. Повышаешь уровень абстракций до объектов/функций, приходишь в enterprise или просто говноконтору — и все, у тебя нету никакого варианта управлять моделью памяти так как тебе нужно. И по барабану — императивщина/функциональщина. Пока ты не опустишься до уровня ручного управления памятью, ты не сможешь выжать максимум из своего компьютера. Но кому это нужно?

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

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

P.S: Если вы вдруг подумали, что я сторонник чистого функционального программирования — это не так. Я считаю чистое императивное и чистое функциональное программирование двумя отличными идеями, чтобы оказаться в жопе. Смесь парадигм принесет счастье и мир программисту.
Дело в том, что в промышленном программировании очень мало задач, которые жрут CPU. Они все написаны и решены за нас.
Из за такого подхода мы имеем то, что мы имеем.
все механизмы работы с памятью, начиная от аллокации являются полностью кривыми и протекают.
Нет, просто в программах слишком много слоев абстракций, которые жрут память.
Посмотри на веб.
Смотрю и хочу поубивать всех, кто приложил к этому убожеству руку.
И очень мало кому нужно знание ассемблера.
Знание ассемблера нужно чтобы понимать как все это работает и не падать на колени в религиозном ужасе если авторы компилятора накосячили (а такое бывает).
Смесь парадигм принесет счастье и мир программисту.
Речь идет о начальном уровне. На начальном уровне хватит и одной парадигмы, и это должно быть императивное программирование.
Из за такого подхода мы имеем то, что мы имеем.

Ты читать умеешь? У меня 5-10% загрузки ЦП. Мой процессор практически не занят. Ему нету работы. Графику и видео рендерит видеокарта. Если человек играет в игры — то они жрут все (процессор, видеокарту, память). Все, на десктопе для среднестатистического юзера закончились задачи, которые требует огроменных ресурсов. Изредка запускается архиватор (давно не запускал), фотошоп какой-нибудь (опять же, давно не запускал). У меня лично время от времени отъедается значительная часть ЦПУ на компилирование проекта (но это происходит не часто). Если мы берем среднестатистического юзера, то большую часть времени его процессор простаивает. Да, процессоры в росте тактовой частоты остановились. Ну и что, если эти такты все равно не используются?

Дальше, бекенд. Бекенд это царствие слоупоков. Ваш код практически не жрет ресурсов, а если жрет — вы что-то сделали не так. Забыли про кеширование, например. Процессор просто простаивает пока гоняются запросы туда/сюда. Ну или вы имеете дело с одним из немногих участков кода, которые реально выполняют объемные задачи, которые требуют процессор. Сейчас уже легче, есть асинхронное программирование, но утилизация CPU желает лучшего. Единственное, что жрет ресурсы в бекенде — это всякие прикольные вещи типа sql server, rabbitmq, memcached, elasticsearch. А еще например, задачи конвертации аудио/видео — они работают через ffmpeg. Скажи, вот ты готов что-нибудь из этого полностью реализовать? За две недели. И чтобы все работало быстро, без багов. Если нет, то давай ты откинешь свой аргумент.

Нет, просто в программах слишком много слоев абстракций, которые жрут память.
Я не знаю как написать то, что я написал раньше, поэтому повторюсь: ты читать умеешь? Почему при одинаковой утилизации ЦПУ (небольшой — 5-10%) и разной утилизации ОЗУ (75%, 50%, 25%) на глазах видно как отзывчивость системы и приложений меняется? Дело не в том, что им не хватает памяти, или они жрут память. Дело в том, что никто этой вашей памятью распоряжаться эффективно не умеет. И императивное программирование от этого не спасет.

Смотрю и хочу поубивать всех, кто приложил к этому убожеству руку.

+ + +

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

Так, я понимаю, ты больше C/C++? Ну и как это тебе помогло? Вот я нашел багу в спецификации языка. Знаешь что я сделал? С полным пониманием ситуации утерся и написал костыль.

слишком много слоев абстракций

Допустим много. Я сам так считаю, что многовато. Знаешь в чем проблема? Я вот тебе её в виде вопроса сформулирую. Есть задача — написать приложение, которое, к примеру (на той же Java) будет писаться год командой из десяти девелоперов. Сколько она будет писаться без лишних абстракций на том же ассемблере/си?
Сколько она будет писаться без лишних абстракций на том же ассемблере/си?
Полтора года командой из трех девелоперов. Ибо абстракции — это прямое следствие мифического человека-месяца.
… или одним человеком за 4 месяца на Хаскеле :)
Я же не говорю, что ФП — это плохо. Просто с него не надо начинать.
Стоп. Сначала «ломаем мозги» переменными и циклами, а потом «функциональщину сложнее понять». Если человек хотел просто удвоить каждый элемент в списке, может быть дать ему написать list |> map x => x *2, а не засирать мозги ненужной для задачи ерундой?)
Человек не знает что такое список. Он хочет не удвоить каждый элемент, а, скажем, посчитать количество рогов в каждом колхозе при известном количестве копыт. И ему сперва нужно объяснить, что копыта нужно записывать в список или массив, а не заводить отдельную переменную для каждого колхоза. А уже потом он сам решит, нужна ли в том конкретном приложении функциональщина.
Только надо в таком случае ему сразу показать, что можно или циклом пахать по этому списку или массиву, или map'ом функцию применить, а не культивировать миф «функциональщина — сложно».

И да, я всегда ставлю вопрос по-другому: «нужна ли в конкретном приложении императивщина»
Только он не знает, что такое функция. И вообще ничего не знает. В лучшем случае — по аналогии с математикой.
Тот, кто учился хотя-бы в 7-м классе не может не знать, что такое функция)
UFO just landed and posted this here
В функциональном программировании функция представляет собой ровно то же самое)
UFO just landed and posted this here
Я это прекрасно осознаю. В чистых функциональных языках (Haskell) функции зависят только от аргументов, если передав в f(x) 2 в качестве x я получу 20, то эта функция всегда вернёт 20 и только 20. Более того, некоторые императивные языки (например, D) могут дать аналогичные гарантии (модификатор pure)
В функиональной парадигме, если добавить значение «зависло», то это всегда так.
Функциональная парадигма отчетливо дает понять, что даже основные структуры данных, вроде массива, списка и словаря — не что иное, как функции в их чисто математическом понимании.
С одним параметром. А о декартовом умножении и тьюплах догадываются далеко не все первокурсники.
f(x,y) = x + y
Школа закончилась, это универ, детка

Если серьёзно, то достаточно показать вышенаписаную функцию и становится всё понятно даже без объяснения
достаточно показать вышенаписаную функцию и становится всё понятно даже без объяснения
Как называется когнитивное искажение при котором специалист считает неочевидные вещи очевидными? Это на самом деле совсем не очевидно.
А как называется искажение, при котором человек не может рассуждать по аналогии?)

Ну хорошо, можно показать
f(x) = x + 2
f(x, y) = x + y

можно даже пояснить, что первое — функция с одним аргументом, прибаляющая к аргументу 2, второе — функция с двумя аргументами, складывающая их. Это ни весть какое усложнение по сравнению с переменными :-)

P.S. можно долго разводить софистический спор о том, что очевидно, а что — нет.
Грудь — единственный интуитивный интерфейс, всему остальному приходится учиться.
А как называется искажение, при котором человек не может рассуждать по аналогии?
Судя по моему не очень большому жизненному опыту, оно называется нормой. Но проблема не в этом а в том, что в ФП даже для простейшего действия, как например удвоение элементов в списке, нужно вводить функции, функции высшего порядка и т. п. В императивном программировании вводится только одна новая сущность: цикл.
В императивном программировании вводится только одна новая сущность: цикл.

Неправда. Циклы, переменные, ветвления — этого всего не было.

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

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


Неспособность мыслить логически — норма? Ок.

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

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

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

«тут критик воскликнет», а что если у нас нет готового count в апи коллекций? Ну что ж, тут мы тоже можем выехать без всех этих массивов и циклов (это подсчет для кложуровского сиквенса):

#(reduce 
    (fn [c _] (inc c))
     0 %)


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

в данном примере не пострадало ни одного человека, заставленного изучать механику работы с памятью, необходимую для массивов, итп
Вроде понятно, а вроде нет. Что есть reduce?
UFO just landed and posted this here
Ну вот в Стэнфорде показывают алгоритм в псевдокоде, со словами «реализовать на вашем любимом ЯП можете сами». При этом практикум выглядит как «вот вам входные данные, дайте нам результат».
UFO just landed and posted this here
Да погодите. Никто и не говорит, что вам надо учиться программированию на бумажке — делайте это с использованием ПК, не надо себя насиловать. Просто изложение фундаментальных алгоритмов с применением — это, как мне кажется, общепринятая практика. Псевдокод позволяет, в первую очередь, сосредоточиться на том, как работает алгоритм. Безусловно, описывать CRM-систему или что-нибудь такое же монстроподобное на нём не надо :)
UFO just landed and posted this here
Согласен. Теория, не подкрепленная практикой, имеет свойтво исчезать из чертогов знаний :)
Нет, сейчас в МГУ это С. От Pascal отказались.
Все обстоит немного иначе. Одним из мощнейших инструментов для борьбы с чудовищной алгоритмической сложностью является псевдокод. Объем тасков, которые вы можете написать (оставаясь при этом в здравом уме) без псевдокода очень ограничен. За примерами — к Кнуту (который написал TeX на смеси Pascal с псевдокодом).
Сходите откройте фундаментальный труд Искусство Программирования Дональда Кнута. ВНЕЗАПНО там псевдокод для несуществующей машины.
UFO just landed and posted this here
Раз для машины, даже несуществующей, уже не псевдо. Псевдокодом называют код с не четко прописанной семантикой.
А низкоуровневые императивные алгоритмы можно сразу и не показывать вообще. Вот есть в стандартной библиотеке алгоритм sort. Ну и черт с ним, какая разница как он работает, главное что сортирует! Предположим, что sort и прочее у нас уже есть, и начнем решать настоящие задачи. В качестве языка можно взять как раз какой-нибудь лисп, чтобы не нужно было изучать синтаксис. И только потом, когда человек начинает понимать, что и зачем он делает, тогда углубляться в «что там под капотом».
А потом эти одухотворённые Хаскелем студенты придут в реальную промышленность и их придётся обучать заново?
Ну по крайней мере они будут знать что-то из математики.
Лично я не могу считать программистом человека, который не может написать бинарный поиск (а таких я, к сожалению, встречал не мало)
А я не могу считать программистом человека, который не понимает указатели.
О, да! Именно математический пуризм Pascal в определении указателей мне сильно мешал в свое время переходу на C.
В чем там математический пуризм-то? :) Я, правда, в Turbo Pascal особо не программировал, сразу на Дельфи сел, но не помню ничего особенно «математического» в них.
А Turbo Pascal это не Pascal, там уже адресная арифметика, нетипизированные ссылки и т.п. Меня учили по чистому творению Никлауса Вирта, не испорченному грязными руками Филиппа Кана и прочей Borland :)
По-моему, того Паскаля уже «нет» :) Во всяком случае, FreePascal, имеет вполне себе нормальные указатели. Не знаю, какой из вариантов Паскаля кроме Дельфи и FreePascal сейчас стоит использовать для обучения…
А никто не говорит что 5 лет нужно учить Хаскель. Речь идет про первый язык, введение.
Судя по письму Дейкстра, он как раз предполагает, что первый язык уже был императивный.
А что в самом Хаскеле или его парадигмах его мешает «реальной промышленности»?
Ничего, кроме инертности индустрии и армии Java-программистов, которые хотят есть.
Мне кажется что хаскель программиста легко будет научить писать на джаве, а вот наоборот сложновато
Его не нужно будет учить, он сам ее изучит за недели две.
Джава сама захочет изучить хаскель-программиста :)
Интересная мысль. Можно аргументировать? Переход от одной парадигмы к другой, мне казалось, сложен в обоих направлениях.
Боюсь, тут гораздо больше проблем будет в стиле:
  • я писал 100 строчек на haskell, почему мне приходится писать 1000 строчек на Java, чтобы реализовать эту же ерунду?
  • и это вы называете системой типов?
  • ладно, а где автовывод типов?
  • и это вы называете паттернами?
  • ребята, вы вообще имеете представление о хорошем коде?


Я изначально учился императивному программированию, функциональное освоил после и не в полной мере. Сравнивая свой профессиональный опыт C# и «около-универское-около-хобби» Java я могу однозначно сказать, что для меня во многих случаях вернуться к императивному подходу (там где нету функций высших порядков, там где нету гарантии неизменяемости, там где нету гарантии отсутствия явновыраженных side effects) — это мучительно больно, но все же не составляет затруднений. Ну т.е. я могу с легкостью фигачить на Java говнокод, тогда как тот же код на C# получился бы у меня конфеткой. Как в условиях тотальной ментальной ограниченности языка писать хороший поддерживаемый код — этого я не представляю.

Главная трудность программирования — это писать хороший читабельный изменяемый код. Боюсь, программист на Haskell не сможет так легко с наскоку освоить этот навык для Java языка. А к тому моменту когда он сможет освоить этот навык, программист застрелится.
Хаскель программист не захочет программировать на Java :)
То, что на производстве он редко где используется?
UFO just landed and posted this here
Зачем, поищут место где будут писать на Scala, Clojure ну или Python или JS на худой конец.
Должен признаться, я не особо понимаю, в чем хороша армия разработчиков в «реальной промышленности», которые обожают void методы, боятся слова «монад» и не исходят из того, что immutability должна быть поведением по умолчанию. Разве что поддерживать legacy?
Человек, который умеет в Хаскель, скорей всего научится в ваш язык программирования за две недели. Более того, он может быть даже напишет компилятор вашего языка программирования за две недели на хаскеле xD
Потом они наконец приведут промышленность в нормальное состояние, когда глюки программ станут редкостью.
Функциональный стиль делает и программирование на императивных языках чище.
И студенты довольно быстро замечают элегантность функционального подхода

Вот что-то не верится…
Не верится если представить студента, который начал знакомство с программированием с public static void, а потом ему показывают чистую функцию без побочных эффектов на Лиспе, и он, конечно, никакую элегантность не понимает.
Я могу поверить в студентов MIT или заведений сходного уровня подготовки и отбора — но тем не менее — чистый функциональный подход — достаточно тяжелая для головы концепция и даже состоявшиеся и опытные программисты от «пишу код на хаскеле» до «понимаю функциональный подход, его плюсы/минусы/ограничения» тратят не один год. Императивное объектно-ориентированное программирование дальше от математической чистоты, но ближе к «осязаемому» миру — поэтому для восприятия проще. Современные языки позволяют «эмулировать» функциональные подходы в разработке — и как мне кажется — проще на них выйти уже убедившись, что студент смог понять и принять более простые подходы.
не могу не вспомнить старую шутку — программист на Фортране на любом языке может писать на Фортране. Хаскель, хоть и усложняет это дело — но не меняет в корне.

Из личного опыта — от момента, когда я проникся и восхитился элегантностью TDD, в частности BDD, до момента, когда я смог его эффективно использовать на реальных задачах, сложнее «протестируйте калькулятор» — прошло около полутора лет — и то, потому, что я искренне верил в то, что это нужно и важно.
Коллега, я вам завидую. Кроме шуток. А Вы не могли бы поделиться опытом использования TDD/BDD на реальных задачах? Если, конечно, имеете такое желание и возможность.

Имхо...
Тоже придерживаюсь мнения, что разработка через тестирование абсолютно нужное и важное направление. Правда, в большинстве литературы на этот счет приводятся примеры, не сложнее, как вы сказали «калькулятора». Внимательная медитация над «опусами» Кента Бека и М. Гартнера заставило плевался и вообще послать идею TDD куда подальше. Но все-же есть какое-то внутреннее понимание того сама концепция имеет право на жизнь. Вот только как ее применять на реальных проектах?


В BitcoinJS тесты вместо документации. Эта библиотека используется в таких крупных проектах, как Blockchain.info. Мне кажется, что ответ на ваш вопрос включает почти все библиотеки и многие приложения. Можно даже писать тесты к сайтам: писать запросы и ставить проверки на ответы. Кроме того, TDD даёт однозначный ответ на вопрос «когда делать коммит» (когда дописали до момента, что все тесты проходят и ими покрыт весь код).
Ответ хороший, но есть нюанс — если ты не TDD раньше — то ты не напишешь сразу код так, что он будет тестируемый.
Ну и 100 процентное покрытие — это избыточная (иногда значительно) сложность — особенное если имеешь дело не со stateless приложениями. Да и просто возникают тысячи вопросов на тему «о, это так здорово — но как протестировать, когда у нас вон тот объект дергает вон этот синглтон, в котором изменяется состояния вон тем классом и вообще?» На которые «просто писать код иначе» — не самый подходящий ответ))
ты не напишешь сразу код так, что он будет тестируемый.
Могу соврать, но вроде бы чистый TDD подразумевает написание сначала тестов, а уже потом кода. Сначала скажи, что хочешь от кода, а потом пиши код. Разумеется, это происходит не в масштабах всего кода, а только отдельных классов и функций. При таком подходе исключается возможность написать нетестируемый код :)

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

Если код настолько сложен, что его не удаётся полностью обложить тестами, то его надо разбивать на простые модули, которые будет проще покрыть тестами. Тестировать можно на разных уровнях и разными способами. Даже если приложение не stateless, то в нем всё равно можно выделить набор типичных сценариев использования, в которых проявляется вся его функциональность. Даже графические приложения можно покрыть тестами, программно имитируя работу пользователя с графическим интерфейсом.
но как протестировать, когда у нас вон тот объект дергает вон этот синглтон, в котором изменяется состояния вон тем классом и вообще


ай! в точку!

А еще, если...
А еще, если класс имеет состояние (т.е. не совсем чистый черный ящик)… Или хуже: логика/результы его работы зависит от внешних факторов: текущей даты, окружения ОС, кодировки, таймзоны, или фазы луны ))
Вот например, такая элементарнейшая задачка, автоматизация тестирования которой меня лично ввела в ступор: есть простая библиотечная функция из 15 строк, рекурсивно удаляющая из указанного каталога файлы старше N дней. Как протестировать правильность ее выполнения? Вроде функция классический черный ящик, опирающийся исключительно на функционал File/Date. Ан, нет… имеет неявную внешнюю зависимость.

Придется для теста создавать во временном каталоге структуру из папок и файлов, принудительно менять им дату создания и потом поверять, что из них реально осталось.
И еще написать тест для теста. А то мало ли…
Это хорошо, когда вот так вот дату создания поменять можно. А когда нельзя?


За ссылки спасибо.
есть простая библиотечная функция из 15 строк, рекурсивно удаляющая из указанного каталога файлы старше N дней
Если не получается протестировать это по-нормальному, то можно подменить глобальные функции (если язык это позволяет). Например, заставить код тестов думать, что сейчас какая-то определенная дата и дата создания файла тоже определенная. А можно подменить все функции работы с файлами, чтобы самих файлов не было, а тесты считали, что они есть и созданы тогда-то. Если такой возможности нет, то придётся получать права в системе, необходимые для манипуляций с датами файлов (в линуксе для этого вроде бы рут не нужен).
А еще, если...
Подобные проблемы решаются с помощью Dependency Injection или Inversion of Control
Inversion of Control (на английском, пример на C#)
… есть простая библиотечная функция...

Если функция библиотечная (то есть а. Вы не можете ее изменять и б. она уже стабильна) то тестировать ее не нужно. Если же функция Ваша, то тестируется логика работы самой функции. А реальный код удаления для теста подменяется при помощи DI или IoC. Для отдельно стоящей функции — это, например, может быть еще один параметр с объектом (или указателем на функцию), ответственным за реальное удаление. Для класса все красивее (смотрите видео).
TDD очень хорош на реальных задачах класса «давайте напишем сервис, который делает так, так и вот так» — отрезаем все внешние зависимости, а дальше делаем что угодно.
Еще TDD очень хорош при проектировании API. Так например, в процессе создания библиотеки для проекта мне концепция TDD позволила вовремя увидеть, что планируемый API не совсем удобен для использования. Представляю, если бы сей факт был выявлен уже после ее написания.
Вот пример того, как тесты помогли найти источник тормозов в игре.
Хм, а почему, собственно, вы считаете функциональный подход сложнее императивного? Т.е. если взять студента, у которого ещё нет серьёзного опыта программирования ни с функциональным, ни с императивным подходом, то чем обучение в рамках первого сложнее обучения в рамках второго?

В императивном языке вы описываете последовательность действий, присваивания и main, в функциональном — последовательность вычислений, let-связывания и REPL. В императивном вы объединяете данные в массивы, в функциональном — в списки. В императивном вы сначала вычисляете аргументы, потом саму функцию, в функциональном-ленивом — сначала функцию, а потом по необходимости аргументы. Циклы, правда, в функциональщине заменены более тяжёлой для восприятия рекурсией, но ведь её так или иначе придётся изучать. Да и с рекуррентными соотношениями типа факториала, которые и суть рекурсия, студенты к этому моменту должны уже быть, по идее, знакомы. В общем и целом, если вы не переучиваетесь, а именно учитесь с нуля, то вряд ли найдёте в ФП много более тяжёлых моментов, чем в ИП. И даже наоборот — вам не придётся думать про суть переменных и как они хранятся в памяти, как состояние может меняться во времени, как следить за переменными в цикле и т.д.
Я больше вот о чем: изучать предмет лучше, когда упражнения как-то взаимодействуют с реальным миром. А в чисто-функиональном мире это-то как раз хоть и элегантно, но сразу концептуально сложно и при изучении воспринимается скорее как оверхед/костыли.
А вы просто не с той стороны заходите. Конечно если в Haskell пытаться засовывать с ходу оконный интерфейс у вас проблемы будут. Haskell нужно воспринимать как движение от мира математики к реальному миру, тогда он оказывается прост и естественен.
Да, я действительно захожу с другой стороны. Ибо считаю, что теория до практики бессмысленна. И что двигаться надо не от математики к реальному миру, а от реального мира к математике.
Для многих практичных не сложных задач хватает REPL.
Моделирование — вполне реальная задача, которая интерактивности не требует.
Для интерактивности есть реактивное программирование, хорошо укладывающееся в функциональную парадигму.
Двигаться надо от задачи. Иначе получается программирование ради программирования. По-моему, это очень скучно.
UFO just landed and posted this here
UFO just landed and posted this here
Поддерживаю. После полного освоения C надо освоить какой-нибудь скриптовый язык с элементами функциональщины: Lua, JavaScript, Ruby или Python. Потом перейти к C++ и параллельно осваивать теорию: структуры данных и алгоритмы. А там и срок обучения закончится. Чистые функциональные языки можно осваивать параллельно как дополнительный материал, чтобы повышать кругозор.
но лучше конечно с ассемблера, чтобы понимал, как это работает «внизу»
UFO just landed and posted this here
Согласен полностью, пришлось проголосовать за пункт «Java, C, C++», хотя Java (или C#) кажется мне менее правильным выбором ЯП для студента, слишком много он скрывает в своей реализации. Нужно, так сказать, понюхать пороха, увидеть неадекватное поведение при чтении памяти за границами массивов, посмотреть на строки в памяти или иной раз поломать (студенческую) голову над +1 в длине буфера, и так далее. Потом легче жить будет!
И миллионы индусов со знанием английского сразу станут считать себя программистами?

P.S.
Хотя похоже так оно и есть…
Это совет тем, кто с английским пока не дружит.
В самом начале — с того, на котором проще сделать первое приложение. Тут важно получить быстрый фидбек, чтобы заинтересовать.
На втором этапе новичек столкнется с «ужас все тормозит». Вот тут уже заглядывать под капот языка, знакомится с ассемблером и теорией алгоритмов.
И вот только на третьем этапе следует овладевать языком программирования как инструментом. Тут можно и функциональщину показать.

Начинать с функциональщины сразу — имхо отбивать охоту к программированию.
В целом согласен.
Лично я начинал программировать с Бэйсика на спектруме. Но главное зачем? Я писал музыку, которую задавали в музыкальной школе, чтобы свериться: правильно ли я играю.
То есть была сумасшедшая мотивация и интерес, и полное непонимание происходящего нисколько не остановило меня.
Осталось решить, что называется приложением…
Кстати, простое браузерное приложение на elm написать будет проще, чем на js.
Я где-то полгода назад смотрел elm, просто для общего развития. Мучил его целую неделю, но так ничего сам на нем написать и не смог (опыт ФП у меня никакой, только лямбды в C-подобных языках). Самый частый вопрос, который у меня возникал в процессе: «что означает вот этот символ?». То есть, до, собственно, программирования, каких-то алгоритмов и т.п. я так и не добрался, так как ответ на этот вопрос в половине случаев найти не удавалось. Так я elm и забросил.
Синтаксис elm основан на Haskell, синтаксис которого основан на математической нотации. Обычно после стандартных математических курсов он интуитивно понятен.
К тому же в новом языке всегда такие вопросы возникают. Скажем функциональным программистам непонятно, что такое return и зачем его надо писать :-).
Да, я как раз остановился на том, что узнал, что синтаксис elm основан на Haskell, а учить один язык, чтобы выучить другой язык у меня желания не оказалось.
Но если изучать как первый язык или в рамках школьного/институтского курса — таких проблем не будет.
Возможно. Однако, на мой взгляд, лучше было бы что-то человекочитаемое вместо математикочитаемого.
И сложно решить, что лучше: как можно быстрее научить созданию простых приложений без реального понимания программирования, алгоритмов и их вычислительной сложности, а потом начать знакомство с этими важными темами, или начать «с начала», и органично придти к созданию приложений и продуктов после освоения фундамента.

На самом деле, сам факт того, что в этом месте ставится выбор — это уже печально. Я думал, что тут выбор очевиден, но вопрос-то ставится, значит кому-то скорость обучения важнее качества. Я понимаю, что в современных реалиях почти вся теоретическая основа не нужна, все сводится к бездумному умению строчить код. Дошло уже до того, что многие корректно написать бинпоиск не в состоянии — так зачем уметь, если всё это есть в стандартной библиотеке любого языка? Кстати, тот же алгоритм Дейкстры сейчас разве что программист-олимпиадник напишет просто из головы. Но с другой стороны, люди, у которых знания шире обычного «программиста» всегда ценятся. И чем больше дефицит, тем больше они ценятся. Тех же призеров Google Code Jam/Facebook Hacker Cup гугл с фейсбуком сами в слезах уговаривают пойти к ним работать, знаю не по наслышке. Вас вряд ли встретят с таким энтузиазмом, если вы просто придете на собеседование.
С распространением идеи «научимся кодить!» и «кодинг это новая грамотность», программирование стало в глазах многих простым инструментом для решения мгновенных бизнес-задач и просто для казуального хобби-кодинга. И как бы нам это нравилось или не нравилось, правда в том, что многие люди намеренно не собираются и никогда не будут изучать алгоритмы и структуры данных, работу с памятью и архитектуру компьютера. Рассуждая примерно так: "есть графический редактор – на нем можно смастерить плакат, и не нужно изучать типографику, полиграфию и дизайн. И есть программирование (а лучше какой-нибудь готовый целевой IDE вроде Android Studio) – на нем можно смастерить приложение, и не нужно изучать информатику".

Мы, как образовательный проект, конечно же считаем что важно изучать основы (поэтому публикуем уроки по алгоритмам, операционным системам, СИКПу, протоколам и пр.). То предложение, которое вы процитировали, это рассуждения на тему того, что если к нам пришел человек, который хочет сделать игру на мобилке, а мы ему предлагаем начать с алгоритмов, то он, возможно, уйдет в другое место, где яркими буквами написано «мы научим делать игры на мобилки!!!». Стоит ли его завлекать и убеждать в важности фундаментальных основ? Может, он никогда и не мог стать настоящим программистом?

И честно – непонятно что произошло. Человек начинается непонятных туториалов, напишет игру (которая будет глючить и сильно жрать батарейку потому что алгоритм не эффективен) и будет доволен, другие люди будут играть и будут довольны, при этом никто так и не узнает, что такое двоичный поиск.
Если честно, я просто в экстатическом восторге от того, что по мере развития технологий — инструментарий дорастает до того уровня, когда генератор идеи, после не слишком утомительного обучения, путем компоновки кубиков Лего способен САМ донести свою идею до заинтересованной аудитории, не опасаясь потерь на этапе объяснения этой самой идеи еще кому-то.

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

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

Все ж таки задача программирования заключается в облегчении чьей-либо жизни)

Так что да — это, конечно забавный факт, что появилось много людей, создающих продукты, не обладая базовыми знаниями в computer science — но все-таки положительный.
Потому что человеку не объяснили зачем вообще требуется писать хороший код, почему надо вникать в глубины. Зачем ему вообще надо во всём разбираться. Почему ему сейчас специально дают инструмент который ограничивает его от многих проблем и делает всё простым и понятным. Цель многих туториалов — «щас за 20 минут наклепаем программульку и ты будешь мега крут». И всё, другой цели нет. И развиваться у нас не хотят, потому что такой цели нет — «меня потом научат», «да меня научат всему на работе» или «и так же работает» и т.д.
Основная мысль была в том, что это и не нужно — для тех задач, которые решаются. Так что незнание основ — это даже более рационально. Я по идеологии скорее математик, чем программист, и мне незнание основ кажеться вообще дикостью какой-то. Но на деле эти основы и не нужны. А если и нужны, то задача очень специфичная.
Я работал с человеком, который был большим поклонником функционального программирования вообще и хаскеля в частности. Будучи полным нубом и в том и в другом я попросил его привести мне пример из реальной жизни, где использование хаскеля, к примеру, было бы предпочтительнее использования джавы. К сожалению, такового примера мне приведено не было. Хабражители, поделитесь, пожалуйста, примерами того, как хаскель помог вам в профессиональной деятельности. Это не подколка и не разжигание холивара, мне правда интересно.
Вы прост вопрос не очень корректно задали. Вобщем-то преимущество в любой области, поскольку преимущество в системе типов, а она используется везде. Мощная система типов способствует отладке программы в компайл тайме.
Ну лично мне он помогает писать наброски алгоритмов. Например, появилась какая-то бешеная идея в голове, доказать не можешь, но хочеться по-быстрому проверить работает или нет. Писать на какой-нибудь Java долго, а на хаскелле написать набросок в разы быстрее. Почему хаскель не прижился в проф. сфере, это уже другой вопрос, но польза от него есть.
Быстрая сортировка на хаскеле:

qsort []     = []
qsort (x:xs) = qsort small ++ mid ++ qsort large
   where
     small = [y | y<-xs, y<x]
     mid   = [y | y<-xs, y==x] ++ [x]
     large = [y | y<-xs, y>x]

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

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


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

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

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

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

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

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

Написать какой-нибудь engine для компресии данных будет стоить месяцы работы, вместо того чтобы докупить террабайтный винт за 60 баксов.
Это я и имел в виду. Ладно бы терабайтный винт, у некоторых тысячи машин с терабайтной памятью в каждой, а программистов для этого дела не хватает.
А не подскажите человеку, совсем не понимающему Хаскелл, где и как в этом коде элемент-разделитель выбирается?
Первый элемент из списка, понятно. Самая простая реализация.

Если захочется сделать более сложную — нужно будет вместо «x:xs» написать «xs» и сослаться на другую, вспомогательную, функцию, которая выберет вам «правильный» элемент. Причём можно будет сослаться на неё во всех трёх строчках не задумываясь о том, что тут «три раза функцию вызываем».
В C++ нету оператора сложения двух контейнеров и нет функции, которая складывает элементы одного контейнера, удовлетворяющие какому-то условию, в другой (в силу того, что работа с контейнерами в стандартной библиотеке построена через механизм итераторов). Если и то, и то реализовать, то получиться также коротко (разве что лямбды страшновато выглядят) и также неэффективно:
template<typename Pred>
std::vector<int> put_if(const std::vector<int>& vec, Pred pred)
{
    std::vector<int> result;
    std::copy_if(std::begin(vec), std::end(vec), std::back_inserter(result), pred);
    return result;
}

std::vector<int> operator+(const std::vector<int>& l, const std::vector<int>& r)
{
    std::vector<int> result(l);
    std::copy(std::begin(r), std::end(r), std::back_inserter(result));
    return result;
}

std::vector<int> qsort(const std::vector<int>& vec)
{
    if (vec.size() <= 1)
        return vec;
    auto small = put_if(vec, [&](int x){ return x < vec[0]; });
    auto middle = put_if(vec, [&](int x){ return x == vec[0]; });
    auto large = put_if(vec, [&](int x){ return x > vec[0]; });
    return qsort(small) + middle + qsort(large);
}
На C++ можно написать эффективную реализацию. А если использовать шаблоны, то можно на массивах из double заткнуть за пояс сишный qsort. Это просто замечательно. Но к этому пришли не сразу. Представим, что быстрая сортировка — это наш новый алгоритм, который до нас никто в мире не реализовывал. Не думаю, что было бы правильно реализовывать его сразу на C или C++ в таком виде, как он реализован в стандартной библиотеке. Сначала надо было бы реализовать наиболее понятным способом. Затем протестировать, убедиться, что всё работает правильно. А потом, если эта понятная, но медленная реализация окажется узким местом, переписать на C, используя оптимизации. И снова прогнать тесты, чтобы не наляпать при этом.
Или даже так, буквально транслируя словесное описание алгоритма быстрой сортировки:
qsort []     = []
qsort (x:xs) = qsort (filter (<x) xs) ++ filter (==x) xs ++ [x] ++ qsort (filter (>x) xs)
qsort [] = []
qsort all@(x:xs) = foldl (++) [] $ map (flip ($) all) $ [qsort . filter (<x), filter (==x), qsort . filter (>x)]

%)
Яркий пример — монад Maybe. Да, в Java 8 уже есть монад Option, но не так много людей на нее перешли и еще меньше его будут использовать. Когда я использую Java библиотеки (в Scala), мне приходится оборачивать каждый вызов в Option(a).flatMap(_ => Option(b)).map(doSomething), а то еще кинет где нибудь null (ведь ничего этому не мешает), и что мне с ним делать?
По умолчанию на Хаскеле предпочтительно писать все. Потому что это быстрее, безбажнее, красивее, короче, поддерживаемее, расширяемее и т. д. Однако, есть ограничения:

— вы хотите использовать какие-то объемные библиотеки, которые есть в Джаве/Си++/ваш язык, а в Хаскеле — нет, и писать самому — выйдет таки дороже (сильно дороже, если библиотеки прямо сильно большие)
— у вас есть требования по скорости/потреблению памяти, которым Хаскель временами просто не может соответствовать. Даже Джава, вопреки распространенным упрекам малознакомых с нею личностей, может соотвествовать почти каким угодно требованиям. Ну а нативные языки соответствуют им по умолчанию.
— бизнес-аргументы — у вас есть разработчики на Джаве/вашем языке, но нет на Хаскеле
А что если взять ваш комментарий и заменить слово «Хаскель» на слово «Lua»? Тоже мало библиотек и программистов и эти программисты тоже призывают на Lua писать всё, а потом оптимизировать на C нагруженные точки программы. Звучит вполне разумно, благо Lua и C очень хорошо взаимодействуют. Дальше возьмите JavaScript — тот же Lua, но как язык похуже (с моей точки зрения), однако с огромным количеством библиотек и программистов. Почему бы не использовать «предпочтительно» скриптовые языки такого типа?

Для проверки я решил одну задачку на нескольких языках. Задачка решена на каждом языке наиболее понятным мне способом, безо всяких. Сама задачка хоть и счётная, довольно бесполезна, это просто первое, что пришло мне в голову. Так вот, на уровне сей справились Java, JavaScript, Python, Lua, JavaScript. Затем с многократным отставанием шёл Haskell, после которого ещё с трёхкратным отставанием Perl и Ruby. На Haskell получился очень красивый и короткий код, но писал я его дольше всего. Получается, программы на Haskell дольше пишутся и медленнее работают, чем на быстрых скриптовых языках. Опять же, в случае Lua было бы очень просто переписать это место на C, а в случае с Haskell я даже не знаю, что бы я делал. В общем, это претензия скорее к моему незнанию Haskell, нежели к самому языку.
То, что Вам дольше заняло писать на Haskell, является функцией Вашего знания языка. Если сравнить читабельность Java против Haskell, последний (ИМХО) побеждает с существенным отрывом. Зачем все эти for?
Быть может каждый будет хвалить свое болото, но…
Scala + Scalaz = Java производительность в рантайме с силой многих фишек Haskell.
Самые сильные вещи в Хаскеле это параметрические тайпклассы, GADT всякие. Есть штуки такого уровня в Scala?

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

Замечание на тему того что Scala полностью поддерживает императивный/ооп стиль является правдой, но с другой стороны позиционируется как ее плюс. Весь вопрос в том, насколько радикально мы идем в ФП.
Обычные тайпклассы там делаются с помощью имплиситов.
С параметрическими сложнее, но можно по крайней мере в случае, если параметры из типа могут быть извлечены.
Я не знаю про Lua ровным счетом ничего, поэтому не могу ответить на ваш вопрос-предложение. JS не «похуже», а один из худших распространенных языков.

Да, Хаскель плохо подходит для числодробления, миллиардов операций. Он хорошо подходит, когда самих действий мало, но много логики. Писали вы его дольше всего, может потому, что вы не знаете Хаскель просто?) Ну да, я уже сказал что производительность это не его конек, хотя в большинстве жизненных задач он должен быть быстрее интерпретируемых языков.
Я не знаю про Lua ровным счетом ничего
Можете узнать почти всё за 15 минут. Если бы в JavaScript было меньше путаницы и были бы метатаблицы вместо прототипов, то это был бы почти Lua.

JS не «похуже», а один из худших распространенных языков.
Чем JavaScript хуже того же питона? Таким «плохим» JavaScript выглядит из-за тех, кто на нем пишет. Если бы веб-разработка происходила на паскале, то и паскаль был бы «один из худших распространенных языков».

Писали вы его дольше всего, может потому, что вы не знаете Хаскель просто?)
Так и есть. Это мой первый и пока что последний код на Haskell.
С числодроблением особых проблем нет. Только ручками придется строгость и unboxed-типы указывать.
Проблемы бывают в долгоработающих приложениях из-за накопления отложенных вычислений.
Вы просто не умеете готовить Haskell ^)
Спасибо! У вас значительно быстрее получилось. (А Lua всё равно в 2 раза быстрее.)

Должен отметить, что код стал менее понятен, хотя я его по-прежнему могу прочитать «со словарем». Чтобы догадаться до такого решения, надо в Haskell как следует разбираться. К примеру, для меня остается загадкой, почему мой код работал медленнее. Могли бы вы объяснить?
0. У меня ввыполняется 18 секунд.

1. Haskell по умолчанию работает с длинной арифметикой. Указываем, что работает с машинным Int-ом, и получаем 13 секунд.
После шага 1
cmpsum::Int->Int->Int->Int
cmpsum i j k =
    if i + j == k then 1 else 0

main = print $ sum([cmpsum i j k | i <- [1..1000], j <- [1..1000], k <- [1..1000]])


2. По вашему коду нужно сначала составить полный список, а затем сложить его элементы. На самом деле все немного оптимизируется, но тем не менее лишние сущности остаются.
Для начала можно избавиться от промежуточного списка - время выполнения 3 с
cmpsum::Int->Int->Int->Int
cmpsum i j k =
    if i + j == k then 1 else 0

main = print $ foldl (\acc i -> foldl (\acc j -> foldl (\acc k -> cmpsum i j k + acc) acc [1..1000]) acc [1..1000]) 0 [1..1000]


3. Но на самом деле это выглядит некрасиво, и все еще неоптимально. Избавляемся от маленьких списков, переходя к рекурсии, которая является по сути аналогом циклов в функциональном программировании
Именно этот код соответствует коду на С - время выполнения 1 с
cmpsum::Int->Int->Int->Int
cmpsum i j k =
    if i + j == k then 1 else 0

next i j 1001 acc = next i (j+1) 1 acc
next i 1001 k acc = next (i+1) 1 k acc
next 1001 _ _ acc = acc
next i j k acc = next i j (k+1) (cmpsum i j k + acc)

main = print $ next 1 1 1 0



Еще вот интересно почитать про такое же тестирование
когда вы выполняете sum [foo i j k | i <- [1..1000], j <- [1..1000], k <- [1..1000]], то получаете такие шаги вычисления

1. sum [foo i j k | i <- [1..1000], j <- [1..1000], k <- [1..1000]
2. sum [ [foo 1 ... 1000 j k] | j <- [1..1000], k <- [1..1000]] --- 1000 объектов foo i 
3. sum [ [foo 1 ... 1000 1...1000] | k <- [1.. 1000]] --- 1000_000 объектов foo i j 
4. sum (foo 1... 1000 1... 1000 1: [foo 1 ... 1000 1 ... 1000 k | k <- [2 ... 1000]) -- теперь первый элемент вычислен и его можно сразу просуммироать
5. sum (foo 1... 1000 1... 1000 2 : [foo 1 ... 1000 1 ... 1000 k | k <- [3 ... 1000]) 
6 ...


Таким образом получается в максимуме список из 1000_000 элементов
В моделировании микроэлектроники чистый Haskell оказывается удобнее, чем C++ со специализированной библиотекой SystemC, а тем более Java.
Я на нём пишу генераторы кода, а ещё он мне очень помог сесть и поехать на Scala и Swift. Хаскель ценен не сам по себе, а как источник идей из параллельного мира, который проникает в обычный довольно быстро.

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

Ну сказанное совсем не означает, что его вот прямо нельзя использовать в продакшене.
Возможно я сталкиваюсь с задачами, которые не так хорошо ложаться на хаскель. Вот к примеру: github.com/hulu/statsd-router. Можно ли подобную штуку сделать на хаскеле? И можно ли достичь сравнимой произволительности?
Мне трудно сразу въехать, что делает эта софтина, очень специфичная область, в которой я ни в зуб ногой.
Но хаскель — тьюринг полный язык, так что можно точно. Производительность тоже вопрос очень спорный.

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

Но, я надеюсь, мы не пытаемся сейчас обсуждать экстремумы типа «ничего на хаскеле!» и «всё на хаскеле!». Трудозатраты для написания стабильных, развесистых систем на языке с системой вывода типов а-la Хиндли-Милнер, паттерн матчингом и всякими прочими плюшками сильно меньше, чем создание такой же на Си. Поэтому нужно выбирать в каждом конкретном случае оптимальный вариант. Я бы не стал писать веб-сервис на си и драйвер файловой системы на хаскеле.
Как я сказал в своем первом вопросе я не подкалываю и не холиварю, я хочу понять могу ли я улучшить свою производительность, если буду что-то делать на хаскеле. Поэтому еще 4 уточняющих вопроса:

1. Насколько хорошо на хаскеле пишется сетевая часть?
2. Как в хаскеле с многопоточностью?
3. Можно ли на хаскеле писать event-driven программы с упором на сетевое взаимодействие в частности и I/O вообще?
4. Насколько удобно на хаскле реализовывать конечные автоматы?
C такими запросами вам Erlang нужен. Он можно сказать под такие запросы и создавался
Вкратце: всё пишется хорошо.

1. В коробке есть всё, от BSD сокетов до http
2. Отлично, нативные треды, грин-треды, транзакционная память, всё есть
3. Можно, например xmonad.org
4. Честно говоря не знаю насколько удобно, но можно :)
Знание функционального программирования без императивного не имеет ценности. Нужно понимать как в конечном счете работат программа, какая реально получается последовательность действий, оценки количетсва операций, в том числе и асимптотические, понимать в каком случае растет стек, а в каком хип и так далее. В ином случае программа превращается в черный ящик, в котором неведомо что творится. Зачем плодить быдлокодеров?

Я конечно слогласен, что существующие императивне языки слишком неказисты, но новичку нужен хороших императивный язык. И чем Pascal не этот язык? Может просто в штатах этот язык не прижился, и они не осознали, что теряют? :)
Знание функционального программирования без императивного не имеет ценности.

Учитывая, что функциональная программа — лишь парадигма и все равно будет разбираться пошагово и выполняться императивно на уровне процессора.
Конечно, разбираться «с нижним уровнем» надо. ФП — штука крутая, но это уже новый уровень, который лежит поверх императивного, многие вещи там сводятся к тому, что вместо написания императивной программы, пишется функция, котора возвращяет императивную программу, взять теже монады.
<troll_area>
Знание императивного программирования без функционального не имеет ценности. Нужно понимать принципы моделирования процессов, когда можно использовать разделяемое состояние, когда нет. В ином случае реализация модели превращается в бесструктурный фарш, в котором невозможно разобраться. Зачем плодить быдлокодеров?
</troll_area>
А если серьезно, то «разделяемое состояние» — слишком тонкая материя для новичка, так что все же начинать нужно не с этого.
Практиков нужно готовить строго на императивных ЯП.

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

Функциональным ЯП следует оставить математический софт.

Все, срочно переделываем SQL, он же только для математиков!
Правильно, давайте ещё пяток узскоспециализированных DSL вспомним.
Есть какие-то принципиальные возражения помимо «ну-ну»?
Возражение только одно — кроме SQL для БД ничего нет, ну разве что Industrial-D, который реализован в 1,5 базах
SQL это DSL в той же степени, что и ассемблер — DSL для процессоров
С таким подходом DSL считай что и нет (DSL в общем-то и делаются для манипуляции такими «ограниченными» системами как реляционные БД).

На самом деле это свидетельствует ровно о двух вещах:

1. SQL — хороший DSL и ничего лучше не придумали.
2. Реляционные базы не предзнаначены для реализации «в них» софта общего назначения, поэтому и ЯП общего назначения для них не нужен.

Отдельно отмечу такую тенденцию, как встраивание других ЯП в движки баз (Lua, JavaScript), что как бы намекает о сложностях использования SQL в качестве языка общего назначения.

Я бы за компанию и на вики ссылку дал, но вики не авторитет :-)
Контрольный вопрос: вы про SSA что-нибудь когда-нибудь слышали?

Наш мир, сам по себе, императивен — писать приложения для него на функциональных языках — это играть в испорченный телефон, где между императивными входом и выходом вклиниваются фунциональные преобразования, в которых теряется куча информации (императивной).
Увы, увы. Ваш мир остался в прошлом. В 80х годах прошлого века, если точнее. Нет в современном компьютере со всеми его бесконечными кешами и MOESI никакой любимой программистами императивности. Есть «эмулированный мир» на который, как ни странно, функцинальщина ложится лучше, чем императивщина. Вы, может быть не в курсах, но у «испорченного телефона» между «нашим миром» и программистом есть название: компилятор. И подавляющее большинство современных компиляторов транслируют код функционального представления где переменных никогда не меняют значений, значения pure функций могут быть вычислены однократно и т.д. и т.п. Только вот беда: всю эту функциональщину компилятору приходится выуживать из изначально императивной программы. Так где у нас более «испорченный» телефон — в случае, когда изначально всё сделано так, чтобы компилятор всё мог правильно оптимизировать, или где он вынужден выискивать эти возможности хитрыми путями с риском взорвать мозг программисту?

Сам по себе Haskell не является идеальным языком для создания «лёгких» и «скоростных» программ, но вот эффекта испорченного телефона он как раз позволяет избежать. Он, как это ни удивительно, идеологически «ближе» к тому что современные процессоры заточены вычислять. И есть очень серьёзное подозрение, что железо не заточенное под эмуляцию «мира середины 70х» будет реально быстрее и «холоднее», чем существующее. Правда проверить это не так-то просто: отказаться от совместимости с «простым и привычным» миром Фон-Неймана страшно до жути. Но если у нас не будет программистов, способных отказаться от этого мира, то этот переход мы точно никогда не сделаем.
Контрольный вопрос: вы про SSA что-нибудь когда-нибудь слышали?

И каким боком SSA ко всему этому? Оно не исключает последовательное выполнение команд.

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

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

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

Так где у нас более «испорченный» телефон — в случае, когда изначально всё сделано так, чтобы компилятор всё мог правильно оптимизировать, или где он вынужден выискивать эти возможности хитрыми путями с риском взорвать мозг программисту?

Так у нас что, софт для человека или человек для софта? Вы действительно считаете, что человек должен подстраиваться под инструменты? Смешно.

ЯП — это инструмент. Человек живёт в императивном мире, мыслит императивно и действует императивно. С какой стати он должен подгонять себя под неудобные инструменты?

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

Преждевременная оптимизация — зло.
KISS.

Моя позиция по функциональщине вообще не касается её реализации «в железе». Проблема функциональщины в том, что она усложняет работу уже на уровне семантики языка.
Человек живёт в императивном мире, мыслит императивно и действует императивно.

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

Иногда, но не всегда. Кроме того, это часть «планирования», но «реализация» — фактическое подсиание — будет идти всё равно последовательно. И ошибки тут возникнут чисто императивные, например: что делать, если посреди бумаг окажется та, которую подписать нельзя?

В контексте же «планирования» идёт другая императивщина. «Подписать бумаги» нужно обязательно после каких-то действий (например, после того как их затребовали в других местах) и до каких-то действий (до их отсылки). Действительно, «подписать бумаги» — это абстракция над процессом подписывания, но на своём уровне абстракции она используется императивно.
Процесс планирования отлично записывается в виде композиции функций:
Запросить бумаги >> подписать бумаги >> отослать бумаги
бумаги map (_ -> if(можно подписать) Some(подписанная) else None) flatten
или бумаги filter(можно подписать) map (подписать)

Это будет 2n, но зато будет понятнее и нагляднее. Плюс, если это такие уж тяжелые действия, то рантайм это распаралелит.
Это будет о(n+n) и 2n по памяти. Так что в оценке сложности проигрываем только по памяти. Если вы об этом.
Поправьте меня, если я порю чушь, но и filter и flatten потребуют еще одного прохода по коллекции.
Ну я как бы об этом и говорю map+flatten против filter + map. Плюс при оценке сложности асимптотике константы опускаются, так что надо говорить уже об оптимизации самих языковых конструкций без доп.проходов и выделения памяти.
Да, Вы правы.
Короче говоря — лучше помнить, что не надо делать адскую фигню, но первым приоритетом оставлять immutability и читабельность.
Кстати, на тему сложности по памяти, далеко не факт. В случае с filter во время исполнения можно сделать soft copy с прошлой коллекции.
2n по памяти

Почему? Сила функциональщины в лени.
Filter произведет ленивую коллекцию за O(1) — без вычислений над коллекцией.
Map произведет ленивую коллекцию за O(1) — без вычислений над коллекцией.
Потом результаты нужно материализовать, за O(n) памяти можно в любой массив/список положить.
Если вам нужен вообще первый свежеподписанный документ, то никакого лишнего выделения памяти у вас не произойдет — вы просто получите первый элемент с помощью First(). И ваш код будет красивее и лучше пахнуть.
ЯП — это инструмент. Человек живёт в императивном мире, мыслит императивно и действует императивно. С какой стати он должен подгонять себя под неудобные инструменты?

Это Вы мыслите императивно, а не человек. Не надо делать таких смелых утверждений. Мне вот функциональное программирование кажется ближе, а ваши аргументы про «неудобные» инструменты смешными. Функциональное программирование и создавалось, как инструмент для решения конкретных задач, а не плясок вокруг синтаксических примудростей как в современном C++.
а не плясок вокруг синтаксических примудростей как в современном C++.

Не путайте конкретную реализацию с абстрактной идеей. Это вредно.

Опишите как вы функционально планруете покупки.
Я императивно покупки тоже не планирую, если вы об этом. Как и функционально. У меня есть список покупок, но нет четкой последовательности действий. Но алгоритмы именно из идеи воплощать в код проще на функциональном языке, и я сейчас говорю только про себя. It's all about this, воплотить алгоритм в работающий код. А как там думает человек, я не знаю. Я знаю, что те алгоритмы и те абстракции, которые у меня возникают в голове, проще писать на функциональном языке.
С какой стати он должен подгонять себя под неудобные инструменты?

Давайте ещё матан выкинем и оставим только выч.методы.
А матан — удобный инструмент. С ним удобно решать задачи матана, как ни странно.

Но я не буду использовать его при готовке, например, бутерброда. Потому что его будет неудобно для этого использовать.
Если матан удобен для решения задачи — почему его не использовать для этого?
Если ФП удобно для решения задачи — почему его не использовать для этого?

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

Согласен, но если говорить о выборе инструмента обучения, уместно говорить о статистике. Если большинству человек удобна парадигма Х, то ей и стоит учить.
Я бы согласился, если бы не одно но: никакой статистики, из которой можно заключить, что большинству людей удобнее парадигма Х нет: если изначально учат парадигме Х, в индустрии используется в основном Х, то человеку будет «удобнее» Х. В кавычках только потому, что человек ничего кроме этого не знает. А если преподавать и «Х» и «Y», а затем (для начала пусть в сферической вселенной в вакууме) предоставить выбор, что использовать для задачи — далеко не факт, что человек выберет X.
никакой статистики, из которой можно заключить, что большинству людей удобнее парадигма Х нет

От того и holy wars :-)
Что делает компилятор внутри себя, с точки зрения прикладного программирования, не имеет значения — он делает это без участие человека и его работа не несёт никаких сложностей с точки зрения, например, формализации бизнес-логики.
Вы уж определитесь: вам не нравится «испорченный телефон», либо «что там делает компилятор меня не волнует». В первом случае таки SSA имеет прямое отношение к происходящему, во втором — вас совершенно не должно волновать что там происходит с ячейками памяти, а гораздо важнее то, что что «бизнес-логика» как раз выражается вполне себе функциональным языком. Если вы почитаете любой договор или закон, то у вас нигде не возникнут переменные, меняющиеся со временем. Наоборот, у вас будут многоуровневые понятия близкие к математике и функциональным языкам, а вовсе не к императивному программированию.

Императивное программирование и ООП, в общем-то, естественным образом возникает только при программировании UI. Но как-то глупо сводить всё программирование к программированию UI. Да и там сейчас всякие атомы в фаворе, которые к «чистой императивности» имеют очень отдалённое отношение.

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

Человек живёт в императивном мире, мыслит императивно и действует императивно.
Это смотря какой человек. «Условный таджик», которого вы наняли вскопать огород таки мыслит и действует императивно. Архитектор, учёный, да даже квалифицированный бухгалтер — мыслят в других понятиях. В основном — описываемых математически. Какой-нибудь «остаток денег на счёте» — это «разница между доходами и расходами», а вовсе не «результат выполнения 1000 раз инструкций «добавить приход к остатку или вычесть расход из остатка»». Ну и далее — вопрос: таки мы разрабатывает ЯП для дворников или авиаконструкторов?

Моя позиция по функциональщине вообще не касается её реализации «в железе». Проблема функциональщины в том, что она усложняет работу уже на уровне семантики языка.
Странная позиция. Давайте рассмотрим предметно: вот тут вам показали как выглядит быстрая сортировка на Haskell'е. Покажите мне «упрощение работы» переписав эту сортировку на любой императивных язык — будет о чём говорить. Да и вообще — покажите решение любой задачи, которое будет на имперетивном языке проще и понятнее, чем на Haskell'е. Только без использования библиотек и встроенных конструкций языка: понятно, что если у вас что-то в один язык встроено, а в другой нет, то в первом языке оно будет «проще».

Я видел много возражений против «функциональщины», но почти всегда они сводились либо к тому, что «оно очень плохо на железо ложится» (тут можно спорить, но от этого довода вы, как я понял, уже отказались, так что забудем), либо «оно усложняет работу потому что я в этих закорючках ни черта не понимаю». Что тоже бред: так мы дойдём до того, что начнём для счёта зарубки использовать. А то, понимаешь, придумали всякого: позиционное исчисление, переменные всякие, кто ж со всем этим совладает?
Да и вообще — покажите решение любой задачи, которое будет на имперетивном языке проще и понятнее, чем на Haskell'е.
Напишите очередь. Только, пожалуйста, так, чтобы pop и push стоили O(1), а не O(n). Ну и использовать стандартную библиотеку, где она наверняка реализована, тоже нельзя, конечно.
1. Есть Okasaki's queue, которая в среднем O(1). Отдельные операции могут выполняться за O(n), но они встречаются не чаще, чем одна на n операций.

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

По поводу вашего телефона я уже высказался, не подменяйте понятия. У меня другой телефн )

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

Императивный код тоже может не содержать переменных, меняющихся со временам. Это не показатель функциональщины.
Зато признак императивщины — это изменение состояния объектов (не переменных). Закон, например, не описывает что в момент времени t у нас есть юр.лицо Xi в состоянии f(t), а в t+1 — юр. лицо Xi+1 в состоянии f(t+1). Закон описывает изменение одного и того же юр. лица.
Законы и договора декларативны, но описывают они императивную модель, а не функциональную.

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

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

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

1. крадём носки
2. ?????
3. профит

Какой-нибудь «остаток денег на счёте» — это «разница между доходами и расходами», а вовсе не «результат выполнения 1000 раз инструкций «добавить приход к остатку или вычесть расход из остатка»»

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

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

И ещё раз повторю, что функциональщине вполне можно отдать математику.

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

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


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

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

QuickSort без использования дополнительной памяти?
Наш мир, сам по себе, императивен
А вот народная мудрость с вами не согласна
В одну реку нельзя войти дважды
Моё мнение, что начинать обучение надо с теории, самые азы, чтобы стало понятно что и для чего нужно. Потом перейти на что-то, что будет наглядно показывать результат «программирования», т.е. что-то где вписывают псевдокод и получают наглядный и красивый результат выполнения. И потом опять теория и опять псевдокод. А как только станет понятно, что псевдокода уже недостаточно, то надо переходить к реальным языкам программирования (личный пример, я начал изучать программирование в 12 лет, нас не планировали обучать именно языку программирования, но после того как мы сами попросили нам изменили программу обучения и дали VB).
А вообще языка программирования — это просто языки, как русский, китайский, английский, португальский и т.д. которые позволяют решать определённые задачи. Нужно эту мысль вложить в головы обучаемых, чтобы они учили подходы и алгоритмы, а языки были к этому дополнением, которые показывают конкретную реализацию выбранного подхода.
А вот именно заинтересовать по принципу «клац сюда клац сюда и получилось приложение в app store» — это мне кажется плохо, потому что юное дарование уже не захочет больше ничего другого разбирать. Нужен правильный подход к обучению.
И ещё, как говорили мне пои учителя: «К обучению программированию нужен индивидуальный подход, потому что все вы разные и у вас разный уровень». Хотя бы в начале так надо подходить чтобы всех вытянуть на нужный уровень понимания.

P.S. у меня в вузе на 1м курсе после немножечко Pascal был сразу Assembler. Никто вообще не понимал что происходит, одногруппники просто пытались изменить пример так, чтобы он выдал то, что требуется в задаче и всё, остальное было всем безразлично, потому что не правильный подход.
Хорошей причиной выбора функционального языка программирования в курсе для новичков является то, что большинство студентов немного знакомы с императивным программированием. Увидев новизну функционального программирования, они понимают, что программирование шире, чем они думали. И студенты довольно быстро замечают элегантность функционального подхода для решений, которые очень сложно (или невозможно) сформулировать знакомыми им со школы инструментами.
Ну и где тут хаскель «первый язык»? Как минимум второй.
Начинать нужно с языка, который:
1. Имеет небольшой багаж архитектурных проблем.
2. Позволяет быстро переходить от кода к работающей программе.
3. Мультипарадигменный.

(1) — Это означает, что обучающийся будет мыслить в терминах некоторых здоровых концепций, а не бороться с конкретными проблемами конкретных языковых сред.
(2) — Это означает, что можно проводить быстрые итерации в разработке (что-то поменял, запустил, посмотрел) без необходимости настраивать окружение, разбираться с тонкостями компилятора. Это позволяет увидеть результат быстро и поддерживает внимание ученика на том, что он делает.
(3) — Если язык позволяет мыслить в нескольких парадигмах, то обучение на нём также можно проводить сразу по нескольким парадигмам. При этом не придётся каждый раз выделять часы на вводный курс по синтаксису, компилятору/интерпретатору.

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

Намного более интересным вопросом я считаю «Что использовать в качестве второго языка для обучения». При условии, что если первый язык был выбран верно, конечно. Лично я считаю, что тут можно двигаться сразу в двух направлениях:
1. Эффективные типизированные языки. В начале курса заглядываем под капот того же Питона и видим громадный оверхед на все действия. У ученика возникает естественное желание более эффективно использовать данные нам столь мощные железки. Переходим к изучению строгой типизации, времени жизни, вывода типов, деструкторов, обобщённого программирования. Языки: современный C++.
2. Предельно гибкие языки. Тут мы подводим ученика к вопросу где проходит грань между синтаксисом, кодом и данными языка на примере какого-нибудь диалекта Lisp. Хорошим вариантом будет Scheme или Clojure.
Она настолько плох, что вся индустрия в целом принимает низкокачественный дизайн как стандарт де факто.
Дейкстра зрел в корень проблемы ещё в далёком 2001-ом.
Судя по тому что мнения сильно расходятся, нельзя просто взять и выбрать один подход. То что хорошо подойдет для одного обучаемого, может быть неприемлемо для другого. Поэтому вывод напрашивается сам собой — Преподавать курс императивных языков для быстрого старта с параллельным курсом функциональных языков, где уже подробно разбираются алгоритмы, структуры, возможно еще что-нибудь низкоуровневое в рамках курса, либо в рамках параллельного третьего.
Тоже не совсем верно, нужно понимать свою аудиторию. Нужно понимать кому и что ты хочешь донести, какой базовый уровень подготовки, насколько аудитория мотивирована для получения новых знаний. И опять же на первых порах — давать слишком много, тоже плохо. Плохо потому что если что-то ляжет не так, то у кого-то в головах такая каша может начаться, что потом её никак не расхлебать.
Что-то можно попробовать давать в рамках «послушать для общего развития», а потом позже уже дать на настоящем серьёзном уровне, когда обучаемые будут готовы. Если кто-то в рамках «послушать» что-то не понял, то и не страшно, потом уляжется.
На ВМК МГУ первый месяц вообще на бумажке пишут программы для машины Тьюринга и нормальные алгоритмы Маркова.
а потом учили абстрактный ассемблер. Трехрегистровые АЛУ, двухрегистровые, однорегистровые…
Имхо надо начинать с декомпозиции, затем параллельно вводить понятие алгоритмической сложности, чтобы показать что декомпозиция может быть как эффективной так и нет. Затем можно рассмотреть структуры данных и абстракции. Язык в данном случае особой роли не играет. Не надо изобретать велосипед, за нас уже все написали. «Структура и интерпретация программ» — вот с чего надо начинать обучение программированию.
ага, а арифметике надо учить начиная с определения кольца по сложению, затем параллельно вводить поля Галуа и можно рассмотреть вычеты по модулю.
А что, неплохо. Мне нравится. Вы ещё теорию множеств забыли :)
Не, теория множеств это лишнее. А вот без трех способов введения вещественных чисел никуда не денешься, это азы.
Ну целые числа вы же будете вводить, раз у вас конечные поля и вычеты по модулю? Значит вам нужны азы теории групп и теории множеств.
UFO just landed and posted this here
Я бы сказал, что начинать нужно с двух вещей сразу: с базовых алгоритмов на простом языке типа Pascal и спустя некоторое время добавить низкоуровеный язык, чтобы будущие программисты знали и понимали, как всё работает
Обучение программированию с любого языка можно начинать.
Показать, что можно написать «a=5», а потом «print a».
Потом показать что можно запросить 2 цифры и вывести их сумму. Таким образом можно сделать свой калькулятор.
Потом показать работу с графикой (точки, цвета, примитивы). Таким образом можно рисовать на экране.
Потом показать работу с клавиатурой (опрос нажатых клавиш). Таким образом можно сделать управление программой.
Потом показать циклы, условия. Таким образом можно опрашивать клавиши в бесконечном цикле, и делать что нибудь (двигать ГГ на экране) в зависимости от нажатой клавиши.
Потом показать массивы и их использование для хранения и отображения какой нибудь 2-мерной карты игрового поля. Таким образом можно сделать игру, где ГГ ходит по карте по нажатию клавиш, и, например, по земле ходит, а в речку зайти не может.
А потом сказать что есть еще куча готовых модулей, которые облегчат загрузку графики, будут играть музыку и звуки, отображать 3D и т.д.
Главное — заинтересовать человека.
Если ваша цель — создать очередного быдлокодера, которые порождает глючные поделки путём гугления на stackoverflow, то да — такой подход годится. Если вы хотите научить человека писать качественные программы, то — нет, увы. Это, кстати, не говорит, о том, что Дейкстра прав: быдлокодеров нужно больше, чем людей, умеющих прилично программировать (они дешевле, а с возложенными на них задачами справляются). Топик стартер про это уже говорил.
А «приличный программист» не может в личиночной стадии быть «быдлокодером»?
Это вообще разные навыки. Примерно как автомеханик и автоконструктор. Первому важно быстро махать инструментами и знать про номенклатуру выпускаемых деталей, второму — нужен сопромат и куча других специализированных знаний. Кстати быстро махать гаечным колючем автоконструктор может и не уметь.
Аналогия понятна. Осталось понять, как соотносятся множества «автомехаников» и «автоконструкторов» (кого больше и как велико пересечение) и насколько прост переход между ними.
А какое это вообще имеет отношение к обсуждаемой теме? Автомехаников ВУЗы не готовят, для этого есть техникумы, ПТУ и т.д. и т.п.

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

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

Поэтому надо начинать не с языка, а сразу с конечной цели — «зачем» (под пк, под мобилы, для интернета, для контроллеров). А потом уже выбирать для желаемого направления язык. И то не факт, что обучаемый в процессе освоения не попробует перепрыгнуть на другой язык (если изначально будет выбран труднопонимаемый язык) или не забросит вообще это дело.
Вот не думал, что Дейкстра холивар затеет!
Какой искусственный язык выбрать, чтобы обучится программированию наилучшим способом? Наверное тот, на котором вы собираетесь
«разговаривать» и дальше. В этом смысле, искусственный и естественные языки похожи: не будешь разговаривать — быстро забудешь. Если же вы не собираетесь посвятить свою жизнь программированию, то все равно лучше изучить императивный язык, так как это развивает способность к алгоритмическому мышлению. Другого шанса в университете не будет (сейчас уже и численные методы в мат. пакетах изучают)
С Машины Тьюринга надо начинать…
Я начинал с JavaScript (10 лет назад) и очень доволен. Порог входа низкий, школьникам самое то. Можно программировать как в объектно-ориентированной, так и в функциональной парадигме. Можно самим реализовывать наследывание, события и многое другое, для обучения будет полезно. Плюс развившись дополнительно они смогут писать сайты, нативные приложения под Windows 8/10, и с помощью cordova кроссплатформенные приложения под Android, iOS, Blackberry, Amazon OS и др… Плюс не будут ругать JavaScript когда станут взрослыми.
так и в функциональной парадигме

Не больше чем в python.

Плюс не будут ругать JavaScript когда станут взрослыми.

А зря, у языка много ошибок в дизайне и это вроде уже не опровержимый факт. Все языки имеют свои проблемы и JS не самый плохой, но всё же не без ошибок. Короче ругать надо, есть шанс, что исправиться. :)
UFO just landed and posted this here
Зря Вы так про монады и функторы. Это же элегантные шуроповерты, вместо стандартных отверток.
Я за подход «начинать с основ теории алгоритмов и параллельно с чего-нибудь императивного», то бишь комплексный подход. Причем не с того, о чем выше пишут в комментариях — о самих алгоритмах и их оценках, а именно с теории алгоритмов — вычислимости функций, процессов Хоара, мб других формализмов для кругозора. Всякие сортировки, обходы графов и т.д. — дело наживное. У самого сначала были структуры данных и алгоритмы + C/C++, а уже потом теория алгоритмов и понимание, почему это все так и откуда берется — хорошо ставит мозг на место. Но комплексный подход все же будет лучше, чем последовательно с перерывами эти вещи изучать.
«что лучше: как можно быстрее научить созданию простых приложений без реального понимания программирования, алгоритмов и их вычислительной сложности, а потом начать знакомство с этими важными темами, или начать «с начала», и органично придти к созданию приложений и продуктов после освоения фундамента.»

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

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

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

Тут надо понимать что в практике всегда присутствует теория и если в начале семестра рассказывать только про for, а в конце дать весь список repeat, while и goto, то мы, лишая ученика общей картины, теряем 6 месяцев творческого режима. Всегда можно дать полное знание, а спрашивать только начальное, если хотим пожалеть ученика, но только этим всем заниматься надо аккуратно и как следует, а не с важным видом захламлять детям головы.
Начинать нужно с определения зачем вообще обучение программированию нужно в конкретном случае.
Всегда был уверен и остаюсь верен идее о том, что программированию не нужно начинать учить. Программированию нужно начинать учиться. Программирование — очень прикладная дисциплина. И начинать ей учить нужно параллельно в четырех ипостасях этой дисциплины. Раньше компьютеры, операционные системы и периферия были очень примитивны и требовалось начинать с понимания того, что это вообще, как работает и чего можно добиваться программируя конкретную железяку.

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

Какие четыре ипостаси программирования я имею в виду?
1. Понимание роли «софта» в современной инфраструктуре, какие принципы программирования устройств вообще, понимание разнообразия устройств и всевозможных сред их взаимодействия
2. Умение проектировать информационные системы (и алгоритмы, и интерфейсы взаимодействия, и структуры данных)
3. Умение изучать и разрабатывать документацию и взаимодействовать с уже написанным ранее кодом
4. Владеть современными и овладевать перспективными инструментами по всему жизненному циклу ПО, знать и понимать историю их возникновения, развития, основные тренды и настроения «в массах» и «в элитах», преимущества, недостатки и осознавать возможности, трудности, препятствия и риски применения разных инструментов

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

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