Я прекрасно помню мозголомные моменты в моей программистской деятельности.
В своё время (очень давно) мне казалось что узнав бейсик, паскаль, фокал и ассемблер для ВМ80 а потом уже и Z80, я неимоверно крут и всё знаю :)
И каким разрывом шаблона для меня обернулось изучение языка C. Хуже всего это то, когда ещё пока весь в старых методиках, с определённым образом устроенными мозгами, начинаешь изучать новые.
Какими кривыми были мои первые подуги на C. Это по сути были те же программы на бейсике, только слегка с другим синтаксисом :)
В то далёкое время нормальных книг ещё не было, интернета не было и подавно. И приходилось изучать по чудом достававшимся урывкам.
Потом была пора изучения объектно-ориентированного программирования. C++ не пошёл сразу. Я купил по нему целых 3 неудачных книги. То, что они неудачные, я понял потом. А пока мне казалось, что язык уж слишком сложный.
ООП я понял из замечательной книги по java, тогда ещё 1.0 Патрика Нортона, одного из создателей.
Потом аккурат подоспел и C++. Я просто тут не упоминаю кучу промежуточной практики, которую постоянно приходилось делать.
Всякие скриптовые языки типа перла, где не надо думать про типы данных, арифметику указателей и выделение/освобождение памяти казались манной небесной. Это сейчас современное поколение, не любящее перл и считающее его извращением, слишком нежное.
Последним переломным моментом стало изучение функциональных языков типа Хаскеля и Лиспа. Не столько их самих, сколько заложенные в них понятия работы со списками и рекурсии.
Вот где начинается настоящий когнитивный диссонанс! Это когда все твои предыдущие представления о программировании следует выбросить на помойку и открыть для себя новые истины. Ну, тут я, конечно, утрирую мальца.
Жизнь не позволит никому летать в облаках чистой функциональщины при наличии вполне себе земной аппаратуры. Хотя для собственного развития это существенный прогресс. Две мощные ступеньки: отношение ко множеству как к одной меняющейся сущности (не пытайтесь это понять с ходу, сломаете мозг) и вы ражение сущности через саму себя (рекурсия) для обработки множества.
Я помню, как коллеги на новой работе матерились по началу на такие конструкции перла как map и grep. А это ведь всего лишь простенькие функциональные паттерны, которые как-то облегчают тяжёлое бремя циклов.
А вот пример пользы понимания рекурсии. Ранне мне с моими "бейсичными" знаниями задача по обходу дерева показалась бы сверхзапутанной и заумной. Разумеется, в старых понятиях описать подобные процессы довольно тяжко и громоздко.
Представьте себе дерево, состоящее из узлов. Узел имеет 2 ответвления: левое и правое. На каждом ответвлении сидит такой же узел или оно пустое. Требуется узнать высоту дерева то есть, максимальне количество узлов от корня и до последнего узла. То есть длину самой длинной ветки от корня.
-- Описываем рекурсивный тип данных
-- состоящий из узла левого и правого
-- ответвления аналогичной сущности
-- Или этот весь параметр равен Empty
data Three a =
Node a (Three a) (Three a)
| Empty
deriving (Eq, Show)
-- Определяем функцию
-- Первый паттерн на случай попадания на Empty вместо полноценного узла
thigh l
| l == Empty = 0
-- Тут единица прибавляется к максимальному значению
-- прохода по первой и второй ветке
-- Пустые ветки не учитываются, а в конце выбирается
-- максимально дляинная ветка от корня
thigh (Node a left right) =
1 + max (thigh left) (thigh right)