Тьма невежества

В ЖЖ [info]nicka_startcev обсуждаем функциональное программирование и его «место под солнцем». Вспомнилась другая дискуссия, которую я однажды упоминал — там фигурировала несложная (для понимающих прикол) задачка, которую штатные форумные мегапрограммисты пытались решить известными им методами. Разумеется, никто ее не решил и даже толком не понял, что же там требуется. Хочу изложить тут несколько своих и не своих мыслей, которые в этом контексте оказываются довольно интересны.

Как обычно построено изучение языков программирования (в России)? В самом первом приближении оно выглядит так: в школе изучается КуМир или Pascal, в ВУЗе — сначала Си, затем Си++. Некоторые маньяки предлагают начинать с ассемблера, а Си — только после него. Кое-кто придерживается мнения, что Си надо забыть, как страшный сон, и начинать с Java.

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

Что получается в результате? Где-то я встречал идею упорядочить языки программирования по их «мощности». Язык B мощнее языка A, если позволяет легко записать нетривиальную для A операцию. Например, C мощнее Pascal, так как допускает запись произвольных операторов в конструкции for. Применение? Проход по связному списку «в одну строчку». С++ — мощнее C (классы и прочие извращения).

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

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

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

PPS Я не ошибся, когда назвал Javascript «более мощным», чем C и Pascal. Вышеприведенное определение «мощности» не связано со скоростью работы программ, с близостью к «железу» и прочими параметрами, которыми сишники и ассемблерщики гнобят остальных.

Тьма невежества: 8 комментариев

  1. function x(real a, real b) { if (a) { return a; } else { return b; } }
    #define x(a,b) (a)?(a):(b)

    или я задачу неправильно понял, и тут подразумевалось что-то из серии eval()?

      1. ну я по наивности своей исходил из математических выражений, что 2+2=4, сколько раз его ни вычисляй
        если же под «выражением» подразумевать именно выражение ЯП, т.е. с вызовом функций и прочая, то тогда да…

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

          1. > свойство идемпотентности не обязательно присуще любой функции даже в математике

            Чего? Как нас учил на первом курсе А. Г. Кушниренко (сопровождая это страшилками — мол, спросят вас это на госэкзаменах, а вы все забыли, чему на первом курсе учили), «функция — это тройка: множество X — область определения, множество Y — область значений, и некоторое подмножество декартова произведения X*Y, удовлетворяющее таким-то свойствам».

            Вопрос: и как при таком определении может отсутствовать «свойство идемпотентности»?

    1. см. eval

      Не самое «изящное», но идея понятна. Изящное решение бывает в языках с настоящими маркосами — Lisp, IBM High Level Assembler

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *