Table Of ContentCopyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
Министерство образования и науки Российской Федерации УДК 519.682
ББК 32.973-018я73
Омский государственный университет им. Ф.М. Достоевского Ч 188
Рекомендовано к изданию в качестве учебного пособия
учебно-методическим советом математического факультета
Рецензенты:
канд. физ.-мат. наук, доцент С.В. Зыкин,
канд. физ.-мат. наук, доцент А.Л. Агафонов
Чанышев О.Г.
Ч 188 Основные элементы языка программирования Icon:
Учебное пособие. – Омск: Изд-во ОмГУ, 2004. – 55 с.
О.Г. Чанышев
ISBN 5-7779-0523-4
Основные элементы Пособие является первой публикацией на русском языке,
языка программирования Icon посвященной мощному средству быстрой разработки программ
для систем ИИ, особенно для автоматического анализа естест-
венно-языковых текстов – языку Icon. В основу положена кни-
Учебное пособие
га Thomas W. Christopher «Icon Programming Language Hand-
book», однако данное пособие – не перевод. Автор опирается
на собственный опыт работы с языком; примеры программ в
подавляющем большинстве оригинальны.
Для студентов математического факультета.
УДК 519.682
ББК 32.973-018я73
Изд-во Омск © Чанышев О.Г., 2004
ОмГУ 2004 ISBN 5-7779-0523-4 © Омский госуниверситет, 2004
2
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
ОГЛАВЛЕНИЕ 10. Процедуры
10.1. Вызов процедур.............................................................................36
Введение.........................................................................................................5 10.2. Выход из процедуры......................................................................38
1. О синтаксисе, переменные, декларации............................................11 11. Основные функции для работы с файлами.....................................39
2. Генераторы 12. Немного о совыражениях – coexpression..........................................41
2.1. Every, to, every do.............................................................................13 13. Графический интерфейс
2.2. !e – генерация элементов.................................................................15 13.1. Атрибуты окна...............................................................................44
2.3. Оператор & – and.............................................................................15 13.2. Текст – запись в окно и чтение из................................................46
2.4. Backtracking и неуспех....................................................................15 13.3. Диалоги...........................................................................................47
2.5. Проверка на &null............................................................................16 13.4. Создание меню...............................................................................48
2.6. Альтернатива |..................................................................................16 13.5. Чтение и запись изображений......................................................50
2.7. Повторы с ограничением. Функция генерации Заключение..................................................................................................51
последовательностей....................................................................................17 Задачи для закрепления материала........................................................52
2.8. Coevaluation – «Совычисления».....................................................17 Список используемой литературы..........................................................54
2.9. Множественные арифметические операции сравнения...............18
3. Управляющие структуры
3.1. if.........................................................................................................19
3.2. case of................................................................................................19
3.3. while do.............................................................................................19
3.4. until do...............................................................................................20
3.5. repeat – повторять до бесконечности.............................................20
4. Символьные множества
4.1. Операции с множествами символов...............................................21
4.2. Принадлежит ли символ множеству? Функция any.....................21
5. Строки .....................................................................................................22
5.1. Подстроки.........................................................................................22
5.2. Операторы для работы со строками...............................................23
5.3. Функции для преобразования строк...............................................23
5.4. Функции сканирования строк.........................................................24
5.5. Более мощные варианты функций сканирования.........................27
6. Списки
6.1. Создание списков.............................................................................29
6.2. Индексированный доступ к элементам списков...........................29
6.3. Операции со списками.....................................................................29
6.4. Функции для работы со списками..................................................30
6.5. Списки как стеки или очереди........................................................30
7. Таблицы...................................................................................................31
7.1. Сортировка таблиц..........................................................................32
7.3. Некоторые другие функции............................................................33
8. Множества...............................................................................................34
9. Записи.......................................................................................................35
3 4
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
Введение жения Icon'а – генераторы». Выражения генерируют последова-
тельности значений, используя «бэктрекинг».
В предисловии к одной из лучших монографий, посвящен- Пример использования генератора:
ных Прологу [1], И. Братко писал: «В средние века знание латин- procedure main()
ского и греческого языков являлось существенной частью образо- L:=["mmm","nnnnn","oooooo"] # Список строк
вания любого ученого. Ученый, владеющий только одним языком, every writes(" ",! L)
неизбежно чувствовал себя неполноценным, поскольку он был end
лишен той полноты восприятия, которая возникает благодаря воз- Выход: mmm nnnnn oooooo
можности посмотреть на мир сразу с двух точек зрения. Таким же Icon не является строго типизированным (тип имеют кон-
неполноценным ощущает себя сегодняшний исследователь в об- станты, но не переменные). Это и не плохо и не хорошо, но чаще
ласти искусственного интеллекта, если он не обладает основатель- всего удобно. Будьте внимательны и следуйте модульному стилю
ным знакомством как с Лиспом, так и с Прологом – этими двумя программирования.
основополагающими языками искусственного интеллекта, без Icon обладает мощными встроенными типами данных для
знания которых невозможен более широкий взгляд на предмет организации сложно структурированной информации: ассоциатив-
исследования». ные таблицы, списки, записи, множества по модулю 2 (автомати-
С полной уверенностью могу добавить к этим языкам и Icon, чески исключающие дублирование), символьные множества. Поч-
который прост и могуч во многом потому, что наследует идеоло- ти любой тип из этого перечня может быть элементом другого ти-
гию мощного семейства языков SNOBOL, первые представители па. Например, элементами таблиц могут быть списки. Списки мо-
которых появились еще в начале 60-х. Название языка не имеет гут состоять из записей и т. п. Только не надо специально услож-
ничего общего с «иконками», а является сокращением от слова нять структуры. Все должно быть ЦЕЛЕСООБРАЗНЫМ. («Красо-
«iconoclastic» (иконоборец) [1], используемом в смысле борьбы с та – это целесообразность» – Иван Ефремов (?)).
конформизмом в разработке языков программирования. Процедуры в Icon'е «относятся к величинам первого класса
Настоящий материал следует рассматривать как введение в (first class values, что означает возможность присваивания перемен-
программирование на Icon’е. Это – не учебник по программирова- ным значений самих процедур, а не результатов их выполнения).
нию, он рассчитан на студентов, уже имеющих опыт программи- В Icon встроен механизм «совыражений» (co-expression) –
рования на Си или Паскале. «Императивная» внешность Icon’а почти независимо выполняющихся частей программы, что дает
способствует быстрому усвоению языка. Простота синтаксиса, возможность как создавать классические сопрограммы, так и реа-
небольшое, но функционально мощное множество структур дан- лизовывать произвольные псевдопараллельные алгоритмы.
ных делают его очень удобным языком быстрого прототипирова- Icon поддерживает автоматическую конверсию типов.
ния, т. е. за более короткое время, чем программирование на Си, Icon включает кросс-платформенные графические возмож-
можно написать и отладить программу, при помощи которой про- ности.
веряются основные идеи концепции. Мой собственный опыт подтверждает, что программы на
Сохраняя внешне стиль императивных языков, на самом де- Icon'е быстро разрабатываются, быстро и надежно работают. Я
ле Icon имеет много инструментов, роднящих его с языками логи- даже стал задумываться: а не изменить ли моей старой любви –
ческого программирования. Например, «бэктрекинг», или генера- Prolog'у?! (Тем более что Icon распространяется свободно (не для
торы. Christopher [2] пишет: «Самое большое различие между коммерческого использования!) и Вы можете свободно распро-
Icon'ом и другими языками программирования – это то, что выра-
5 6
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
странять собственные выполняемые модули (exe – файлы), в от- "The vertical bar, "|", read "«or»", looks like a binary operator
личие от PDC Visual Prolog.) but does not behave like one".
Приведем несколько «программулек» для иллюстрации: Другой пример: символ "\" в выражениях "\x" и "|(z to y)\x"
procedure main() обозначает различные операторы (в первом случае проверяется,
#Перезапись файла имеет ли значение переменная x, а во втором – является ли огра-
f:=open("x.txt","r")|stop("cannot open x.txt") ничителем генерируемых значений).
f2:=open("y.txt","w")|stop("cannot open y.txt") У Icon’а есть сложности с кириллицей. Он «не понимает»
# Классический стиль кириллические имена файлов при стандартном открытии
while s:=read(f) do write(f2,s) f:=open(“имя_моего_файла”,”rt”) либо когда имя файла передается
close(f) в командной строке
close(f2) icon_prog.exe имя_моего_файла
procedure main(args))
end
f:=open(args[1],”rt”)
……………………….
В стиле Icon'а подчеркнутые элементы кода заменит выра-
end
жение
Чтобы обойти эту сложность, следует работать в графиче-
every write(f2,!f)
ском режиме и обращаться к соответствующему «диалогу».
link graphics
Большинство проблем при парсировании кириллического
procedure main()
текста Вы можете обойти, создав собственное множество симво-
# Простейший вариант открытия графического окна:
лов:
WOpen("size=400,300") | stop("can't open window")
allRus:='АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЪЫЭ
Font("Times New Roman,18") # Устанавливаем шрифт
ЮЯабвгдеёжзийклмнопрстуфхцчшщьъыэюя'
L:=["Линия 1","Линия 2","Линия 3"]
И при необходимости можете создать объеденное множество:
case SelectDialog("Выберите линию",L,L[1]) of
allLetters:= &ascii++allRus
{
………………………………………………………………..
"Okey":
Теперь несколько слов о математических возможностях
{
Icon’а (которые меня не очень интересуют и в дальнейшем изло-
GotoRC(1,1)
жении специально не рассматриваются). Язык обладает вполне
WWrite(dialog_value) # Печатаем выбранную строку
достаточным набором операторов и функций для того, чтобы быть
WDone()
алгоритмически полным и в «вычислительном» смысле. Он рабо-
}
тает с целыми и реальными числами. Имеет специальные средства
"Cancel": {}
для манипулирования коплексными и рациональными числами.
}
Бинарные операторы:
end
* – умножение
/ – деление
Может быть, единственное, что мне не нравится в Icon'е, это
% – остаток (5%2=1)
семантическая многозначность операционных символов (разре-
+ – сложение
шаемая контекстно). Вот цитата из Cristophera [2, с. 41]: - – вычитание
7 8
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
Следует помнить, что звездочка (*), используемая как пре- и Idol (объектно-ориентированное раширение Icon. – О.Ч.), рас-
фиксный оператор, возвращает длину объекта. пространяемые в исходных текстах. В любом случае изучение
Информацию о языке, а также дистрибутивы самого языка этих языков доставит удовольствие и вооружит вас мощнейшим
можно получить по адресу http://www.cs.arizona.edu/icon. Устано- инструментом как быстрого прототипирования сложных про-
вите Icon (и «пропишите»!). Для написания простых программ грамм, так и "реактивного" создания целого класса очень нужных
(файл с исходным текстом должен иметь расширение.icn) можете приложений, для которых любой другой инструментарий не под-
пользоваться любым текстовым редактором. ходит из-за слишком больших трудозатрат».
Если у Вас сложный проект, состоящий из нескольких icn-
файлов, то предварительно компилируются отдельные части про-
граммы:
wicont –c <имя_файла>.icn
Затем для компиляции и получения исполняемого модуля:
wicont <имя_главного_файла>.icn
Главный icn-файл содержит procedure main(…) и деклара-
тивы link с именами файлов проекта:
link <имя_1>.icn
…………………
link <имя_N>.icn
………………….
procedure main(…)
……
end
procedure p1(…)
………
end
procedure pn(…)
………
end
Некоторые книги на английском языке доступны в pdf-
формате по адресу http://www.cs.arizona.edu/icon/books.htm. Лите-
ратурные источники по данной теме на русском языке мне не из-
вестны, за исключением сотни строк в статье А. Зубинского [2],
цитатой из которой я и завершу введение: «Заинтересовавшимся…
можно порекомендовать отличную online-версию книги Icon
Programming Language Handbook Томаса Кристофера (пригодный
к чтению на любых платформах pdf-формат) и сами системы Icon
9 10
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
1. О синтаксисе, переменные, декларации global – создание переменной, известной всем процедурам
(global x,y).
Возможно, Вы уже обратили внимание на то, что синтаксис procedure <имя_процедуры> – начинает объявление проце-
языка Icon очень прост. Операторы языка разделяются либо сим- дуры.
волом перевода строки, либо точкой с запятой (;). Например: record <имя_записи>(<список_имен_полей>) – создает
every {writes(" ",1 to 5);writes(" ",6 to 10)} структуру данных, называемых «записью» (record r(x,y,z)).
или link <имя_внешней_процедуры> указывает редактору, что
every данная программа использует внешнюю процедуру.
{ invocable <имя_процедуры> – позволяет обращаться к про-
writes(" ",1 to 5) цедуре по имени-строке ("f"(x)).
writes(" ",6 to 10) Декларации global, record, link, invocable должны появляться
} только в начале программы (в преамбуле), до первого объявления
Запятая используется для разделения элементов в разного какой-либо процедуры.
рода перечислениях. Группы операторов, например, в выражениях Договоримся на дальнейшее, что, следуя Christopher'у, ла-
if {} then {} else тинской e или ei, где i – целое, будем обозначать произвольные
ограничиваются фигурными скобками. Квадратные скобки выражения.
[] служат, преимущественно, для индексирования выражений
(L[3] обозначает третий элемент некоторой структуры). В круглые
скобки обычно заключается список параметров или выражения в
«совычислениях» – coavaluation. Объявления процедуры начина-
ются со слова procedure, за которым следует либо main(...), либо
<имя_процедуры>(p1,...,pn) с формальными параметрами.
Процедура заканчивается словом "end". Процедуры не могут
быть вложенными. Все ключевые слова пишутся с маленькой ла-
тинской буквы.
Имена переменных могут состоять из латинских букв, цифр
и знаков подчеркивания. Имена переменных, буквы которых на-
браны в различных регистрах – разные имена (naMe и name, Name
– разные имена).
Декларации
local – создание переменной, известной только внутри про-
цедуры и существующей до выхода управления из данной проце-
дуры (local x,y).
static – создание переменной, известной только внутри про-
цедуры и сохраняющей последнее присвоенное значение в тече-
ние выполнения программы в целом (static x,y).
11 12
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
2. Генераторы Оператор to может генерировать серию значений. Напри-
мер, в случае 100 to 103 мог бы сгенерировать значения 100, 101,
Генераторами называются операторы (и выражения), произ- 102, 103, если ему это позволят.
водящие множество значений в контексте генерации. Чтобы по- В случае write(10 to 20) печатается единственное значение
нять, как работают генераторы, следует иметь в виду: 10.
во-первых, общую для всех языков основную последова- Но every write(1 to 3) напечатает 123.
тельность выполнения выражений – слева направо и сверху вниз с Вариант to by очевиден, by задает шаг.
учетом приоритета операторов; Примеры:
во-вторых, возврат назад для того, чтобы найти подвыраже- every i:=1 to 100 by 10 do write(i)
ние, генерирующее более одного значения, взять новое значение и Выход: 1
повторить процесс. 11
Этот возврат с перебором называется бэктрекингом. Прото- 21
типами бэктрекинга являются различные конструкции, органи- ....
зующие циклы. Бэктрекинг – «главный кит» Пролога, наряду с 91
подстановкой и унификацией. Он использует его, как нечто само every {writes(" ",1 to 5); writes(" ",6 to 10)}
собой разумеющееся. Например, человек, знакомый только с Си, Выход: 1 6 7 8 9 10
не сможет понять, что предикат p: Но
every (writes(" ",1 to 5), writes(" ",6 to 10))
p:-fact1(_,_,X,_),fact2(_,Y,_), X<Y,!,...
дает на выходе:
переберет все экземпляры фактов fact1, fact2, чтобы найти 1 6 7 8 9 10 2 6 7 8 9 10 3 6 7 8 9 10 4 6 7 8 9 10 5 6 7 8 9 10
первую их комбинацию, удовлетворяющую условию X<Y. В В данном случае (every (e1,e2)):
Icon'е контекст перебора почти всегда должен быть указан явно, 1. После генерации первого из возможных значений выра-
т. е. одного оператора, имеющего статус генератора, недостаточ- жения e1
но. Например: управление передается выражению e2.
f:=open("myfile.txt,"rt") 2. e2 генерирует все возможные значения.
.......................... 3. Затем e1 генерирует следующее значение и т. д.
S:=!f # читается одна запись файла e1 и e2 могут быть успешными и неуспешными.
Но выражение every(write(!f)) выведет построчно на экран every i:=1 to 5 do writes(" ",i)
все записи (несколько ниже приведен пример кода в чисто «про- S:=4
логовском» стиле). every S<4 do writes(" ",17 to 18)
Выход: нет выхода.
2.1. Every, to, every do Если же мы напишем every S<4, то будет напечатано число
17.
every создает контекст, в котором может быть сгенерирова-
но множество значений. В нижеследующем примере каждое вы-
ражение в последовательности, за исключением последнего, гене-
рирует не более одного значения. Последнее выражение генериру-
ет столько значений, сколько позволяет контекст.
13 14
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
2.2. !e – генерация элементов end
Выход: – исходная строка S и O'key с новой строки.
Если e – некоторая структура, то !e берет первый элемент
Проверка каждого символа на равенство символу перевода
структуры, а в контексте генерации генерирует множество эле-
строки порождает неуспех вплоть до последнего символа, что за-
ментов этой структуры.
ставляет первое подвыражение (sim:=!S) генерировать новые сим-
Примеры:
волы. В итоге напечатается строка S, а затем O'key.
L:=[1,2];every writes(" ",!L).#Выход: 1 2
s:="cat";every writes(" ",!s).#Выход: c a t
2.5. Проверка на &null
Бинарные операции, содержащие генераторы:
every writes(" ",5 to 6)+(10 to 20)) Унарный оператор ‘\’ успешен, если его операнд имеет зна-
напечатает 15 25 16 26 чение, отличное от &null, а ‘/’ – в противном случае, т. е. мы мо-
жем написать
2.3. Оператор & – and if \x & \y then...".
Если x не присвоено значение, мы не можем написать if
e1&e2
~x…, но должны написать if /x … .
Этот оператор возвращает значение правого операнда и
имеет наинизший приоритет.
2.6. Альтернатива |
every i:=|seq(1,2)\3 & j:=|seq(2,2)\3 & i~= j & writes(" ",i+j)
Выход: 3 5 7 5 7 9 7 9 11 Вертикальная черта ‘|’, читаемая как «или», смотрится как
бинарный оператор, но появляется и в ином контексте. Выраже-
2.4. Backtracking и неуспех ние:
e1 | e2 означает генерацию всех элементов e1, а затем – всех
Перебор прекращается, когда перебирать уже нечего, и
e2.
управление переходит к следующему выражению. Например, на-
procedure main()
печать 12345 можно так (не рассматривая очевидный вариант
local x,y,z
write("12345")): every writes (1 to 5).
L:=["Vera","Manja","Tanja"]
Этот же результат можно получить, если использовать
x:=1
встроенное в Icon выражение &fail, которое всегда порождает не-
if (\x | \y) then z:=10
успех.
(writes(" ",!L) | write(" ",z))
write (1 to 5) + &fail.
every (writes(" ",!L) | write(" ",z))
write("\n","O'key")
#while (writes(" ",!L)) | write(" ",z))
Знак ‘+’ нужен только для конструирования синтаксически
end
правильного выражения, т. е. контекст генерции задается "неуспе-
Выход: Vera Vera Manja Tanja 10
хом".
Если раскомментировать выражение перед end, то получим
Тогда мы можем использовать чисто «прологовский» стиль:
бесконечную печать слова Vera.
procedure main()
S:="tak pit hochetsa, chto perenochevat negde\n"
(sim:=!S, writes(sim),sim=="\n")
write("O'key")
15 16
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
2.7. Повторы с ограничением. Функция генерации после- every writes(" ",(!S,1 to 3))
довательностей write()
every writes(" ",(!S & 1 to 3))
Генератор «с перезарядкой» |e позволяет генерировать все
end
значения e, затем происходит реинициализация и процесс повто-
Выход:
ряется бесконечно.
q q q w w w e e e r r r t t t y y y u u u
Чтобы избежать бесконечного повторения процесса, исполь-
1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
зуется ограничитель числа повторений: |e\n.
1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
Например: every |(writes(7))\7 выведет 7777777,
так же, как и every (writes(|7\7)), и every i:=1 to 7 do writes(7).
2.9. Множественные арифметические операции сравне-
ния
Специальная функция seq() предназначена для генерации
бесконечных рядов значений Такие операции, как a<b<c, Christopher относит к генерато-
seq() генерирует 1,2,3,............. рам. В связи с этим следует сказать об обычном в Icon'е програм-
seq(i) генерирует i,i+1,i+2........ мистском трюке. Если мы ходим выбрать наименьшее из x и y, то:
seq(i,j) генерирует i+j,i+2j,i+3j.. x:=x>y или x>:=y
every writes(" ",seq(2,2)\5) выведет 2 4 6 8 10
как и every writes(" ",seq(2,2))\5
2.8. Coevaluation – «Совычисления»
В общем виде совычисления представляются так:
e0(e1,e2,...,eN),
где e0 – выражение, вычисляющее номер выражения в скоб-
ках, которое генерирует значения, и может быть переменной, зна-
чение которой есть целое число, вычисляемое где-то в другом
месте программы. Действия остальных заключаются в активации
бэктрекинга.
«Вырожденная» форма:
(e1,e2,...,eN) эквивалентна N(e1,e2,...,eN)
или (e1&e2&...&eN).
Пример:
procedure main()
K:=1
S:="qwertyu"
every writes(" ",K(!S,1 to 3))
write()
17 18
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
3. Управляющие структуры 3.4. until do
until e1 do e2
3.1. if... Эквивалентно while not e1 do e2
Пример: Печать чисел Фибоначчи
if e1 then e2 else e3
procedure main()
if e1 then e2
local i,j
e1 может генерировать не более одного значения
i:=1;j:=1
e3 могут генерировать столько значений, сколько позволяет
until i>100 do {write(i,j);i+:=j;i:=:j}
контекст.
end
3.2. case of
3.5. repeat – повторять до бесконечности.
case e1 of
i:=1
{
repeat
e2 : e3
{
if i<10 then {write("i меньше 10");i:=i+1} else break
e4 : e5
}
...
e2n : e2n+1
default : e2n+2
}
3.3. while do
while e1 do e2
while e1
Генерируется одно значение e1, и если НЕ ЛОЖЬ, то вы-
полняется e2.
Пример:
i:=0
while i<2 do {writes(" ",i);i+:=1}
Выход: 0 1
В следующем примере будут бесконечно «печататься» на
экране вводимые Вами строки символов:
while write(read( ))
19 20