Неспешно читаю-решаю упражнения из SICP. Дошел где-то до середины книги, так что могу написать какое-то более развернутое мнение.
Начну с плюсов. Как недавно заметил
infowatch, в «околокомпьютерных» областях достаточно велико количество самоучек, а «официальные» учебные планы зачастую неадекватны — следовательно, любой более-менее приличный «компьютерщик» в той или иной степени оказывается «самоучкой». Недостатки такого подхода очевидны — нет «систематичности» знаний и «единой картины мира».
Вообще, складывается такое впечатление, что отечественное программирование во многом представляет собой некий «карго-культ», копирующий внешние стороны такового в США. Кто-то рассказал про интервью при приеме на работу в Google и Microsoft — и все-все-все, включая распоследнюю «веб-студию», бросаются спрашивать про сортировку и красно-белые деревья. То, что когда-то эти вопросы позволяли Google и Microsoft набирать исключительно студентов-отличников ведущих американских ВУЗов — в расчет не принимается. Аналогичное впечатление производят и учебные планы — например, вопросы, связанные с индуктивными вычислениями и прочей рекурсией явно заимствованы из курсов с использованием Lisp наподобие SICP. На «традиционных» у нас C и Pascal они выглядят довольно дико. В общем, самоучки учат самоучек.
Что делать в такой ситуации? Наверное, лучше всего «забить» на попытки Рабиновича напеть Паваротти и «самоучиться» по первоисточникам — тем более, что ситуация с ними сегодня лучше, чем десяток лет назад. Например, SICP достаточно неплохо переведена, и теперь не придется вычленять «разумное, доброе, вечное» из кривого пересказа. Не надо «плеваться» от того, что эта книга — всего лишь «вводный курс» программирования. В свое время, например, кто-то обратил внимание на возраст присутствующих в аудитории на видеолекциях (в интернете выложены видеозаписи лекций по этому курсу) — и там было немало вполне взрослых людей, возможно даже и с опытом работы.
Более того, из-за особенностей применяемого диалекта Lisp, в SICP уже в конце первой главы переходят к вполне содержательным задачам — то есть демонстрирующим не какие-то конструкции языка, а различные подходы к программированию. Это отличает ее от других «вводных курсов», где берется какой-то язык программирования (раньше дико модным был Pascal), подробно изучаются его конструкции, а из «программирования» до обучающихся доводится лишь одна истина — что, оказывается, можно набрать на клавиатуре какой-то текст, затем нажать нужные кнопки и компьютер волшебным образом выполнит то, что хотел программист.
Что меня особенно удивило — я ни разу не видел более краткого описания ООП, чем один-единственный абзац в SICP (в начале 3 главы):
Существует мощная стратегия разработки, которая особенно хорошо подходит для построения программ, моделирующих физические системы: воспроизводить в структуре программы структуру моделируемой системы. Для каждого объекта в системе мы строим соответствующий ему вычислительный объект. Для каждого действия в системе определяем в рамках нашей вычислительной модели символьную операцию. Используя эту стратегию, мы надеемся, что расширение нашей модели на новые объекты или действия не потребует стратегических изменений в программе, а позволит обойтись только добавлением новых символьных аналогов этих объектов или действий. Если наша организация системы окажется удачной, то для добавления новых возможностей или отладки старых нам придется работать только с ограниченной частью системы.
Между прочим, волшебные слова «инкапсуляция, наследование и полиморфизм» в книге не встречаются ни разу. В любой «нормальной» книжке утверждается, что якобы они и составляют так называемое «объектно-ориентированное программирование» (которого не существует — но это отдельная тема), а здесь удалось обойтись вообще без них.
Разумеется, что все рассматриваемые в SICP подходы к программированию можно показать и с использованием других языков. Например, встречаются решения задач оттуда на Common Lisp (это, правда, не считается — так как он все равно достаточно близок к Scheme), Python, Javascript и даже на C# — в общем, «на чем угодно». Правда, ни один из этих языков (за исключением, разве что, Common Lisp) не подходит для того, чтобы продемонстрировать все эти подходы сразу.
Теперь к недостаткам — благо «хвалебных» отзывов о SICP и без меня предостаточно. Можно было бы начать с классического «Не покупайте эту книгу«, но у меня к SICP другие претензии. Меня, как математика, поражают вольности с численными методами. Любой программист считает себя непревзойденным специалистом в этой области — но это далеко не так. Не последнее место в формировании этого заблуждения занимают книги по программированию, в которых численные методы рассматриваются в отрыве от их «содержания», как обычные алгоритмы.
Например, в главе 1.3.1 приводятся формулы численного интегрирования, и утверждается, что «определенный интеграл … можно численно оценить с помощью формулы» («the definite integral … can be approximated numerically using the formula «) — при этом не раскрывается ни законность этой оценки (что можно «простить»), ни ее точность. Правда, вычисляются два приближения для одного интеграла, меньшее значение переменной dx соответствует большей точности — и только! В упражнении 1.29 приводится формула Симпсона, утверждается, что она представляет собой «более точный метод численного интегрирования» (в чем эта точность заключается — не объясняется), а затем предлагается проинтегрировать с ее помощью кубический многочлен — якобы это должно «доказать», что она «более точна». Удивительно, но результат оказывается ближе к истинному значению — но это не сходимость, как в первом случае, а просто свойство формулы Симпсона — она дает точное значение при интегрировании кубических многочленов.
Чуть дальше появляются более «страшные» вольности. Например, в «определении» производной (оно необходимо для метода Ньютона) предлагается заменить стремящееся к 0 dx каким-то «очень малым» значением. Сказать, что это приближение, видимо, религия не позволяет.
В конце раздела 1.3 находим упражнение 1.45 — от которого я пришел в ужас. Сообщается, что метод Ньютона не работает для некоторых функций, например, для извлечения корня n-й степени. Предлагается использовать многократное «торможение усреднением» (average damping — этот термин я не встречал нигде, кроме SICP), а «кратность» его применения установить — держитесь — экспериментально! Да, читатель SICP, скорее всего, не сможет доказать полученное утверждение — но предложение «экспериментально» доказать математическое утверждение, согласно современным представлениям, дико само по себе. Может, не стоит вообще давать такие задачи?
Практически весь раздел 1.3 посвящен численным методам в том или ином виде — и везде есть какие-то «косяки». Да, большинство читателей их не заметит — но здесь я не могу разделять их восторгов по поводу книги. Тут требуется несколько более высокий уровень строгости в изложении. В целом книга крайне хороша с «программистской» точки зрения, но как только речь заходит о математических вопросах — то начинается «тушите свет, сливайте воду». Численные методы — хорошая демонстрация для абстракций, связанных с использованием «функций высших порядков» (для которых, правда, в математике придуманы свои термины — например, «функционал» или «оператор»), но они требуют все же несколько другого подхода.
Продолжение, как говорится, следует.






