Содержание


Io - компактный объектно-ориентированный язык программирования

Часть 1. Обзор возможностей и синтаксиса языка Io

Comments

Серия контента:

Этот контент является частью # из серии # статей: Io - компактный объектно-ориентированный язык программирования

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Io - компактный объектно-ориентированный язык программирования

Следите за выходом новых статей этой серии.

В группе языков, основанных на парадигме объектно-ориентированного программирования, Io выделяется своей простотой и лаконичностью. Идеальных программ, полностью свободных от каких бы то ни было недостатков, не бывает, тем более, когда речь идёт о реализации языка программирования. Именно поэтому необходимо достаточно подробно изучить возможности и особенности любого языка программирования (в данном случае - Io), а также области его применения, прежде чем выносить окончательное суждение о его необходимости, эффективности, удобстве для разработчика и т.д.

История появления языка Io

Язык Io появился в 2002 году, когда его автор Стив Декорт (Steve Dekorte), пытаясь лучше понять принципы функционирования и реализации языков программирования, решил совместить теорию с практикой и написать собственный простой и лаконичный язык. Декорт спроектировал Io, как чистый объектно-ориентированный язык, основанный на прототипах, с динамической типизацией, в котором устранено различие понятий "класс" и "экземпляр". В Wikipedia отмечается влияние на Io таких языков, как Smalltalk (принцип "всё есть объект" и динамическая типизация), Self и NewtonScript (объектная модель, основанная на прототипах), Lisp (равнозначность инструкций и данных в коде программы), а также Lua и Act1.

Общие сведения

Код программ на языке Io транслируется и выполняется с помощью компактной, легко переносимой виртуальной машины. Пакеты Io для различных платформ расположены на его Web-сайте. Язык Io распространяется в соответствии с условиями лицензии BSD/MIT.

Основными свойствами данного языка, которые подчёркивает сам автор, являются концептуальная простота и лаконичность, встраиваемость (возможность объединения с кодом, написанным на других языках) и расширяемость, возможность динамически изменять внутренние объекты во время выполнения, интроспективность, а также реализация концепции параллелизма.

В Io все сущности представляют собой объекты, которые обладают возможностью изменяться во время выполнения программы. Код любой программы компонуется из выражений, которые также могут быть модифицированы в процессе выполнения программы. В свою очередь выражения фактически представляют собой инструкции передачи сообщений. Реализован механизм контекстных областей видимости объектов на уровне функций и блоков кода. Для управления параллельными вычислениями применяются акторы (actors).

Выполнение программ

В программах на языке Io не требуется обязательного присутствия функции main() или какого-либо специального объекта, с которого должно начаться выполнение. Таким образом, Io-программы в определённой степени можно считать сценариями (скриптами – англ. scripts).

Запуск программы из командной строки выполняется следующим образом:

io projects/io/my_first_prog.io

Также можно работать в интерактивном режиме интерпретатора Io, как показано в листинге 1.

Листинг 1. Использование интерпретатора Io в интерактивном режиме
$ io
Io 20070410
Io> "It's Io interpreter" println
It's Io interpreter
==> It's Io interpreter
Io>

В интерактивном режиме выводится не только результат выполнения введённого выражения, но и возвращаемое этим выражением значение, обозначаемое префиксом "==>". В данном случае результат выполнения выражения совпадает с возвращаемым значением.

Следует отметить, что в интерактивном режиме вводимые выражения выполняются в общем контексте верхнего уровня, соответствующем объекту с именем Lobby.

Листинг 2. Содержимое контекста верхнего уровня Io-программы
$ io
Io 20070410
Io> print
 Object_0x9898a88:
  Lobby            = Object_0x9898a88
  Protos           = Object_0x9898550
  args             = method(...)
  exit             = method(...)
  forward          = method(...)
  launchPath       = "/home/alexs/projects/io"
==>  Object_0x9898a88:
  Lobby            = Object_0x9898a88
  Protos           = Object_0x9898550
  args             = method(...)
  exit             = method(...)
  forward          = method(...)
  launchPath       = "/home/alexs/projects/io"
Io>

В интерактивном режиме также можно выполнять программы, которые хранятся в отдельных файлах, как показано ниже:

doFile("my_first_prog.io")

Указанная программа по умолчанию будет выполнена в контексте всё того же объекта Lobby. Если необходимо выполнить загружаемую программу в контексте какого-либо другого объекта, то имя этого объекта указывается перед вызовом метода doFile(), а в терминах языка Io - объекту передаётся сообщение:

myMainObject doFile("my_first_prog.io")

Синтаксис языка Io

Первое, что обращает на себя внимание при ознакомлении с синтаксисом языка Io, - это отсутствие зарезервированных ключевых слов и операторов, знакомых по другим языкам. Исходный код любой программы записывается исключительно с помощью выражений, составляемых из сообщений, каждое из которых представляет собой объект, доступный (и изменяемый) в любой момент выполнения программы.

Для большей ясности можно воспользоваться нестрогой нотацией формы Бэкуса-Наура (в кавычках записаны литералы), приведенной в листинге 3.

Листинг 3. Нотация языка Io
выражение  ::= { сообщение | терминатор }
терминатор ::= "\n" | ";"
сообщение  ::= символ [ аргументы ]
символ     ::= идентификатор | число | строка
аргументы  ::= "(" [выражение [ { "," выражение } ] ] ")"

В языке Io поддерживаются три наиболее широко используемых формата комментариев: //, /* */ и #. Способы их практического применения очевидны.

Сообщение может включать список аргументов, которые передаются, как обычные выражения, и вычисляются объектом, принимающим сообщение.

Листинге 4. Использование сообщения для организации цикла
Io> for( i, 1, 5, i println )
1
2
3
4
5
==> 5
Io>

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

Листинг 5. Использование условных выражений в сообщении
Io> beta := 7
==> 7
Io> alpha := if( beta > 5, beta, 5 )
==> 7
Io>

Следует ещё раз обратить внимание на то, что в первом случае литерал for и во втором случае литерал if не являются специальными формами или зарезервированными ключевыми словами, а представляют собой просто сообщения.

Операторы, доступные в языке Io

Оператор – это сообщение, в имени которого отсутствуют алфавитно-цифровые символы (за исключением знаков препинания и символа подчёркивания). К операторам также относятся литералы: and, or, return. Пример использования оператора:

1 + 2

В соответствии с концепцией языка Io это выражение компилируется в сообщение:

1 +(2)

То есть, числовому значению 1 передаётся сообщение "+" с аргументом 2.

В сложных выражениях приоритет стандартных арифметических операторов соответствует приоритету аналогичных арифметических операторов языка C.

Операторы, определённые пользователем, выполняются слева направо.

В языке Io существуют три оператора присваивания:

  • ::= создаёт слот, создаёт set-метод для этого слота и присваивает слоту значение;
  • := создаёт слот и присваивает ему значение;
  • = если слот существует, то ему присваивается значение, в противном случае генерируется исключение.

Операторы присваивания при компиляции преобразовываются в соответствующие сообщения, как показано ниже:

beta ::= 7 компилируется в newSlot( "beta", 7 )
beta := 7  компилируется в setSlot( "beta", 7 )
beta = 7   компилируется в updateSlot( "beta", 7 )

Методы перечисленных выше сообщений можно переопределять (то есть заменять на свои методы). В частности, для локальных объектов методы updateSlot() переписываются таким образом, чтобы не возникало исключений в случаях присваивания значений слотам этих локальных объектов, указанных в явной форме.

Работа со строками

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

string := "В Io отсутствует понятие \"ключевое слово\", как таковое."

В строке могут быть записаны стандартные Esc-символы (\n, \t, \a и т.д.):

string := "Это первая строка.\nЭто вторая строка.\nЭто третья строка."

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

longstring := """Язык Io основан на концепции "всё есть объект".
Исходный код - выражения, состоящие из сообщений.
Операторы тоже являются сообщениями."""

Числовые значения

При записи чисел допускается применение практически всех стандартных форматов, также в Io поддерживается запись числовых значений в шестнадцатеричном представлении.

Листинг 6. Числовые форматы, поддерживаемые в языке Io
Io> 12 + 18
==> 30
Io> 3.14 * 2
==> 6.2800000000000002
Io> .987 + 11.003
==> 11.9900000000000002
Io> 2e4 - 2e3
==> 18000
Io> 1.655e-3 - 5.112e-4
==> 0.0011438
Io> 0xFF + 0x3
==> 258
Io> 0XE - 0xa
==> 4
Io>

Арифметические выражения вычисляются по традиционной методике, несмотря на то, что операторы, обозначающие арифметические действия, внутри интерпретатора преобразовываются в вызовы соответствующих методов (этот механизм скрыт от пользователя):

Io> (9+5)*10-(2+3)*5
==> 115

Для передачи результата вычислений в какой-либо объект используется метод doString(), как показано в листинге 7.

Листинг 7. Использование метода doString()
Io> myNewObject := Object clone
==>  Object_0x99336f0:
Io> myNewObject doString("(18+25)*33")
==> 1419
Io>

Если перед вызовом метода doString() не указывается имя объекта, то вычисление и вывод результата выполняется в текущем контексте.

Пример Io-программы

В большинстве случаев лучше понять особенности синтаксиса языка программирования помогает исходный код программы, не очень большой по размеру и без излишних сложностей в логике. Упрощённая имитация операций с личным банковским счётом вполне подходит для первого опыта. Исходный код приведён в листинге 8.

Листинг 8. Операции с личным счётом
Account := Object clone
Account balance := 0
Account deposit := method( amount, balance = balance + amount )
Account withdraw := method( amount, balance = balance - 1.005 * amount )
account := Account clone
account deposit( 5000.00 )
account withdraw( 250.00 )
account balance println

Если приведённый в листинге 1 код сохранить в файле с именем my_acc.io, а затем попытаться выполнить его в интерпретаторе io, то результат будет выглядеть приблизительно так:

Io> doFile("my_acc.io")
4748.75
==> 4748.75
Io>

В этой программе использованы практически все элементы синтаксиса, описанные в предыдущих разделах, - сообщения, операторы присваивания и арифметические операторы, числовые значения. Создание и использование объектов, слотов и методов будет рассмотрено во второй статье цикла, а в данный момент достаточно их понимания на интуитивном уровне.

Управляющие конструкции

Для обеспечения работы логических управляющих конструкций в языке Io определены специальные синглтоны (singleton) true (истина) и false (ложь), а также особый синглтон nil, обозначающий неопределённое значение ("отсутствие значения").
Операции логического сравнения выполняются с помощью методов: ==!=><>=<=, которые возвращают true или false. Кроме того, существует метод compare(), возвращающий значения -1 (меньше), 0 (равно) или 1 (больше) и применяемый для реализации специализированных методов сравнения значений.

Метод if() используется в следующей форме:

if( <условие>,		<true-сообщение>[, else <false-сообщение>] )
if( denominator == 0,	"Error" println )

Здесь необязательная часть else опущена. Условное выражение считается истинным, если его результатом является true, а если условное выражение даёт результат false или nil, то оно ложно.

Метод if() возвращает в качестве значения сообщение, вычисленное по результату проверки, поэтому выражения, представленные ниже, являются эквивалентными:

if( sum < 100, x := sum, x := 100 )

и

x := if( sum < 100, sum, 100 )

Условные выражения можно также записывать в более развёрнутой форме:

if( sum < 100 ) then( x := sum ) else( x := 100 )

Кроме того, поддерживается метод для вложения условных выражений elseif():

if( sum < 10 ) then( x := 0 ) elseif( sum < 10 ) then( x := 1 ) else ( x := sum )

Также поддерживаются методы в стиле языка Smalltalk: ifTrue(), ifFalse(), ifNil() и ifNonNil(), позволяющие записывать выражения в форме:

( sum < 100 ) ifTrue( x := sum ) ifFalse( x := 100 )

Здесь следует обратить особое внимание на то, что начальное условное выражение обязательно должно быть записано в круглых скобках.

Циклы

Самый простой тип цикла - безусловный бесконечный цикл, реализуемый с помощью метода loop():

loop( "infinite loop" println )

Если цикл должен быть повторён строго определённое количество раз без проверки каких-либо условий, то применяется метод repeat(), как показано в листинге 9.

Листинг 9. Использование метода repeat()
Io> 3 repeat( "Warning!" println )
Warning!
Warning!
Warning!
==> Warning!
Io>

Цикл, точное количество повторений которого заранее неизвестно, но задано определённое условие, при котором итерации должны выполняться, записывается с помощью метода while():

while( <условное_выражение>, <сообщение> )

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

Листинг 10. Пример организации цикла while
Io> a := 10
==> 10
Io> while( a < 20,
)-> a println
)-> a = a + 2
)-> )
10
12
14
16
18
==> 20
Io>

Метод for() позволяет организовать цикл с определёнными граничными значениями и с заданным шагом счётчика. Общая форма записи этого цикла выглядит так:

for( <счётчик>, <начальное_значение>, <конечное_значение>, [<шаг>,] <сообщение> ).

Если шаг изменения счётчика не указан, то по умолчанию принимается значение шага, равное 1.

Листинг 11. Пример организации цикла for
//в этом цикле шаг изменения счетчика не указан
Io> for( i, 0, 3, i println )
0
1
2
3
==> 3
//в данном цикле указан шаг изменения счетчика
Io> for( i, 0, 10, 3, i println )
0
3
6
9
==> 9
Io>

В теле любого из выше перечисленных циклов можно использовать методы изменения порядка выполнения: continue позволяет игнорировать оставшуюся часть тела цикла и начать новую итерацию, а break немедленно завершает выполнение всего цикла.

Листинг 12. Управление порядком выполнения цикла
Io> for( i, 1, 10,
)-> if( i == 2, continue )
)-> if( i > 7, break )
)-> i print
)-> )
134567==> nil
Io>

Следует отметить, что при нестандартном завершении цикла (с помощью метода break) возвращаемое значение считается неопределённым (обозначается, как nil).

Метод return позволяет осуществить выход из любой части блока кода или тела метода с требуемым возвращаемым значением, например:

Листинг 13. Использование метода return для возврата значения из метода
Io> test := method( "first" println; "second" println; return "exit"; "third" println )
==> method(
    "first" println; "second" println; return "exit"; "third" println
)
Io> test
first
second
==> exit
Io>

В языке Io реализован также цикл foreach, но его практическое применение несколько отличается от применения традиционных циклов, поэтому этот цикл будет рассматриваться в следующих статьях.

Заключение

Язык Io представляет собой чистый объектный язык, то есть реализацию концепции "всё есть объект". Его синтаксис прост и ясен, хотя на первый взгляд и может показаться непривычным. В Io реализованы все считающиеся де-факто стандартными конструкции и операторы.

В первой статье цикла были описаны общие характеристики и синтаксис языка программирования Io. Во второй статье будет рассматриваться объектная система языка, а в третьей статье - дополнительные средства и возможности Io.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=766449
ArticleTitle=Io - компактный объектно-ориентированный язык программирования: Часть 1. Обзор возможностей и синтаксиса языка Io
publish-date=10182011