Структура языка Perl

редактировать

Структура языка программирования Perl включает в себя как синтаксические правила язык и общие способы организации программ. Философия дизайна Perl выражается в часто цитируемом девизе «есть несколько способов сделать это ». Как многопарадигмальный, динамически типизированный язык, Perl обеспечивает большую степень гибкости при разработке программ. Perl также поощряет модуляризацию; это связано с компонентной структурой его корней Unix и отвечает за размер архива CPAN, поддерживаемого сообществом репозитория из более чем 100 000 модулей.

Содержание
  • 1 Базовый синтаксис
  • 2 Типы данных
    • 2.1 Скалярные значения
    • 2.2 Значения массива
    • 2.3 Хеш-значения
    • 2.4 Дескрипторы файлов
    • 2.5 Значения Typeglob
    • 2.6 Функции массива
    • 2.7 Хеш функции
  • 3 Управляющие структуры
  • 4 Подпрограммы
  • 5 Регулярные выражения
    • 5.1 Использует
    • 5.2 Синтаксис
      • 5.2.1 Модификаторы
      • 5.2.2 Захват
  • 6 объектов
    • 6.1 Примеры
  • 7 Ссылки
  • 8 Внешние ссылки
Базовый синтаксис

В Perl минимальная программа Hello World может быть записана следующим образом:

print "Hello, World! \ N "

Этот печатает строку Hello, World! и новая строка, символически выраженная символом n, интерпретация которого изменяется предшествующим escape-символом (обратная косая черта). Начиная с версии 5.10, новая встроенная функция 'say' производит тот же эффект, что еще проще:

say "Hello, World!"

Вся программа Perl также может быть указана в качестве параметра командной строки для Perl, поэтому ту же программу можно также запустить из командной строки (пример показан для Unix):

$ perl -e 'print "Hello, World! \ N "'

Каноническая форма программы немного более подробна:

#! / Usr / bin / perl print" Hello, World! \ N ";

Знак решетки вводит в Perl комментарий , который выполняется до конца строки кода и игнорируется компилятором (кроме Windows). Используемый здесь комментарий имеет особый вид: он называется строкой shebang. Это сообщает Unix-подобным операционным системам найти интерпретатор Perl, что позволяет вызывать программу без явного упоминания perl. (Обратите внимание, что в системах Microsoft Windows программы Perl обычно вызываются путем связывания расширения .pl с интерпретатором Perl. Чтобы справиться с такими обстоятельствами, perlобнаруживает строку shebang и анализирует ее на предмет переключателей.)

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

Версия 5.10 Perl представляет функцию say, которая неявно добавляет символ новой строки к своему выводу, делая минимальную программу «Hello World» еще короче:

use 5.010; # должен присутствовать для импорта новых функций 5.10, обратите внимание, что это 5.010, а не 5.10 say 'Hello, World!'
Типы данных

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

ТипСигилПримерОписание
Скаляр $$ fooОдно значение; это может быть число, строка , дескриптор файла или ссылка.
Массив @@fooУпорядоченный набор скаляров.
Хеш %% fooОтображение строк в скаляры; строки называются ключами, а скаляры - значениями. Также известен как ассоциативный массив.
Дескриптор файла нет$ foo или FOOНепрозрачное представление открытого файла или другой цели для чтения, записи или того и другого.
Подпрограмма fooЧасть кода, которая может передавать аргументы, выполняться и возвращать данные.
Typeglob ** fooЗапись таблицы символов для всех типов с именем 'foo'.

Скалярные значения

Строковые значения (литералы) должны быть заключены в кавычки. Заключение строки в двойные кавычки позволяет значениям переменных, имена которых появляются в строке, автоматически заменять имя переменной (или быть интерполированным ) в строке. Заключение строки в одинарные кавычки предотвращает интерполяцию переменных.

Например, если $ nameравно «Джим»:

  • , то print («Меня зовут $ name»)напечатает «Меня зовут Джим»(интерполяция в двойных кавычках),
  • , но print ('Меня зовут $ name')напечатает «Меня зовут $ name "(без интерполяции в одинарные кавычки).

Чтобы включить двойные кавычки в строку, поставьте перед ней обратную косую черту или заключите строку в одинарные кавычки. Чтобы включить одинарную кавычку, поставьте перед ней обратную косую черту или заключите строку в двойные кавычки.

Строки также можно заключать в кавычки с помощью операторов qи qq, похожих на кавычки:

  • 'this'и q (this)идентичны,
  • "$ this"и qq ($ this)идентичны.

Наконец, многострочные строки могут быть определены с помощью здесь документов :

$ Multilined_string = <

Числа (числовые константы) не требуют цитирования. Perl преобразует числа в строки и наоборот в зависимости от контекста, в котором они используются. Когда строки преобразуются в числа, завершающие нечисловые части строк отбрасываются. Если ни одна из ведущих частей строки не является числовой, строка будет преобразована в число 0. В следующем примере строки $ nи $ mобрабатываются как числа. Этот код печатает цифру «5». Значения переменных остаются прежними. Обратите внимание, что в Perl +всегда является оператором сложения чисел. Оператор конкатенации строк - это точка.

$ n = '3 яблока'; $ m = '2 апельсина'; напечатайте $ n + $ m;

Предусмотрены функции для округления дробных значений до целых значений: intотбрасывает дробную часть с округлением до нуля; POSIX :: ceilи POSIX :: floorокругляют всегда вверх и всегда вниз соответственно. Преобразование числа в строку printf "% f"или sprintf "% f"с четным округлением, используйте округление банкиров.

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

$ false = 0; # число ноль $ false = 0.0; # число ноль в виде числа с плавающей запятой $ false = 0b0; # число ноль в двоичном формате $ false = 0x0; # число ноль в шестнадцатеричном формате $ false = '0'; # нулевая строка $ false = ""; # пустая строка $ false = (); # пустой список $ false = undef; # возвращаемое значение из undef $ false = 2-3 + 1 # вычисляется до 0, которое конвертируется в "0", поэтому оно ложно

Все остальные (ненулевые) значения оцениваются как истинные. Это включает в себя нечетную буквальную строку с самоописанием "0, но истинно", которая на самом деле равна 0 как число, но истинно при использовании как логическое значение. Все нечисловые строки также имеют это свойство, но эта конкретная строка усекается Perl без числового предупреждения. Менее явная, но более концептуально переносимая версия этой строки - «0E0» или «0e0», которая не полагается на символы, оцениваемые как 0, потому что «0E0» буквально равно нулю, умноженному на десять, в степени нуля. Пустой хеш {}также верен; в этом контексте {}не является пустым блоком, потому что perl -e 'print ref {}'возвращает HASH.

Вычисленные логические выражения также являются скалярными значениями. В документации не указано, какое именно значение будет возвращено: истина или ложь. Многие логические операторы возвращают 1 для истины и пустую строку для ложного. Функция defined () определяет, установлено ли для переменной какое-либо значение. В приведенных выше примерах defined ($ false) истинно для всех значений, кроме undef.

Если требуется 1 или 0, явное преобразование может быть выполнено с помощью условного оператора :

my $ real_result = $ boolean_result? 1: 0;

Значения массива

Значение массива (или список) указывается путем перечисления его элементов, разделенных запятыми, заключенных в круглые скобки (по крайней мере, там, где этого требует приоритет оператора).

@scores = (32, 45, 16, 5);

Оператор qw (), подобный кавычкам, позволяет определять список строк без ввода кавычек и запятых. Вместо круглых скобок можно использовать практически любой разделитель. Следующие строки эквивалентны:

@names = ('Билли', 'Джо', 'Джим-Боб'); @names = qw (Билли Джо Джим-Боб);

Функция split возвращает список строк, которые отделены от строкового выражения с помощью строки-разделителя или регулярного выражения.

@scores = split (',', '32, 45,16,5 ');

Доступ к отдельным элементам списка осуществляется путем указания числового индекса в квадратных скобках. Необходимо использовать скалярную сигилу. Подсписки (фрагменты массива) также можно указать, используя диапазон или список числовых индексов в скобках. В этом случае используется сигил массива. Например, $ month [3]- это «апрель»(первый элемент в массиве имеет значение индекса 0), а @month [4..6 ]равно («май», «июнь», «июль»).

Значения хэша

Программисты Perl могут инициализировать хеш (или ассоциативный массив ) из список пар ключ / значение. Если ключи отделены от значений с помощью оператора =>(иногда называемого жирной запятой ), а не запятой, они могут быть без кавычек (голые слова). Следующие строки эквивалентны:

% favourite = ('joe', «red», 'sam', «blue»); % favourite = (joe =>'красный', sam =>'синий');

Доступ к отдельным значениям в хэше осуществляется путем указания соответствующего ключа в фигурных скобках. Сигил $идентифицирует элемент, к которому осуществляется доступ, как скаляр. Например, $ favourite {joe} означает «красный». Хэш также можно инициализировать, задав его значения индивидуально:

$ favourite {joe} = 'red'; $ любимый {сам} = 'синий'; $ избранное {Оскар} = 'зеленый';

Для доступа к нескольким элементам можно использовать вместо этого знак @(идентифицирующий результат в виде списка). Например, @favorite {'joe', 'sam'} равно ('красный', 'синий').

Дескрипторы файлов

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

Первоначально дескрипторы файлов можно было создавать только с помощью переменных пакета, используя соглашение ALL_CAPS, чтобы отличить его от других переменных. Perl 5.6 и новее также принимает скалярную переменную, которая будет установлена ​​(autovivified ) на ссылку на анонимный дескриптор файла вместо именованного дескриптора файла.

Значения Typeglob

Значение typeglob - это запись таблицы символов. Основное использование typeglobs - создание псевдонимов таблиц символов. Например:

* PI = \ 3.141592653; # создание постоянного скаляра $ PI * this = * that; # создание псевдонимов для всех типов данных 'this' для всех типов данных 'that'

Функции массива

Количество элементов в массиве может быть определено либо путем оценки массива в скалярном контексте, либо с помощью сигилы $ #. Последний дает индекс последнего элемента в массиве, а не количество элементов. Выражения скаляр (@array) и ($ # array + 1) эквивалентны.

Хеш-функции

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

# Каждый вызов каждого из них возвращает следующую пару ключ / значение. # Все значения будут возвращены, но их порядок # предсказать невозможно. while (($ name, $ address) = каждый% addressbook) {print «$ name живет по адресу $ address \ n»; } # Аналогично предыдущему, но отсортировано в алфавитном порядке для каждого моего $ next_name (ключи сортировки% addressbook) {print "$ next_name живет в $ addressbook {$ next_name} \ n"; }
Управляющие структуры

Perl имеет несколько видов управляющих структур.

Он имеет блочно-ориентированные структуры управления, аналогичные тем, что в языках программирования C, JavaScript и Java. Условия заключены в круглые скобки, а контролируемые блоки - в фигурные скобки:

метка while (cond) {…} метка while (cond) {…} continue {…} метка для (init-expr; cond-expr ; incr-expr) {…} label foreach var (list) {…} label foreach var (list) {…} continue {…} if (cond) {…} if (cond) {…} else {…} if ( cond) {…} elsif (cond) {…} else {…}

Там, где контролируется только один оператор, модификаторы оператора обеспечивают более сжатый синтаксис:

оператор if cond; заявление, если только cond; заявление while cond; выписка до конд; оператор для каждого списка;

Логические операторы короткого замыкания обычно используются для воздействия на поток управления на уровне выражения:

expr и expr expr expr expr или expr expr || expr

(Операторы «and» и «or» похожи на и ||, но имеют более низкий приоритет , что упрощает их использование для управления целыми операторами.)

Ключевые слова управления потоком next(соответствующие C continue), last(соответствующие C break), returnи redoявляются выражениями, поэтому их можно использовать с операторами короткого замыкания.

Perl также имеет две конструкции неявного цикла, каждая из которых имеет две формы:

results = grep {…} list results = grep expr, list results = map {…} list results = map. expr, list

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

Вплоть до выпуска 5.10.0 в Perl 5 не было оператора переключения. Начиная с 5.10.0, оператор многостороннего перехода с именем заданный/ , когда доступен, который принимает следующую форму:

использовать v5.10; # должен присутствовать для импорта заданных новых функций 5.10 (expr) {when (cond) {…} default {…}}

Синтаксически эта структура ведет себя аналогично операторам переключения, найденным в другие языки, но с некоторыми важными отличиями. Самым большим из них является то, что в отличие от структур switch / case, операторы given / when прерывают выполнение после первого успешного перехода, а не ждут явно определенных команд прерывания. И наоборот, явные continueнеобходимы для имитации поведения переключения.

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

Perl включает оператор goto label, но он используется редко. Ситуации, когда gotoвызывается на других языках, не так часто встречаются в Perl из-за широты возможностей управления потоком.

Существует также оператор goto sub, который выполняет хвостовой вызов . Он завершает текущую подпрограмму и немедленно вызывает указанную подпрограмму . Это используется в ситуациях, когда вызывающий может выполнять более эффективное управление стеком, чем сам Perl (обычно потому, что не требуется никаких изменений в текущем стеке), а при глубокой рекурсии хвостовой вызов может иметь существенное положительное влияние на производительность, потому что это позволяет избежать накладных расходов на управление областью / стеком при возврате.

Подпрограммы

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

# Вызов подпрограммы # Круглые скобки здесь необходимы, если подпрограмма определена позже в коде foo (); foo; # (это также работает, но имеет другие последствия в отношении аргументов, передаваемых подпрограмме) # Определение подпрограммы sub foo {…} foo; # Здесь круглые скобки не требуются

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

foo $ x, @y,% z;

Параметры подпрограммы не нужно объявлять ни по номеру, ни по типу; фактически, они могут отличаться от звонка к звонку. Любая проверка параметров должна выполняться явно внутри подпрограммы.

Массивы раскрываются до их элементов; хэши расширяются до списка пар ключ / значение; и весь набор передается в подпрограмму как один плоский список скаляров.

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

К элементам @_можно получить доступ, присвоив ему индекс обычным способом.

$ _ [0], $ _ [1]

Однако результирующий код может быть трудным для чтения, а параметры имеют семантику передачи по ссылке, что может быть нежелательно.

Одна распространенная идиома - присвоить @_списку именованных переменных.

мой ($ x, $ y, $ z) = @_;

Предоставляет мнемонические имена параметров и реализует семантику передачи по значению. Ключевое слово myуказывает, что следующие переменные лексически привязаны к содержащему блоку.

Другая идиома - убрать параметры из @_. Это особенно часто встречается, когда подпрограмма принимает только один аргумент или для обработки аргумента $ selfв объектно-ориентированных модулях.

мой $ x = shift;

Подпрограммы могут назначать @_хешу для имитации именованных аргументов; это рекомендуется в Perl Best Practices для подпрограмм, которые, вероятно, когда-либо будут иметь более трех параметров.

sub function1 {my% args = @_; print "аргумент 'x' был '$ args {x}' \ n"; } function1 (x =>23);

Подпрограммы могут возвращать значения.

return 42, $ x, @y,% z;

Если подпрограмма не завершается с помощью оператора return, она возвращает последнее выражение, вычисленное в теле подпрограммы. Массивы и хэши в возвращаемом значении расширяются до списков скаляров, как и для аргументов.

Возвращенное выражение оценивается в контексте вызова подпрограммы; это может удивить неосторожных.

подсписок {(4, 5, 6)} подмассив {@x = (4, 5, 6); @x} $ x = список; # возвращает 6 - последний элемент списка $ x = array; # возвращает 3 - количество элементов в списке @x = list; # возвращает (4, 5, 6) @x = array; # возвращает (4, 5, 6)

Подпрограмма может обнаружить контекст своего вызова с помощью функции wantarray.

sub либо {return wantarray? (1, 2): «Апельсины»; } $ x = либо; # возвращает "Апельсины" @x = либо; # возвращает (1, 2)
Регулярные выражения

Язык Perl включает специальный синтаксис для написания регулярных выражений (RE или регулярных выражений), а интерпретатор содержит механизм для сопоставления строки в регулярные выражения. Механизм регулярных выражений использует алгоритм поиска с возвратом, расширяя его возможности от простого сопоставления с образцом до захвата и подстановки строк. Механизм регулярных выражений является производным от регулярного выражения, написанного Генри Спенсером.

. Синтаксис регулярных выражений Perl изначально был взят из регулярных выражений Unix версии 8. Однако он разошелся до первого выпуска Perl и с тех пор расширился, чтобы включить гораздо больше функций. Многие другие языки и приложения теперь используют Perl-совместимые регулярные выражения вместо регулярных выражений POSIX, например PHP, Ruby, Java, Microsoft .NET Framework и HTTP-сервер Apache.

Синтаксис регулярных выражений чрезвычайно компактен благодаря истории. Первые диалекты регулярных выражений были лишь немного более выразительными, чем globs, а синтаксис был разработан таким образом, чтобы выражение напоминало текст, которому оно соответствует. Это означало использование не более одного символа пунктуации или пары ограничивающих символов для выражения нескольких поддерживаемых утверждений. Со временем выразительность регулярных выражений значительно выросла, но дизайн синтаксиса никогда не пересматривался и по-прежнему основывается на пунктуации. В результате регулярные выражения могут быть загадочными и чрезвычайно сложными.

Использует

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

$ x = ~ / abc /;

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

s ///(замените), с другой стороны, задает операцию поиска и замены:

$ x = ~ s / abc / aBc /; # upcase the b

Еще одно использование регулярных выражений - указание разделителей для функции split:

@words = split /, /, $ line;

Функция splitсоздает список частей строки, разделенных тем, что соответствует регулярному выражению. В этом примере строка делится на список отдельных частей, разделенных запятыми, и этот список затем назначается массиву @words.

Синтаксис

Модификаторы

Регулярные выражения Perl могут принимать модификаторы. Это однобуквенные суффиксы, изменяющие значение выражения:

$ x = ~ / abc / i; # совпадение с шаблоном без учета регистра $ x = ~ s / abc / aBc / g; # глобальный поиск и замена

Поскольку компактный синтаксис регулярных выражений может сделать их сложными и загадочными, в Perl был добавлен модификатор / x, чтобы помочь программистам писать более разборчивые регулярные выражения. Это позволяет программистам помещать пробелы и комментарии внутри регулярных выражений:

$ x = ~ / a # соответствует 'a'. #, за которым следует любой символ c #, за которым следует символ 'c' / x;

Захват

Части регулярного выражения могут быть заключены в круглые скобки; соответствующие части совпадающей строки захватываются. Захваченные строки назначаются последовательным встроенным переменным $ 1, $ 2, $ 3,…, и список захваченных строк возвращается как значение совпадения.

$ x = ~ /a(.)c/; # захватить символ между 'a' и 'c'

Захваченные строки $ 1, $ 2, $ 3,…можно использовать позже в коде.

Регулярные выражения Perl также позволяют применять встроенные или определяемые пользователем функции к зафиксированному совпадению с помощью модификатора / e:

$ x = "Oranges"; $ x = ~ s / (ge) / uc ($ 1) / e; # OranGEs $ x. = $ 1; # добавьте $ x к содержимому совпадения в предыдущем операторе: OranGEsge
Objects

Есть много способов написать объектно-ориентированный код на Perl. Самый простой - это использование «благословенных» ссылок. Это работает путем идентификации ссылки любого типа как принадлежащей данному пакету, и пакет предоставляет методы для благословенной ссылки. Например, двумерная точка может быть определена следующим образом:

sub Point :: new {# Здесь Point->new (4, 5) приведет к тому, что $ class будет «Point». # Это переменная для поддержки создания подклассов (см. Справочную страницу perloop). мой ($ class, $ x, $ y) = @_; благослови [$ x, $ y], $ class; # Неявный возврат} sub Point :: distance {my ($ self, $ from) = @_; my ($ dx, $ dy) = ($$ self [0] - $$ с [0], $$ self [1] - $$ с [1]); sqrt ($ dx * $ dx + $ dy * $ dy); }

Этот класс можно использовать, вызывая new ()для создания экземпляров и вызывая distanceдля этих экземпляров.

мой $ p1 = Point->new (3, 4); мой $ p2 = Point->new (0, 0); напечатайте $ p1->distance ($ p2); # Печатает 5

Многие современные Perl-приложения используют объектную систему Moose. Moose построен на основе Class :: MOP, метаобъектного протокола, обеспечивающего полный самоанализ для всех классов, использующих Moose. Таким образом, вы можете спрашивать классы об их атрибутах, родителях, потомках, методах и т. Д. С помощью простого API.

Классы лося:

  • Класс имеет ноль или более атрибутов.
  • Класс имеет ноль или более методов.
  • Класс имеет ноль или более суперклассов (также называемых родительскими классами). Класс наследует от своего суперкласса (ов).
  • Класс выполняет ноль или более ролей, которые добавляют возможность добавлять предопределенные функции к классам без создания подклассов.
  • Класс имеет конструктор и деструктор.
  • У класса есть метакласс.
  • Класс имеет ноль или более модификаторов метода. Эти модификаторы могут применяться к его собственным методам, методам, унаследованным от его предков, или методам, предоставляемым ролями.

Роли лося:

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

Примеры

Пример класса, написанного с использованием расширения MooseX :: Declare для Moose:

используйте MooseX :: Declare; class Point3D extends Point {has 'z' =>(isa =>'Num', is =>'rw'); после очистки {$ self->z (0); } метод set_to (Num $ x, Num $ y, Num $ z) {$ self->x ($ x); $ self->y ($ y); $ self->z ($ z); }}

Это класс с именем Point3D, который расширяет другой класс с именем Point, описанный в примерах Moose. Он добавляет к своему базовому классу новый атрибут z, переопределяет метод set_toи расширяет метод clear.

Ссылки
Внешние ссылки
Последняя правка сделана 2021-06-01 09:33:46
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте