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

Материал из Deeptown Manual
Перейти к: навигация, поиск
м
Строка 20: Строка 20:
 
Как уже [[Модули|отмечалось ранее]], в K++ любая программа или библиотека является модулем. Первая строчка данной программы задает имя модуля, в который будет скомпилирована программа.
 
Как уже [[Модули|отмечалось ранее]], в K++ любая программа или библиотека является модулем. Первая строчка данной программы задает имя модуля, в который будет скомпилирована программа.
  
Стандартные типы данных, такие как строки, целые числа, а также класс console_stream, объявлены в модуле std - третья строчка программы подключает этот модуль.
+
Стандартные типы данных, такие как строки, целые числа, а также класс console_stream, объявлены в модуле std третья строчка программы подключает этот модуль.
  
 
Теперь несколько слов о том, как такая программа будет запущена.
 
Теперь несколько слов о том, как такая программа будет запущена.
Строка 26: Строка 26:
 
В первую очередь стоит отметить, что нет никаких стандартов на имя функции main или объекта STDOUT. На платформе Gide каждая программа является библиотекой, и порядок ее использования полностью определяется пользователем. В данном случае предполагается, что программа будет запускаться при помощи консольной команды '''gide.run''', реализованной в модуле стандартной библиотеки. Эта команда определяет три глобальные переменные STDIN, STDOUT и STDERR, имеющие тип console_stream, и запускает функцию main, экспортируемую программой.
 
В первую очередь стоит отметить, что нет никаких стандартов на имя функции main или объекта STDOUT. На платформе Gide каждая программа является библиотекой, и порядок ее использования полностью определяется пользователем. В данном случае предполагается, что программа будет запускаться при помощи консольной команды '''gide.run''', реализованной в модуле стандартной библиотеки. Эта команда определяет три глобальные переменные STDIN, STDOUT и STDERR, имеющие тип console_stream, и запускает функцию main, экспортируемую программой.
  
Если бы мы, скажем, писали бы программу, генерирующую текстуру - никакой функции main в ней не было бы. Набор экспортируемых ей функций полностью определялся бы требованиями генератора текстур, которые описаны в соответствующей документации.
+
Если бы мы, скажем, писали бы программу, генерирующую текстуру никакой функции main в ней не было бы. Набор экспортируемых ей функций полностью определялся бы требованиями генератора текстур, которые описаны в соответствующей документации.
  
Четвертая строчка программы объявляет глобальную переменную STDOUT, имеющую тип console_stream, как внешнюю - т.е. создаваемую пользователем.
+
Четвертая строчка программы объявляет глобальную переменную STDOUT, имеющую тип console_stream, как внешнюю т.е. создаваемую пользователем.
  
 
И, наконец, строки 6-9 задают функцию main, которая вызывает метод print объекта STDOUT, передав ему строку "Hello, world!\n" в качестве параметра.
 
И, наконец, строки 6-9 задают функцию main, которая вызывает метод print объекта STDOUT, передав ему строку "Hello, world!\n" в качестве параметра.
Строка 50: Строка 50:
 
  }
 
  }
  
Смысл этой программы понятен интуитивно: создается два массива - исходный (ary) и результирующий (sums), и затем массив sums заполняется суммами чисел из массива ary от 0 до текущего индекса i.
+
Смысл этой программы понятен интуитивно: создается два массива исходный (ary) и результирующий (sums), и затем массив sums заполняется суммами чисел из массива ary от 0 до текущего индекса i.
  
Особое внимание в этом примере следует уделить объявлениям переменных. В строках 5 и 6 объявляются два массива - ary и sums - причем в инструкции var их тип никак не указывается. В этом случае работает следующее правило: если при объявлении переменной ее тип не указан, то типом переменной становится тип результата инициализатора переменной (т.е. выражения, стоящего справа от =).
+
Особое внимание в этом примере следует уделить объявлениям переменных. В строках 5 и 6 объявляются два массива ary и sums причем в инструкции var их тип никак не указывается. В этом случае работает следующее правило: если при объявлении переменной ее тип не указан, то типом переменной становится тип результата инициализатора переменной (т.е. выражения, стоящего справа от =).
  
Выражения, записанные в квадратных скобках через запятую - это встроенная в K++ конструкция, создающая объект, имеющий тип array (объявленный в стандартной библиотеке) и заполненный соответствующими значениями.
+
Выражения, записанные в квадратных скобках через запятую это встроенная в K++ конструкция, создающая объект, имеющий тип array (объявленный в стандартной библиотеке) и заполненный соответствующими значениями.
  
Оператор new создает экземпляр произвольного класса - здесь мог бы стоять в том числе и пользовательский класс. В данном случае new создает экземпляр класса array.
+
Оператор new создает экземпляр произвольного класса здесь мог бы стоять в том числе и пользовательский класс. В данном случае new создает экземпляр класса array.
  
Третья инструкция (строка 7) создает переменную типа int. Когда тип указан в самой конструкции var - объект соответствующего класса создается автоматически. Таким образом, например, следующие объявления эквивалентны:
+
Третья инструкция (строка 7) создает переменную типа int. Когда тип указан в самой конструкции var объект соответствующего класса создается автоматически. Таким образом, например, следующие объявления эквивалентны:
  
 
  var sums = new array;
 
  var sums = new array;
Строка 70: Строка 70:
 
  var int i;
 
  var int i;
  
Метод push класса array добавляет элемент в конец массива; size - возвращает количество элементов массива. Дальнейший код, думаю, объяснять не стоит.
+
Метод push класса array добавляет элемент в конец массива; size возвращает количество элементов массива. Дальнейший код, думаю, объяснять не стоит.
  
 
== Использование блоков ==
 
== Использование блоков ==
Строка 99: Строка 99:
 
  0 1 2
 
  0 1 2
  
Данный пример также демонстрирует объявление параметров функции: это делается в стиле языка C. Впрочем, тип параметра функции можно опустить - в этом случае будет сгенерирован [[Переменные#Динамическая типизация на примере Ruby|динамический код]].
+
Данный пример также демонстрирует объявление параметров функции: это делается в стиле языка C. Впрочем, тип параметра функции можно опустить в этом случае будет сгенерирован [[Переменные#Динамическая типизация на примере Ruby|динамический код]].
  
В функции main используется специальный синтаксис для вызова функции times: тело блока идет сразу после оператора вызова функции. Такой синтаксис работает только в том случае, если параметр-блок объявлен последним.
+
В функции main используется специальный синтаксис для вызова функции times: тело блока идет сразу после оператора вызова функции. Такой синтаксис работает только в том случае, если параметр—блок объявлен последним.
  
 
Можно было бы переписать эту конструкцию так:
 
Можно было бы переписать эту конструкцию так:
Строка 108: Строка 108:
 
  times(3,b);
 
  times(3,b);
  
Параметры блока могут быть перечислены между символами "|" через запятую. В данном случае блок принимает один параметр - номер итерации.
+
Параметры блока могут быть перечислены между символами "|" через запятую. В данном случае блок принимает один параметр номер итерации.
  
 
== Расширение классов ==
 
== Расширение классов ==
Строка 133: Строка 133:
 
  }
 
  }
  
Оператор extend расширяет функционал класса - в данном случае класса int. Его использование аналогично объявлению класса, но объявленные внутри поля, методы и операторы будут добавлены к уже существующему классу.
+
Оператор extend расширяет функционал класса в данном случае класса int. Его использование аналогично объявлению класса, но объявленные внутри поля, методы и операторы будут добавлены к уже существующему классу.
  
 
Таким образом, к классу int, объявленному в стандартной библиотеке, добавляется метод times, вызывающий связанный блок количество раз, равное текущему числу (не забываем: мы добавляем метод в класс int, который отвечает за хранение числа).
 
Таким образом, к классу int, объявленному в стандартной библиотеке, добавляется метод times, вызывающий связанный блок количество раз, равное текущему числу (не забываем: мы добавляем метод в класс int, который отвечает за хранение числа).
  
 
После такого объявления, в функции main мы используем уже метод times класса int: конструкция 3.times() означает создание объекта 3 класса int и вызов у этого объекта метода times().
 
После такого объявления, в функции main мы используем уже метод times класса int: конструкция 3.times() означает создание объекта 3 класса int и вызов у этого объекта метода times().

Версия 14:59, 6 сентября 2007

Содержание


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

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

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

Kpp1.png

Как уже отмечалось ранее, в 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 говорит о том, что имя функции не следует декорировать. Декорирование имен применяется для того, чтобы дать возможность перезагружать функции с одинаковыми именами но разными типами параметров.

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

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

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]);
}

Смысл этой программы понятен интуитивно: создается два массива — исходный (ary) и результирующий (sums), и затем массив sums заполняется суммами чисел из массива ary от 0 до текущего индекса i.

Особое внимание в этом примере следует уделить объявлениям переменных. В строках 5 и 6 объявляются два массива — ary и sums — причем в инструкции var их тип никак не указывается. В этом случае работает следующее правило: если при объявлении переменной ее тип не указан, то типом переменной становится тип результата инициализатора переменной (т.е. выражения, стоящего справа от =).

Выражения, записанные в квадратных скобках через запятую — это встроенная в K++ конструкция, создающая объект, имеющий тип array (объявленный в стандартной библиотеке) и заполненный соответствующими значениями.

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

Третья инструкция (строка 7) создает переменную типа int. Когда тип указан в самой конструкции var — объект соответствующего класса создается автоматически. Таким образом, например, следующие объявления эквивалентны:

var sums = new array;
var sums = [ ];
var array sums;

или

var i = 0;
var i = new int;
var int i;

Метод push класса array добавляет элемент в конец массива; size — возвращает количество элементов массива. Дальнейший код, думаю, объяснять не стоит.

Использование блоков

Подобно языку Ruby, в K++ реализован механизм передачи в качестве параметра функции некоторый связанный (с вызовом) блок кода. Функция затем может вызвать этот блок один или более раз, и воспользоваться результатом, который возвращает блок.

Выглядит это следующим образом:

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");
}

Результат выполнения программы:

0 1 2

Данный пример также демонстрирует объявление параметров функции: это делается в стиле языка C. Впрочем, тип параметра функции можно опустить — в этом случае будет сгенерирован динамический код.

В функции main используется специальный синтаксис для вызова функции times: тело блока идет сразу после оператора вызова функции. Такой синтаксис работает только в том случае, если параметр—блок объявлен последним.

Можно было бы переписать эту конструкцию так:

var b = { |i| STDOUT.print((i as string) + " "); };
times(3,b);

Параметры блока могут быть перечислены между символами "|" через запятую. В данном случае блок принимает один параметр — номер итерации.

Расширение классов

Приведенный выше пример можно переписать следующим образом:

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");
}

Оператор extend расширяет функционал класса — в данном случае класса int. Его использование аналогично объявлению класса, но объявленные внутри поля, методы и операторы будут добавлены к уже существующему классу.

Таким образом, к классу int, объявленному в стандартной библиотеке, добавляется метод times, вызывающий связанный блок количество раз, равное текущему числу (не забываем: мы добавляем метод в класс int, который отвечает за хранение числа).

После такого объявления, в функции main мы используем уже метод times класса int: конструкция 3.times() означает создание объекта 3 класса int и вызов у этого объекта метода times().

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

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