Введение, или краткий обзор — различия между версиями
Korvin (обсуждение | вклад) м (→Расширение классов) |
Korvin (обсуждение | вклад) м |
||
Строка 21: | Строка 21: | ||
Как уже [[Модули|отмечалось ранее]], в K++ любая программа или библиотека является модулем. Первая строчка данной программы задает имя модуля, в который будет скомпилирована программа. | Как уже [[Модули|отмечалось ранее]], в K++ любая программа или библиотека является модулем. Первая строчка данной программы задает имя модуля, в который будет скомпилирована программа. | ||
− | Стандартные типы данных, такие как строки, целые числа, а также класс console_stream, объявлены в модуле std — третья строчка программы подключает этот модуль. | + | Стандартные типы данных, такие как строки, целые числа, а также класс <tt>console_stream</tt>, объявлены в модуле <tt>[[Стандартная библиотека gide|std]]</tt> — третья строчка программы подключает этот модуль. |
Теперь несколько слов о том, как такая программа будет запущена. | Теперь несколько слов о том, как такая программа будет запущена. | ||
− | В первую очередь стоит отметить, что нет никаких стандартов на имя функции main или объекта STDOUT. На платформе Gide каждая программа является библиотекой, и порядок ее использования полностью определяется пользователем. В данном случае предполагается, что программа будет запускаться при помощи консольной команды '''gide.run''', реализованной в модуле стандартной библиотеки. Эта команда определяет три глобальные переменные STDIN, STDOUT и STDERR, имеющие тип console_stream | + | В первую очередь стоит отметить, что нет никаких стандартов на имя функции <tt>main()</tt> или объекта <tt>STDOUT</tt>. На платформе Gide каждая программа является библиотекой, и порядок ее использования полностью определяется пользователем. В данном случае предполагается, что программа будет запускаться при помощи консольной команды '''gide.run''', реализованной в модуле стандартной библиотеки. Эта команда определяет три глобальные переменные <tt>STDIN</tt>, <tt>STDOUT</tt> и <tt>STDERR</tt>, имеющие тип <tt>console_stream</tt> и запускает функцию <tt>main()</tt>, экспортируемую программой. |
− | Если бы мы, скажем, писали бы программу, генерирующую текстуру — никакой функции main в ней не было бы. Набор экспортируемых ей функций полностью определялся бы требованиями генератора текстур, которые описаны в соответствующей документации. | + | Если бы мы, скажем, писали бы программу, генерирующую текстуру — никакой функции <tt>main()</tt> в ней не было бы. Набор экспортируемых ей функций полностью определялся бы требованиями генератора текстур, которые описаны в соответствующей документации. |
− | Четвертая строчка программы объявляет глобальную переменную STDOUT, имеющую тип console_stream, как внешнюю — т.е. создаваемую пользователем. | + | Четвертая строчка программы объявляет глобальную переменную <tt>STDOUT</tt>, имеющую тип <tt>console_stream</tt>, как внешнюю — т.е. создаваемую пользователем. |
− | И, наконец, строки 6-9 задают функцию main, которая вызывает метод print объекта STDOUT, передав ему строку "Hello, world!\n" в качестве параметра. | + | И, наконец, строки 6-9 задают функцию <tt>main()</tt>, которая вызывает метод <tt>print()</tt> объекта <tt>STDOUT</tt>, передав ему строку "Hello, world!\n" в качестве параметра. |
− | Ключевое слово export говорит о том, что имя функции не следует декорировать. Декорирование имен применяется для того, чтобы дать возможность перезагружать функции с одинаковыми именами но разными типами параметров. | + | Ключевое слово <tt>'''export'''</tt> говорит о том, что имя функции не следует декорировать. Декорирование имен применяется для того, чтобы дать возможность перезагружать функции с одинаковыми именами но разными типами параметров. |
== Более сложный пример == | == Более сложный пример == | ||
Строка 53: | Строка 53: | ||
</source> | </source> | ||
− | Смысл этой программы понятен интуитивно: создается два массива — исходный (ary) и результирующий (sums), и затем массив sums заполняется суммами чисел из массива ary от 0 до текущего индекса i. | + | Смысл этой программы понятен интуитивно: создается два массива — исходный (''ary'') и результирующий (''sums''), и затем массив ''sums'' заполняется суммами чисел из массива ''ary'' от 0 до текущего индекса i. |
− | Особое внимание в этом примере следует уделить объявлениям переменных. В строках 5 и 6 объявляются два массива — ary и sums — причем в инструкции var их тип никак не указывается. В этом случае работает следующее правило: если при объявлении переменной ее тип не указан, то типом переменной становится тип результата инициализатора переменной | + | Особое внимание в этом примере следует уделить объявлениям переменных. В строках 5 и 6 объявляются два массива — ''ary'' и ''sums'' — причем в инструкции <tt>'''var'''</tt> их тип никак не указывается. В этом случае работает следующее правило: если при объявлении переменной ее тип не указан, то типом переменной становится тип результата инициализатора переменной, т.е. выражения, стоящего справа от отператора '='. |
− | Выражения, записанные в квадратных скобках через запятую — это встроенная в K++ конструкция, создающая объект, имеющий тип array (объявленный в стандартной библиотеке) и заполненный соответствующими значениями. | + | Выражения, записанные в квадратных скобках через запятую — это встроенная в K++ конструкция, создающая объект, имеющий тип <tt>array</tt> (объявленный в стандартной библиотеке) и заполненный соответствующими значениями. |
− | Оператор new создает экземпляр произвольного класса — здесь мог бы стоять в том числе и пользовательский класс. В данном случае new создает экземпляр класса array. | + | Оператор <tt>'''new'''</tt> создает экземпляр произвольного класса — здесь мог бы стоять в том числе и пользовательский класс. В данном случае <tt>'''new'''</tt> создает экземпляр класса <tt>array</tt>. |
− | Третья инструкция (строка 7) создает переменную типа int. Когда тип указан в самой конструкции var — объект соответствующего класса создается автоматически. Таким образом, например, следующие объявления эквивалентны: | + | Третья инструкция (строка 7) создает переменную типа <tt>[[Стандартные типы данных#Целые числа|int]]</tt>. Когда тип указан в самой конструкции <tt>'''var'''</tt> — объект соответствующего класса создается автоматически. Таким образом, например, следующие объявления эквивалентны: |
<source lang="kpp"> | <source lang="kpp"> | ||
Строка 77: | Строка 77: | ||
</source> | </source> | ||
− | Метод push класса array добавляет элемент в конец массива; size — возвращает количество элементов массива. Дальнейший код, думаю, объяснять не стоит. | + | Метод <tt>push()</tt> класса <tt>array</tt> добавляет элемент в конец массива; <tt>size()</tt> — возвращает количество элементов массива. Дальнейший код, думаю, объяснять не стоит. |
== Использование блоков == | == Использование блоков == | ||
Строка 110: | Строка 110: | ||
Данный пример также демонстрирует объявление параметров функции: это делается в стиле языка C. Впрочем, тип параметра функции можно опустить — в этом случае будет сгенерирован [[Переменные#Динамическая типизация на примере Ruby|динамический код]]. | Данный пример также демонстрирует объявление параметров функции: это делается в стиле языка C. Впрочем, тип параметра функции можно опустить — в этом случае будет сгенерирован [[Переменные#Динамическая типизация на примере Ruby|динамический код]]. | ||
− | В функции main используется специальный синтаксис для вызова функции times: тело блока идет сразу после оператора вызова функции. Такой синтаксис работает только в том случае, если параметр—блок объявлен последним. | + | В функции <tt>main()</tt> используется специальный синтаксис для вызова функции <tt>times()</tt>: тело блока идет сразу после оператора вызова функции. Такой синтаксис работает только в том случае, если параметр—блок объявлен последним. |
Можно было бы переписать эту конструкцию так: | Можно было бы переписать эту конструкцию так: |
Версия 11:29, 7 сентября 2007
Содержание |
(Введение...)
Здравствуй, мир!
Классический пример программы, выводящей строку "Hello, world!" на экран, на языке K++ выглядит следующим образом:
<source lang="kpp" line="1"> package hello_world;
import std; external console_stream STDOUT;
export function void main() {
STDOUT.print("Hello, world!\n");
} </source>
Как уже отмечалось ранее, в K++ любая программа или библиотека является модулем. Первая строчка данной программы задает имя модуля, в который будет скомпилирована программа.
Стандартные типы данных, такие как строки, целые числа, а также класс console_stream, объявлены в модуле std — третья строчка программы подключает этот модуль.
Теперь несколько слов о том, как такая программа будет запущена.
В первую очередь стоит отметить, что нет никаких стандартов на имя функции main() или объекта STDOUT. На платформе Gide каждая программа является библиотекой, и порядок ее использования полностью определяется пользователем. В данном случае предполагается, что программа будет запускаться при помощи консольной команды gide.run, реализованной в модуле стандартной библиотеки. Эта команда определяет три глобальные переменные STDIN, STDOUT и STDERR, имеющие тип console_stream и запускает функцию main(), экспортируемую программой.
Если бы мы, скажем, писали бы программу, генерирующую текстуру — никакой функции main() в ней не было бы. Набор экспортируемых ей функций полностью определялся бы требованиями генератора текстур, которые описаны в соответствующей документации.
Четвертая строчка программы объявляет глобальную переменную STDOUT, имеющую тип console_stream, как внешнюю — т.е. создаваемую пользователем.
И, наконец, строки 6-9 задают функцию main(), которая вызывает метод print() объекта STDOUT, передав ему строку "Hello, world!\n" в качестве параметра.
Ключевое слово export говорит о том, что имя функции не следует декорировать. Декорирование имен применяется для того, чтобы дать возможность перезагружать функции с одинаковыми именами но разными типами параметров.
Более сложный пример
Вот более сложный пример, демонстрирующий использование переменных и циклов:
<source lang="kpp" line="1"> package sums; import std; export function void main() {
var ary = [ 1, 2, 3, 4 ]; var sums = new array; var int i; sums.push(ary[0]); for(i = 1; i < ary.size(); ++i) sums.push(sums[i-1] + ary[i]);
} </source>
Смысл этой программы понятен интуитивно: создается два массива — исходный (ary) и результирующий (sums), и затем массив sums заполняется суммами чисел из массива ary от 0 до текущего индекса i.
Особое внимание в этом примере следует уделить объявлениям переменных. В строках 5 и 6 объявляются два массива — ary и sums — причем в инструкции var их тип никак не указывается. В этом случае работает следующее правило: если при объявлении переменной ее тип не указан, то типом переменной становится тип результата инициализатора переменной, т.е. выражения, стоящего справа от отператора '='.
Выражения, записанные в квадратных скобках через запятую — это встроенная в K++ конструкция, создающая объект, имеющий тип array (объявленный в стандартной библиотеке) и заполненный соответствующими значениями.
Оператор new создает экземпляр произвольного класса — здесь мог бы стоять в том числе и пользовательский класс. В данном случае new создает экземпляр класса array.
Третья инструкция (строка 7) создает переменную типа int. Когда тип указан в самой конструкции var — объект соответствующего класса создается автоматически. Таким образом, например, следующие объявления эквивалентны:
<source lang="kpp"> var sums = new array; var sums = [ ]; var array sums; </source>
или
<source lang="kpp"> var i = 0; var i = new int; var int i; </source>
Метод push() класса array добавляет элемент в конец массива; size() — возвращает количество элементов массива. Дальнейший код, думаю, объяснять не стоит.
Использование блоков
Подобно языку Ruby, в K++ реализован механизм передачи в качестве параметра функции некоторого связанного (с вызовом) блока кода. Функция затем может вызвать этот блок один или более раз, и воспользоваться результатом, который он возвращает.
Выглядит это следующим образом:
<source lang="kpp" line="1"> package block_demo; import std; external console_stream STDOUT;
function void times(int i, block b) {
var int n; for(n = 0; n < i; ++n) b(n);
}
export function void main() {
times(3) { |i| STDOUT.print((i as string) + " "); }; STDOUT.print("\n");
} </source>
Результат выполнения программы:
0 1 2
Данный пример также демонстрирует объявление параметров функции: это делается в стиле языка C. Впрочем, тип параметра функции можно опустить — в этом случае будет сгенерирован динамический код.
В функции main() используется специальный синтаксис для вызова функции times(): тело блока идет сразу после оператора вызова функции. Такой синтаксис работает только в том случае, если параметр—блок объявлен последним.
Можно было бы переписать эту конструкцию так:
<source lang="kpp"> var b = { |i| STDOUT.print((i as string) + " "); }; times(3,b); </source>
Параметры блока могут быть перечислены между символами "|" через запятую. В данном случае блок принимает один параметр — номер итерации.
Расширение классов
Приведенный выше пример можно переписать следующим образом:
<source lang="kpp" line="1"> package extend_demo; import std; external console_stream STDOUT;
extend int {
public const function void times(block b) { var int n; for(n = 0; n < this; ++n) b(n); }
}
export function void main() {
3.times() { |i| STDOUT.print((i as string) + " "); }; STDOUT.print("\n");
} </source>
Оператор extend расширяет функционал класса — в данном случае класса int. Его использование аналогично объявлению класса, но объявленные внутри поля, методы и операторы будут добавлены к уже существующему классу.
Таким образом, к классу int, объявленному в стандартной библиотеке, добавляется метод times(), вызывающий связанный блок количество раз, равное текущему числу (не забываем: мы добавляем метод в класс int, который отвечает за хранение числа).
После такого объявления, в функции main() мы используем уже метод times класса int: конструкция 3.times() означает создание объекта 3 класса int и вызов у этого объекта метода times().
Примечание: Расширение будет работать во всем модуле, а так же во всех модулях, которые импортируют данный модуль.