ГЕДЕЛЬ, ЭШЕР, БАХ: эта бесконечная гирлянда.
Сравнения между программами на высшем уровне.
Уивер имел в виду переводы с одного человеческого языка на другой. Давайте теперь рассмотрим проблему перевода между компьютерными языками. Предположим, что два человека написали программы для разных компьютеров и мы хотим выяснить, выполняют ли они одно и то же задание. Как это возможно? Для этого нужно сравнить данные программы. Но на каком уровне? Что, если один программист написал программу на машинном языке, а другой — на языке компилятора? Сравнимы ли подобные программы? Безусловно. Но как именно это сделать? Одним способом было бы скомпилировать вторую программу, получив таким образом соответственную программу на машинном языке второго компьютера.
Теперь перед нами две программы на машинном языке. Но тут возникает другая проблема: у нас два компьютера и, следовательно, два различных машинных языка, которые могут очень сильно отличаться друг от друга. В одном компьютере могут быть слова из шестнадцати битов, а в другом — из тридцати шести. В один компьютер могут быть встроены инструкции по управлению стеком (проталкиванию и выталкиванию данных), а в другом их может не быть. Разница между аппаратурой двух компьютеров может привести к тому, что их программы могут показаться несравнимыми — и все же мы подозреваем, что они выполняют одно и то же задание, и нам бы хотелось это проверить. Очевидно, мы рассматриваем программы со слишком близкого расстояния.
Необходимо отойти подальше, перейдя от уровня машинного языка к более высокому, блочному уровню. С этой точки зрения мы можем надеяться заметить те блоки, которые делают программу разумно спланированной на глобальном, а не на местном уровне — блоки, которые подходят к друг другу таким образом, что становятся видны цели программы. Давайте предположим, что обе программы были первоначально написаны на языках высших уровней; значит, определенные блоки там уже есть. Однако теперь возникает другая проблема: существует множество блочных языков, таких, как ФОРТРАН, АЛГОЛ, ЛИСП, АПЛ и многие другие. Как можно сравнить программу на Алголе с программой на АПЛ? Безусловно, мы не будем сравнивать их строчка за строчкой; вместо этого попытаемся опять мысленно разделить эти программы на блоки в поисках неких совпадающих функциональных единиц. Таких образом, мы сравниваем не аппаратуру и не программы, но некую «эфирную сущность» — абстрактные понятия, лежащие в основе программ. Прежде чем сравнивать между собой программы, написанные на различных компьютерных языках, или два предложения на разных человеческих языках, или двух животных, необходимо выделить из нижних уровней определенный «концептуальный костяк».
Это возвращает нас к вопросу о компьютерах и мозгах: какой смысл описывать их на нижних уровнях? Можно ли в таких сложных системах каким-то объективным образом перейти от такого описания к описанию на высших уровнях? В случае компьютера мы можем легко получить распечатку содержимого памяти, так называемый дамп. На заре работы с ЭВМ, дампы использовались в том случае, когда с программой что-то не ладилось. Программист уносил такую распечатку домой и корпел над ней часами, пытаясь понять, что собой представляет каждая крохотная часть памяти. В таком случае, программист делал нечто обратное компиляции: он переводил с машинного языка на язык высшего уровня, концептуальный язык. В конце концов, он понимал цель программы и мог описать ее в терминах высших уровней: «Эта программа переводит романы с русского на английский» или «Эта программа пишет восьмиголосные фуги, основанные на любой данной ей теме».