Icon (язык программирования)
Последнее изменение этой страницы: 20:16, 1 июня 2016.
Парадигма | мультипарадигменный: императивный, логический |
---|---|
Спроектировано | 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(&letters)) do
write(tab(many(&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(&letters)) do
insert(words, tab(many(&letters)))
every write(!words)
Таблицы
Таблицы - множество пар ключ-значения. Ключ и соответствующее ему значение могут быть любого типа. Таблицы, в отличие от списков, предоставляют ассоциативный доступ, а не по позиции. Таблица создается выражением table(). Таблицы растут автоматически при добавлении новых ключей. Следующий пример создает таблицу, содержащую пары слово-количество повторений во входном файле:
words := table(0)
while line := read() do
line ? while tab(upto(&letters)) do
words[tab(many(&letters))] +:= 1
Здесь значение по умолчанию для каждого слова. Из таблицы можно получить список функцией sort(T, i). Вид списка зависит от значения i.
Графические возможности
Icon поддерживает высокоуровневые графические возможности:
- Окна могут быть открыты и закрыты по желанию
- Текст может быть записан в окна в различных шрифтах и размерах
- Символы с клавиатуры могут быть обработаны в процессе печати
- Точки, линии, многоугольники, окружности и гладкие кривые могут перемешаны с текстом
- Цвета можно использовать как для текста, так и для графики
- Изображения можно считывать и записывать
ISSN 2542-0356
Следуй за Полисом
Оставайся в курсе последних событий
Лицензия
Если не указано иное, содержание этой страницы доступно по лицензии Creative Commons «Attribution-NonCommercial-NoDerivatives» 4.0, а примеры кода – по лицензии Apache 2.0. Подробнее см. Условия использования.