Введение, или краткий обзор — различия между версиями

Материал из Deeptown Manual
Перейти к: навигация, поиск
(Здравствуй, мир!)
Строка 25: Строка 25:
 
;5-8: Наконец, объявляется функция <tt>main()</tt>, которая вызывает метод <tt>print()</tt> объекта ''STDOUT'', передав ему строку "Hello, world!\n" в качестве параметра.
 
;5-8: Наконец, объявляется функция <tt>main()</tt>, которая вызывает метод <tt>print()</tt> объекта ''STDOUT'', передав ему строку "Hello, world!\n" в качестве параметра.
  
: Ключевое слово <tt>'''export'''</tt> говорит о том, что имя функции не следует декорировать. Декорирование имен применяется для того, чтобы дать возможность [[Функции#Перегрузка функций и операторов|перегружать функции]] с одинаковыми именами но разными списками параметров (или параметрами разных типов).
+
: Ключевое слово <tt>'''export'''</tt> говорит о том, что имя функции не следует декорировать. Декорирование имен применяется для того, чтобы дать возможность [[Функции#Перегрузка функций и операторов|перегружать функции]] с одинаковыми именами, но разными списками параметров (или параметрами разных типов).
  
  
Строка 52: Строка 52:
 
Смысл этой программы понятен интуитивно: создается два массива — исходный (''ary'') и результирующий (''sums''), и затем массив ''sums'' заполняется суммами чисел из массива ''ary'' от 0 до текущего индекса i.
 
Смысл этой программы понятен интуитивно: создается два массива — исходный (''ary'') и результирующий (''sums''), и затем массив ''sums'' заполняется суммами чисел из массива ''ary'' от 0 до текущего индекса i.
  
;5-6: Особое внимание в этом примере следует уделить объявлениям переменных. Мы видим, что объявляются два [[Стандартные типы данных#Массивы|массива]] — ''ary'' и ''sums'',  причем в инструкции <tt>'''var'''</tt> их тип никак не указывается. В этом случае работает следующее правило: если при объявлении переменной ее тип не указан, то типом переменной становится тип результата инициализатора переменной, т.е. выражения, стоящего справа от отператора '='.
+
;5-6: Особое внимание в этом примере следует уделить объявлениям переменных. Мы видим, что объявляются два [[Стандартные типы данных#Массивы|массива]] — ''ary'' и ''sums'',  причем в инструкции <tt>'''var'''</tt> их тип никак не указывается. В этом случае работает следующее правило: если при объявлении переменной ее тип не указан, то типом переменной становится тип результата инициализатора переменной, т.е. выражения, стоящего справа от оператора '='.
  
:Выражения, записанные в квадратных скобках через запятую — это встроенная в K++ конструкция, создающая объект, имеющий тип <tt>[[Стандартные типы данных#Массивы|array]]</tt> (объявленный в [[Стандартная билбиотека gide|стандартной библиотеке]]) и заполненный соответствующими значениями.
+
:Выражения, записанные в квадратных скобках через запятую — это встроенная в K++ конструкция, создающая объект, имеющий тип <tt>[[Стандартные типы данных#Массивы|array]]</tt> (объявленный в [[Стандартная библиотека gide|стандартной библиотеке]]) и заполненный соответствующими значениями.
  
:Оператор <tt>'''new'''</tt> создает экземпляр произвольного класса — здесь мог бы стоять в том числе и пользовательский класс. В данном случае <tt>'''new'''</tt> создает экземпляр класса <tt>[[Стандартные типы данных#Массивы|array]]</tt>.
+
:Оператор <tt>'''new'''</tt> создает экземпляр произвольного класса — здесь мог бы стоять, в том числе, и пользовательский класс. В данном случае <tt>'''new'''</tt> создает экземпляр класса <tt>[[Стандартные типы данных#Массивы|array]]</tt>.
  
 
;7: Здесь мы создаем переменную типа <tt>[[Стандартные типы данных#Целые числа|int]]</tt>. Когда тип указан в самой конструкции <tt>'''var'''</tt> — объект соответствующего класса создается автоматически. Таким образом, например, следующие объявления эквивалентны:
 
;7: Здесь мы создаем переменную типа <tt>[[Стандартные типы данных#Целые числа|int]]</tt>. Когда тип указан в самой конструкции <tt>'''var'''</tt> — объект соответствующего класса создается автоматически. Таким образом, например, следующие объявления эквивалентны:

Версия 11:47, 1 октября 2007

Содержание


(Введение...)

Здравствуй, мир!

Классический пример программы, выводящей строку "Hello, world!" на экран, на языке K++ выглядит следующим образом:

<source lang="kpp" line="1"> package hello_world;

external console_stream STDOUT;

export function void main() {

   STDOUT.print("Hello, world!\n");

} </source>


1
Как уже отмечалось ранее, в K++ любая программа или библиотека является модулем. Ключевое слово package используется для объявления имени модуля, в который должна быть скомпилирована программа.
3
Здесь мы объявляем глобальную переменную STDOUT, имеющую тип console_stream. Ключевое слово external помечает переменную как внешнюю — т.е. создаваемую пользователем.
5-8
Наконец, объявляется функция main(), которая вызывает метод print() объекта STDOUT, передав ему строку "Hello, world!\n" в качестве параметра.
Ключевое слово export говорит о том, что имя функции не следует декорировать. Декорирование имен применяется для того, чтобы дать возможность перегружать функции с одинаковыми именами, но разными списками параметров (или параметрами разных типов).


Теперь несколько слов о том, как такая программа будет запущена. В первую очередь стоит отметить, что нет никаких стандартов на имя функции main() или объекта STDOUT. На платформе Gide каждая программа является библиотекой, и порядок ее использования полностью определяется пользователем. В данном случае предполагается, что программа будет запускаться при помощи консольной команды gide.run, реализованной в модуле стандартной библиотеки. Эта команда определяет три глобальные переменные STDIN, STDOUT и STDERR, имеющие тип console_stream и запускает функцию main(), экспортируемую программой.

Если бы мы, скажем, писали программу, генерирующую текстуру — никакой функции main() в ней не было бы. Набор экспортируемых ей функций полностью определялся бы требованиями генератора текстур, которые описаны в соответствующей документации.

Более сложный пример

Вот более сложный пример, демонстрирующий использование переменных и циклов:

<source lang="kpp" line="1"> package sums;

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;

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. Впрочем, тип параметра функции можно опустить — в этом случае будет сгенерирован динамический код.

14
В функции 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;

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>


5-12
Оператор extend расширяет функционал класса — в данном случае класса int. Его использование аналогично объявлению класса, но объявленные внутри поля, методы и операторы будут добавлены к уже существующему классу.
Таким образом, к классу int, объявленному в стандартной библиотеке, добавляется метод times(), вызывающий связанный блок количество раз, равное текущему числу (не забываем: мы добавляем метод в класс int, который отвечает за хранение числа).
16
После такого объявления, в функции main() мы используем уже метод times() класса int: конструкция 3.times() означает создание объекта 3 класса int и вызов у этого объекта метода times().


Примечание: Расширение будет работать во всем модуле, а так же во всех модулях, которые импортируют данный модуль.

Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
информация
документация
Инструменты