УДК 004.43
В. В. Лаптев, В. В. Толасова ОСОБЕННОСТИ ЯЗЫКА ПРОГРАММИРОВАНИЯ ДЛЯ ОБУЧЕНИЯ
Введение
В настоящее время при обучении программированию остро стоит вопрос о выборе языка программирования для обучения. В [1] определен набор признаков классификации, и по этим признакам сравниваются несколько языков программирования, которые можно было бы использовать в качестве языка обучения. Делается вывод о том, что лучшим выбором все еще является Pascal. В [2] для обучения предлагается использовать систему Pascal ABC. Авторы [3] ратуют за обучение с использованием Visual Basic, а в [4] в качестве языка для обучения используется С++.
Существование таких разных точек зрения говорят о том, что ни один из предлагаемых языков программирования не представляется бесспорным кандидатом. Pascal как язык для обучения программированию уже не соответствует современным требованиям. С момента определения языка прошло уже почти 40 лет, программирование сильно изменилось: «умерли» устаревшие технологии, родились новые. На смену процедурной парадигме программирования пришли более развитые: объектно-ориентированное программирование, обобщенное программирование, аспектно-ориентированное программирование. Последователями Pascal стали новые языки программирования: Modula-2, Oberon, Zonnon [5].
Появилось много новых промышленных языков программирования. В настоящее время в разработках информационных систем доминирующим стал объектно-ориентированный подход и объектно-ориентированные языки - наследники С: С++, C# и Java. Однако опыт их применения в обучении показывает, что использовать эти языки для обучения достаточно сложно по нескольким причинам. Во-первых, промышленные языки программирования реализованы в рамках больших и сложных интегрированных сред. Во-вторых, промышленные языки сами являются большими и сложными. Например, стандарт языка С++ [6] представляет собой книгу объемом 792 страницы. В-третьих, в составе промышленных языков реализованы большие и сложные стандартные библиотеки. И наконец, эти языки не обладают концептуальной целостностью и включают в себя множество специфических черт, обусловленных платформой реализации.
Еще менее подходящим представляется Visual Basic. В настоящее время этот язык практически не используется в промышленных разработках. Visual Basic разработан фирмой Microsoft и ориентирован на другие разработки этой фирмы: пакет MS Office и операционную систему Windows.
Таким образом, представляется целесообразным разработать и реализовать новый язык программирования, специально предназначенный для обучения в современных условиях. Этот язык, очевидно, должен обладать рядом свойств, облегчающих его применение для обучения.
Требования к языку программирования для обучения
Язык программирования для обучения должен быть «маленьким» и в то же время достаточно мощным. Минимизация понятий облегчает понимание языка и существенно снижает риск совершения ошибок при программировании. Конструкции языка не должны зависеть ни от аппаратных особенностей платформы, ни от операционной системы - именно это требование было одним из основных при создании Pascal. Более того, синтаксическая форма конструкций существенно влияет на простоту усвоения языка и степень понимания программ [7]. Тем не менее язык для обучения должен быть достаточно близким к современным промышленным языкам, поэтому в нем должны быть определены наиболее распространенные управляющие операторы, самые типичные элементарные типы данных и операции с ними.
Как и в любом промышленном языке программирования, в языке для обучения должны быть определены средства для конструирования агрегатов данных - контейнеров. Однако нужно отметить, что в промышленных языках эти средства слишком многообразны и разнородны, что является результатом эволюционного развития. Такое положение создает трудности для начинающих программистов. Между тем практически все контейнеры обладают общим свойствами, поэтому в обучающем языке программирования лучше определить некоторый обобщенный вид контейнера.
Очевидно, что язык программирования для обучения должен поддерживать объектноориентированный подход. Однако для обучения алгоритмике язык должен поддерживать и процедурную парадигму. Кроме того, в языке должны быть определены средства обработки аварийных ситуаций, подобные ставшему уже практически стандартным механизму исключений. Представляется обязательной поддержка в языке многомодульных программ.
Таким образом, в языке программирования для обучения должны быть определены следующие средства:
— небольшое множество элементарных типов данных;
— множество типичных операций с элементарными типами;
— минимальный набор управляющих операторов;
— небольшой набор мощных агрегатов данных;
— средства определения новых функций;
— поддержка обработки исключений;
— механизмы определения новых типов данных (классы);
— поддержка модульности.
Особо нужно сказать о синтаксисе обучающего языка. На первый взгляд совершенно очевидно, что синтаксис должен быть С-подобным, поскольку все наиболее популярные промышленные языки программирования имеют такой синтаксис. Однако «чистый» С-подобный синтаксис недостаточно регулярен и последователен, поэтому представляется целесообразным использовать смешанный синтаксис, взяв лучшее из Pascal и С.
Необходимо упомянуть ещё об одном: реализация языка программирования для обучения в рамках обучающей среды не обязательно должна быть очень эффективной. Гораздо более важным качеством для обучения является максимальная общность и гибкость конструкций.
Язык программирования должен поддерживаться обучающей интегрированной средой, которая тоже имеет ряд специфических черт, отличающих ее от стандартных промышленных систем. В любой профессиональной интегрированной среде реализованы многочисленные системные библиотеки. Однако их реализация и подключение к среде практически никак от языка программирования не зависят и выполняются внешними средствами. Обучающая среда помимо стандартных средств должна обеспечивать простой и независимый от платформы реализации механизм накопления программных компонент.
Определение основных свойств языка
Элементарные типы данных и операции. Все типы, определенные в языке, по умолчанию являются наследниками базового класса Object. К элементарным типам относятся: целые (integer), вещественные (real), булевские (bool). Набор встроенных операций является подмножеством набора операция, определенных в С++, и включает в себя арифметические операции (+, -, *, /, %), инкремент и декремент (++, —), операции сравнения (==, !=, <, >, <=, >=), логические операции (&, |, А, !), операции присваивания (=, +=, -=, *=, /=, %=, &=, |=, А=). Семантика операций соответствует семантике операций С++. Представление констант элементарных типов - традиционное.
Составные типы данных. Агрегат данных в языке только один - контейнер (container). Определение контейнера, его свойства и типовые операции с ним описаны в [8], поэтому здесь на этом останавливаться не будем.
Символы и строки. Эти типы данных нужно выделить отдельно. Во-первых, набор операций с символами (char) значительно отличается от операций с другими элементарными типами данных. Например, обязательными являются операции преобразования регистра символов. Очень часто необходимо выяснить, к какой группе относится символ (буква, цифра, пробельный). Во-вторых, символьный тип значительно больше зависит от платформы и операционной системы, чем другие элементарные типы данных.
Строка является контейнером, специализированным для хранения символов, и поэтому операции со строками несколько отличаются от типовых операций с контейнерами и являются традиционными для строк: сцепление, выделение подстроки, вставка и удаление подстроки, поиск подстроки. Особым видом строк являются регулярные выражения, которые фактически стали уже стандартом в промышленных языках программирования. Представление символьных и строковых констант такое же, как в С++.
Переменные, ссылки, константы и выражения. В объявлении переменной задаются тип, имя и возможное начальное значение. Для числовых переменных разрешается задавать диапазон изменений. Для строковых переменных разрешается задавать максимальную длину. Объявление константы обозначается ключевым словом constant.
В качестве начального значения может задаваться выражение соответствующего типа. В выражениях не допускается смешивать операции разного типа. Преобразования типов по умолчанию не выполняются, за исключением преобразования целое -> вещественное. Примеры объявления переменных и констант: integer a; constant real b = 3.1415926; integer D in [-5..5], R in [0..500] = 0; string S = "строка”, w[30] = “новая строка”;
Объявление ссылки начинается с ключевого слова ref. Ссылка может быть инициализирована именем уже объявленной переменной. Ссылку можно инициализировать и динамической переменной, создаваемой с помощью операции new: ref integer F = D, t = new (31); ref integer a = new in [0..500], b = new(1) in [0..2];
Неинициализированная ссылка получает значение null.
Операторы управления. Вполне традиционные: if, switch, while, for, break. Каждый оператор завершается символом «;». Выражение, завершенное точкой с запятой, является оператором. Каждый оператор может быть помечен традиционным образом. Синтаксис управляющих операторов сделан более последовательным по сравнению с С++. Условный оператор if имеет следующий формат:
if (условие) { операторы }; else { операторы };
Часть else может, естественно, отсутствовать. Условие в скобках - выражение булевского типа. Конструкция { операторы } называется блоком.
Оператор-переключатель switch имеет вид:
switch (выражение) { альтернатива-1; ... альтернатива-k; };
else { операторы };
Выражение должно быть целое. Альтернатива завершается точкой с запятой и имеет вид: case <значение>: { операторы }
В качестве <значение> можно задавать одно целое значение, ряд значений через запятую, диапазон значений в скобках. Часть else выполняется, если значение вычисляемого выражения не совпало ни с одним из значений в альтернативах. Часть else может отсутствовать.
Операторы цикла имеют следующий синтаксис: while (условие) { операторы };
for (выражение-1; условие; выражение-2) { операторы };
Семантика операторов традиционна. Для выхода из цикла применяется оператор break, имеющий формат: break [метка];
Если метка в операторе break отсутствует, то осуществляется выход из текущего блока. Если метка задана, выполняется переход по метке.
Функции. Определение функции имеет вид: method имя (параметры): результат { операторы };
В качестве результата можно задавать любой тип (в том числе и контейнер). Если функция не возвращает результата, то в заголовке его указывать не нужно. Функция может возвращать ссылку. Для выхода из функции и возврата результата применяется оператор return, имеющий тот же синтаксис и семантику, что и в С++. Вызов функции традиционен. Тело функции - это блок.
Параметры передаются либо как значения, либо как ссылки. Формат одного параметра аналогичен объявлению переменной (ссылки). Если параметр инициализирован, то инициализатор является значением по умолчанию. Разрешается определять переменные процедурного типа и передавать функции как параметры.
Функции разрешается перегружать. Разрешается перегружать встроенные операции, задавая вместо имени метода конструкцию operator@, где @ - одна из стандартных операций. В качестве хотя бы одного из параметров должен быть новый тип. Функция с именем main является главной, с нее начинается выполнение программы.
Определение новых типов данных. Новый тип данных определяется конструкцией класса: dass имя { операторы };
Любой класс является наследником базового класса Object по умолчанию. Тело класса -это блок, поэтому, как в обычном блоке, разрешается определять переменные и функции, которые называются полями и методами. По сравнению с обычным блоком для класса определены дополнительные средства, используемые при наследовании. Имена, объявленные в блоке, могут быть объявлены как закрытые (private), или защищенные (protected). Для любого поля можно объявить методы get и set. Такие поля называются свойствами.
Формат определения методов совпадает с форматом объявления функций. Любой метод -виртуальный (virtual). Метод можно объявить как статический (такой метод не является виртуальным), абстрактный (abstract) или бесплодный (sealed). В классе можно объявлять специальные методы: конструкторы и деструктор. Один конструктор может быть статическим.
Разрешено простое открытое наследование, принцип подстановки выполняется. Синтаксис наследования:
dass имя: имя_базового_класса { операторы };
Можно объявить класс публичным, абстрактным или бесплодным.
Разрешены интерфейсы: interface имя { операторы };
Семантика определения интерфейсов совпадает с семантикой, определенной в C#. Каждый интерфейс определяет новый тип. Реализация интерфейса возлагается на класс, который является наследником интерфейса. Разрешается множественное наследование интерфейсов.
Блоки. Как было сказано выше, конструкция в фигурных скобках является блоком. Любые имена, объявленные в блоке, являются локальными по умолчанию. Имя можно сделать публичным (public) - имя становится доступным на следующем уровне вложенности. Переменные, объявленные в блоке, являются локальными с традиционной семантикой. Разрешается объявлять переменные статическими (static).
Функции тоже всегда объявляются в некотором блоке. Функция является локальной в блоке и тоже может быть объявлена видимой на следующем уровне вложенности. Поскольку тело функции является блоком, разрешаются вложенные функции. Функция в блоке имеет неограниченный доступ ко всем переменным, объявленным в блоке, независимо от места объявления.
Классы тоже объявляются в некотором блоке, и тело класса является блоком. Следовательно, допустимы вложенные классы. То же самое касается интерфейсов. Класс и интерфейс могут быть объявлены видимыми (public) на следующем уровне вложенности.
Модули и пространства имен. Компилируемой единицей является модуль. Модуль определяется конструкцией: module имя { операторы };
В модуле определяются переменные, константы, функции, классы, интерфейсы. Тело модуля - это блок. Модули тоже могут быть вложенными; как обычно, для доступа к вложенному модулю его нужно объявить публичным. Экспорт имен определяется модификатором доступа public. Импорт имен в данном модуле из другого модуля осуществляется конструкцией: using имя модуля;
Один из модулей программы должен быть главным, и в нем должна быть определена публичная функция main. Имя главного модуля по умолчанию является публичным в среде и поэтому должно быть уникальным. В главном модуле с помощью предложений using определяется состав проекта. Если в проекте задействован только один модуль, он должен быть главным.
Среда. В среде определен модуль system, в составе которого определены все системные модули, классы, интерфейсы, функции, переменные и константы. Любой модуль, объявленный публичным, является общедоступным для любых других модулей в среде.
В среде можно создавать глобальные переменные с помощью конструкции new: global integer t = new (31);
Имя глобальной переменной должно быть уникальным в среде. Значение переменной сохраняется средой, поэтому в глобальных переменных можно сохранять данные, которые можно использовать при следующих запусках программы. Таким образом, глобальный контейнер фактически является аналогом обычного файла.
Глобальные переменные требуется иногда удалять из среды. Для этого используется конструкция удаления: delete имя;
Заключение
В настоящее время определена первая версия языка и исследуются подходы к реализации интегрированной обучающей среды с этим языком программирования. Из нерешенных проблем остается определение механизма исключений и механизма событий - рассматриваются возможности объединения этих механизмов в общий механизм обработки событий. Исследуются также возможности определения в языке параллельных процессов в том или ином виде.
СПИСОК ЛИТЕРАТУРЫ
1. Лобачев А. А, Куликова О. В. Выбор языка для обучения программированию // Информационные технологии в образовании. XVIII Междунар. конф.-выставка: сб. тр. участников конф. Ч. VI. -М.: МИФИ, 2008. - С. 45-47.
2. Бельчусов А. А., Степанов А. В. Повышение эффективности обучения программированию в школе и вузе // Материалы V Всерос. науч.-практ. конф. «Проблемы информатизации образования: региональный аспект», Чебоксары, 25-27 апреля 2007 г. - Чебоксары, 2007. - С. 27-33.
3. Ведяева Е. С., Ведяева С. Ю. Возможности языков программирования Visual Basic при обучении алгоритмизации и программированию // Информационные технологии в образовании. XVIII Между-нар. конф.-выставка: сб. тр. участников конф. Ч. VI. - М.: МИФИ, 2008. - С. 19-20.
4. Онищенко В. А. Проблемы контроля знаний в компьютерном учебнике по языкам программирования // Материалы V Всерос. науч.-практ. конф. «Проблемы информатизации образования: региональный аспект», Чебоксары, 25-27 апреля 2007 г. - Чебоксары, 2007. - С. 241-245.
5. Gutknecht J., Zueff E. Zonnon Language Report. - Zurich: ETH Zentrum, 2005.
6. International Standart ISO/IEC 14882:2003(E), Programming languages - C++.
7. Пастухов А. Ю., Заболеева-Зотова А. В. Учет психолингвистических особенностей процесса чтения при разработке языков программирования // Концептуальное проектирование в образовании, технике и технологии: межвуз. сб. науч. тр. / ВолгГТУ. - Волгоград, 2001. - С. 151-155.
8. Лаптев В. В., Тырнава Али, Толасова В. В. Об унификации агрегатных типов данных при обучении программированию // Вестн. Астрахан. гос. техн. ун-та. - 2007. - № 4 (39). - С. 216-221.
Статья поступила в редакцию 22.12.2008
PROGRAMMING LANGUAGE CHARACTERISTICS FOR LEARNING
V. V. Laptev, V. V. Tolasova
The problem of choosing the programming language for training is considered in the paper. Requirements to the language are determined, and a new programming language for training is offered. Language structures have C-like syntax, but more consecutive and regular. The language supports two programming paradigms: procedural and object-oriented. One of the main features of the language is the existence of singular compound data type - the generalized container. Some interesting properties of IDE are described besides the language definition.
Key words: programming language, data type, programming paradigm, generalized container.