Icon (язык программирования)

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 20:16, 1 июня 2016.
Icon
Iconlogo.gif
Парадигма мультипарадигменный: императивный, логический
Спроектировано Ralph E. Griswold
Первый   появившийся 1977
Стабильная версия 9.5.1 / 6 июля, 2013
Печать дисциплины динамическая
Портал: Icon
Диалект
Icon, Jcon, Unicon
Под влиянием
SNOBOL, SL5, ALGOL

Icon - это высокоуровневый язык программирования с широкими возможностями обработки строк и структур. Этот язык привнес несколько новшеств, включая выражения, результатом выполнения которых является последовательность данных, целенаправленное вычисление, которые автоматически ищет успешный результат и сканирование строк. Основными преимуществами этого языка являются генераторы и сканирование строк. В настоящее время Icon уже практически не используется и имеет скорее научную и историческую ценность. Потомок этого языка, Unicon, используется в различных задачах и постоянно развивается.

История языка

Icon происходит от SNOBOL. Изначально был разработан в Bell Telephone Labaratories в ранние 60-ые для продвижения разработки приложений, которые обрабатывают строковые данные и другие сложные структуры. Дальнейшим развитием языка занимался университет Аризоны. Название языка было выбрано до того, как термин "иконка" стал популярным в графическом пользовательском интерфейсе и никак с ним не связано.

Области применения

  • анализ текста
  • редактирование текста
  • форматирование документов
  • искусственный интеллект
  • экспертные системы
  • быстрое прототипирование
  • символьная математика
  • генерирование текстов

Вычисление выражений

Условные выражения

В Icon существуют условные выражения. В случае выполнения условия, они возвращают некоторый результат, в противном случае результат не возвращается. Примером является условный оператор

i > j

который при i, имеющем большее значение чем j, считается успешным и возвращает j. Похожим образом

i > j > k

Удобство использования концепта успешного вычисления условных операторов наглядно демонстрируется оператором find(s1, s2), который вычисляется неуспешно, если s1 не является подстрокой s2. Так

if i := find("or", line) then write(i)

напишет позицию, в которой встречается "or" в строке line, и не напишет ничего, если не встречается. В Icon большинство выражений являются условными. Например read() возвращает следующую строку входного файла, но "проваливается", если достигнут конец файла. Следующее выражение является типичным для Icon:

while line := read() do
   write(line)

Это выражение копирует данные из входного файла в выходной. Если аргумент функции неуспешно вычисляется, вызова функции не происходит и функция также считается неуспешно вычисленной. С учетом вышесказанного, переписывание данных из одного файла в другой можно записать следующим образом:

 while write(read())

Генераторы

В некоторых случая выражения могут возвращать более 1 результата.

sentence := "Store it in the neighboring harbor" 
find("or", sentence)

Здесь "or" встречается в позициях 3, 23 и 33. В большинстве языков программирования в качестве результата будет выбрана только одна из позиций, обычно первая. В Icon такое выражение является генератором и имеет возможность вернуть все 3 позиции. Результат, возвращаемый генератором, зависит от контекста. Когда нужен только одно число, будет возвращен первый, например

i := find("or", sentence)

присвоит переменной i значение 3. Если результат, предоставленный генератором не приводит к успешному вычислению вызывающего выражения, генератор предложит другое значение. Например

if (i := find("or", sentence)) > 5 then write(i)

Здесь первый результат, предоставленный генератором является 3, но 3 меньше 5 и оператор сравнения завершается неуспешно. В этом случае происходит возврат к генератору, который в этот раз вернет 23 на выход. 23 больше 5, оператор сравнения срабатывает успешно и записывается число 23. Используя тот факт, что результаты выполнения условных операторов наследуются и операторы сравнения возвращают значение их правого аргумента, пример выше можно записать в компактной форме:

write(5 < find("or", sentence))

Генератор можно вызывать повторно для того, чтобы получить все возвращаемые им значений, используя блок every-do. Например

every i := find("or", sentence)
   do write(i)

запишет все позиции, на которых "or" встречается в sentence. Также в языке имеется несколько встроенных генераторов. Одним из наиболее часто используемых является

i to j

который генерирует целые числа от i до j. Также для работы с генераторами существуют и другие блоки, помимо every-do. Например чередование,

expr1 | expr2

которое генерирует результаты expr1, за которыми следует результаты expr2. Так

every write(find("or", sentence1) |
   find("or", sentence2))

напишет позиции "or" в sentence1, а следом за ними позиции "or" в sentence2.

Сканирование строк

Оператор сканирования строк имеет следующую форму:

s ? expr

где s - строка для исследования и expr - выражение, которое проводит это исследование. Позиция в строке, которая начинается с 1, называется фокусов исследования. Сопоставляющие функции меняют фокус. Move(i) сдвигает позицию на i и возвращает подстроку между предыдущей и новой позицией фокуса. Если позиция не может быть перемещена на указанное количество (из-за недостаточной длины строки), move(i) завершается неудачей. Простой пример:

line ? while write(move(2))

выведет последовательные двухсимвольные подстроки строки line. Другая сопоставляющая функция - tab(i), которая устанавливает текущую позицию в i и возвращает подстроку между предыдущей и новой позицией. Например

line ? if tab(10) then write(tab(0))

сначала установит позицию в 10 а затем в конец исследуемой строки, записывая оставшиеся символы. В случае, если строка недостаточно длинная, ничего записано не будет. Функции анализа строк, например find(), можно использовать в сканировании строк. В таком контексте не указывается строка, в которой осуществляется поиск, т.к. она берется из объекта исследования. Например:

line ? while write(tab(find("or")))
   do move(2)

выводит все подстроки line, которые встречались до "or". Заметьте, что find() возвращает позицию, которую затем использует tab(), чтобы сменить позицию и вернуть желаемую подстроку. Move(2) пропускает найденный "or". Другой пример использования функций анализа строк в сканировании строк:

line ? while write(tab(find("or")))
line ? while tab(upto(&amp;letters)) do
   write(tab(many(&amp;letters)))

выводит все слова в line. Как было продемонстрировано в примерах выше, любое выражение можно использовать в выражении сканирования.

Структуры данных

Icon поддерживает несколько видов структур данных с разными внутренними устройствами и способами доступа к данным. Списки - линейные структуры, к которым можно обращаться как по позиции, так и через функции стека и очереди. Множества - коллекции произвольных значений, которые никак не упорядочены. Таблицы предоставляют механизм ассоциативного поиска.

Списки

В то время, как строки - последовательности символов, списки - последовательности значений произвольных типов. Например

car1 := ["buick", "skylark",  1978, 2450]

список car1 содержит 4 элемента, два из которых строки, а два - целые числа. Заметьте, что значения в списках не обязаны быть одного типа. Также допускаются вложенные списки. Списки также могут быть созданы функцией list():

L := list(i, x)

которая создает список из i элементов, каждый из которых равен x. К элементам списка можно обращаться по позиции в списке:

write(car1[4])

в случае, если в списке есть четвертый элемент, он будет записан. Иначе выражение завершится неудачей. Значения списка L могут быть сгенерированы с помощью !L. Так

every write(!L)

запишет все значения из L. Со списками можно работать как с очередями и стеками. Функция push(L, x) добавляет значение x в левый конец списка L, увеличивая размер списка на 1. Функция pop(L, x) убирает крайнее с лева значение из списка L, уменьшает размер списка на 1 и возвращает удаленное значение.

Множества

Множество - коллекция значений. Пустое множество создается set(). Set(L) создает множество из элементов списка L. Например

S := set([1, "abc", []])

присваивает S множество, содержащее целочисленную 1, строку "аbc" и пустой список. В языке имеются операции над множествами: объединение, пересечение и разность. Функция member(S, x) успешно выполняется, если x является членом множества S. Функция insert(S, x) добавляет x в S, а delete(S, x) удаляет x из S. !S генерирует члены S. Простой пример использования множеств продемонстрирован ниже. Выводятся все разные слова, которые встретились во входном файле:

words := set()
while line := read() do
   line ? while tab(upto(&amp;letters)) do
      insert(words, tab(many(&amp;letters)))
every write(!words)

Таблицы

Таблицы - множество пар ключ-значения. Ключ и соответствующее ему значение могут быть любого типа. Таблицы, в отличие от списков, предоставляют ассоциативный доступ, а не по позиции. Таблица создается выражением table(). Таблицы растут автоматически при добавлении новых ключей. Следующий пример создает таблицу, содержащую пары слово-количество повторений во входном файле:

words := table(0)
while line := read() do
   line ? while tab(upto(&amp;letters)) do
      words[tab(many(&amp;letters))] +:= 1

Здесь значение по умолчанию для каждого слова. Из таблицы можно получить список функцией sort(T, i). Вид списка зависит от значения i.

Графические возможности

Icon поддерживает высокоуровневые графические возможности:

  • Окна могут быть открыты и закрыты по желанию
  • Текст может быть записан в окна в различных шрифтах и размерах
  • Символы с клавиатуры могут быть обработаны в процессе печати
  • Точки, линии, многоугольники, окружности и гладкие кривые могут перемешаны с текстом
  • Цвета можно использовать как для текста, так и для графики
  • Изображения можно считывать и записывать

Ссылки