Смекни!
smekni.com

Языки, которые мы потеряли (стр. 2 из 3)

ООП в ретроспективе

Многие языки, возникшие задолго до появления термина ООП (например, уже упомянутый Лисп), вполне отвечают его критериям, возможно, даже в большей степени, чем «чистокровные» представители ООП, такие как Си++ или его прямые предшественники Симула (Simula) и Смолток (Smalltalk), созданные в 1967 и 1980 году соответственно. Кстати, о предшественниках. Язык Си++ часто критикуют за то, что обращение к методу класса в нем реализовано как вызов функции, в то время как Симула и Смолток позволяли объектам обмениваться сообщениями. Сторонники Си++ утверждают, что конкретный способ вызова метода класса - внутренняя кухня языка, скрытая от программиста и что посылка сообщения является частным случаем вызова функции, только прямой вызов намного более эффективен в плане накладных расходов и машинных затрат на такты и оперативную память.

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

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

Полезныессылкипотеме

Why Pascal is Not My Favorite Programming Language

Аналитическая статья Брайна Керигана - одного из создателей языка Си - критикующего недостатки Паскаля, устраненные в Си, но заново возрожденные в Си++ и его потомках (на английском языке): www.lysator.liu.se/c/bwk-on-pascal.html

433 Examples in 132 (or 162*) programming languages

Исходные коды 433 простых программ («hello, world», факториал, поиск максимума, пузырьковая сортировка, etc) на 162 различных языках программирования, как существующих, так и давно умерших, - очень полезная штука для расширения кругозора (на английском языке): www.ntecs.de/old-hp/uu9r/lanq/html/lanq.en.html

List of hello world programs

Исходные коды «hello, world» программ на 190 языках программирования: http://en.wikibooks.Org/wiki/Transwiki:List of hello world programs

Эволюция программистов и языков программирования (шутка) www.ariel.com.au/iokes/The Evolution of a Programmer.html

Самомодификация в законе

В Лиспе (Lisp) и Форте (Forth), созданных в 1958 и 1970 годах соответственно, самомодификация была вынесена на уровне языка, что позволяло реализовывать высокоэффективные программы, построенные на динамических алгоритмах. Уникальнейшей особенностью Форта (не реализованная ни в каком другом языке) была и остается возможность «честной», модификации Форт-машины, то есть непосредственно самого транслятора, который при желании со стороны программиста можно вообще полностью переписать штатными средствами самого языка!

В Фортране, Алголе, Паскале, Си/Си++ и прочих «хороших и разных», клонах (включая Бейсик) самомодификация возможна лишь теоретически - путем варварской правки машинного кода в оперативной памяти. Почему «варварской».? Да потому, что язык к этому не имеет никакого отношения, более того, самомодификация опирается на недокументированные возможности языка, закладываясь на логику конкретных трансляторов, что чревато развалом программы при переходе на другой компилятор, не говоря уже о том, что машинный код - штука понятная лишь небольшому кругу избранных, но даже Великий Гуру не сможет написать самомодифицирующуюся программу, работающую более чем на одном процессоре. В конечном счете, самомодификация попала в черный список дурных приемов программирования, а сами программы «распались», на код и данные, обрабатываемые этим кодом, инвариантным по отношению к самим данным. Другими словами - один и тот же код обрабатывает разные данные, что не есть правильно. Машина Тьюринга вообще не имела таких понятий. В ней код был неотделим от обрабатываемых им данных. Вернее, поступающие данные задавали методы их обработки (естественно, в рамках заложенных в машину алгоритмов).

К счастью, в последнее время предпринято несколько попыток реабилитации самомодификации. Во-первых, это Java со своей виртуальной машиной, байт-код которой не меняется от процессора к процессору, а, значит, самомодификация не ухудшает переносимость программы (правда, если быть честным, Java не предоставляет для самомодификации никаких языковых средств и программисту приходится работать с низкоуровневыми командами чтения/записи памяти). Во-вторых, Си++, Nemerle и RW поддерживают (и активно продвигают) парадигму метапрограммирования, позволяя писать программы, создающие другие программы, которые в свою очередь создают третьи... Это, конечно, не совсем самомодификация, но нечто на нее похожее. Однако, реализация метапрограммирования крайне тяжеловесна, логика и синтаксис - запутаны, сложны для понимания и абсолютно непрозрачны, а возможности существенно уступают Форту и Лиспу. В общем, муть и мрак.

Вавилонское столпотворение

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

Сам по себе язык в отрыве от среды программирования —малоинтересен, да и все языки крутятся вокруг одного и того же набора концепций и парадигм, просто разные языки смешивают этот коктейль в различных комбинациях. Популярность Си++ отчасти вызвана тем, что он вобрал в себя все существующие парадигмы, допускающие эффективную реализацию. Остальные языки либо неэффективны, либо представляют собой подмножество Си++. Да, есть совершенно иные классы языков, в частности логические языки (ярким примером которых является Prolog), основанные на выводе новых фактов из заложенных в них данных согласно установленной системе логических правил, работающей в замкнутом мире фактов. Другими словами, если определить объекты «вода», «чайник», «газ», «огонь», то Prolog'y достаточно дать задание «вскипятить воду», чтобы он поставил чайник на огонь. Но... насколько же медленно он это сделает! И сколько времени уйдет на формирование «базы знаний» об объектах окружающего мира. В отличие от Си++, придерживающегося парадигм декларативного программирования, описывающих процесс вычисления в виде инструкций, изменяющих состояние программы, функциональные языки (самый популярный из которых Haskell) не представляют собой последовательность инструкций и не имеют глобального состояния, вместо этого они определяют, что нужно вычислять, а как это делать—забота транслятора. Вот только эффективных трансляторов декларативных языков упорно не наблюдается. Увы, машина не может мыслить, а ответ на вопрос «как это сделать?» предполагает активную творческую деятельность. Таким образом, благополучию Си++ ничего не угрожает. Сколько бы языков ни создавалось и какие бы усилия ни предпринимались для продвижения их на рынок, мы получим либо урезанный вариант Си++, либо страшный тормоз. Ни то, ни другое программистам даром не нужно. Разумеется, это не означает, что Си++— венец эволюции. Скорее, это свалка всех идей, демонстрирующих хорошую эрудицию его создателей, но нарушающих целостность языка, из-за чего, собственно, с завидной регулярностью появляются «претенденты на престол», пытающиеся отобрать лучшие из конструкций Си++, скомпоновав их в гармоничный «букет», но... новые языки приходят и уходят, а Си++ вбирает в себя все удачные решения своих конкурентов, становясь целым миром. И навряд ли найдется хоть один вменяемый программист, который осмелится утверждать, что он владеет этим миром во всей его полноте. Максимум на что он может претендовать — на ту малую часть, которую вмещает ум отдельно взятого индивидуума.