Типи

Zephir поєднує в собі статичну та динамічну типізацію. У цьому розділі ми розглянемо підтримувані типи даних та їхню поведінку.

Динамічні типи

Динамічних змінні працюють так само, як і в PHP. Їм можна призначати та перепризначати значення різних типів без обмежень.

Динамічна змінна має бути оголошеною з ключовим словом var. Поведінка майже така сама, як і в PHP:

var a, b, c;
Ініціалізація змінних
let a = "hello", b = false;
Зміна їхнього значення
let a = "hello", b = false;
let a = 10, b = "140";
Виконання операцій
let c = a + b;

Вони можуть бути восьми типів:

Тип Опис
array Масив — це впорядкована мапа. Мапа — це тип, який встановлює відповідність між значеннями та ключами.
boolean Булевий тип виражає значення істини. Він може бути true або false.
float/double Число з рухомою комою. Розмір числа залежить від платформи.
integer Цілі числа. Розмір числа залежить від платформи.
null Особливе значення NULL, яке означає змінну в якої немає значення.
object Абстракція об’єкта як у PHP.
resource Ресурс містить посилання на зовнішній ресурс.
string Рядок є послідовністю символів, де кожен символ є одним байтом.

Check more info about these types in the PHP manual.

Array

Реалізація масивів у Zephir в основному така сама як у PHP: впорядковані мапи оптимізовані для деяких випадків; можна розглядати як масив список (вектор) хеш-таблицю (реалізація мапи), словник, колекція, стек, черги. Можливі й інші трактування. Значеннями масиву можуть бути інші масиви, дерева, та багатовимірні масиви.

Синтаксис оголошення масиву дещо відрізняється від PHP:

Для оголошення повинні використовуватися квадратні дужки
let myArray = [1, 2, 3];
Для оголошення масиву з ключами повинна використовуватися двокрапка
let myHash = ["first": 1, "second": 2, "third": 3];

Ключами масиву можуть лише цілі числа та рядки:

let myHash = [0: "first", 1: true, 2: null];
let myHash = ["first": 7.0, "second": "some string", "third": false];

Boolean

Булевий тип виражає значення істини. Він може бути true або false:

var a = false, b = true;

Float/Double

Числа з рухомою комою (також відомі як “двійкові”, “числа з подвійною точністю”, “дійсні числа”). Літерали з рухомою комою - це вирази з однією або кількома цифрами, а потім - крапка (.), після нього одна або кілька цифр. Розмір числа після крапки залежить від платформи, хоча максимум ~1.8e308 з точністю приблизно 14 десяткових цифр мають загальне значення (64-бітний форматі IEEE).

var number = 5.0, b = 0.014;

Числа з рухомою комою мають обмежену точність. Хоча це залежить від системи, як і в PHP, Zephir використовує формат подвійної точності IEEE 754, який дасть максимальну відносну помилку через округлення порядку 1.11e-16.

Integer

Цілі числа. Розмір числа залежить від платформи, хоча максимальне значення для 32-бітного знакового числа є 2,147,483,647. 64-розрядні платформи зазвичай мають максимальне значення близько 9E18. PHP не підтримує цілі числа без знаку, тому Zephir теж має це обмеження:

var a = 5, b = 10050;

Програмне переповнення цілих чисел

На відміну від PHP Zephir автоматично не перевіряє рівень заповненості цілого числа. Як і в C, якщо ви виконуєте операції які можуть повернути велике число ви повинні використати такі типи як unsigned long або ж float:

unsigned long my_number = 2147483648;

Об’єкт

Zephir дозволяє створювати екземпляри PHP класів, маніпулювати PHP-об’єктами, викликати методи, читати константи класу та інші речі, які дозволяють PHP-об’єкти:

let myObject = new \stdClass(),
    myObject->someProperty = "my value";

Рядок

Рядок string є послідовністю символів, де кожен символ є одним байтом. Як і PHP, Zephir підтримує лише 256-символьний набір, а отже не дає вбудованої підтримки Unicode.

var today = "friday";

У Zephir рядкові літерали можна задавати лише взявши їх у подвійні лапки (як у C або Go). Одинарні лапки зарезервовані для типу даних char.

У рядках підтримуються наступні символи екранування:

Послідовність Опис
\t Горизонтальний відступ
\n Переведення рядка
\r Повернення каретки
\\ Бекслеш
\" Подвійні лапки
var today    = "\tfriday\n\r",
    tomorrow = "\tsaturday";

Zephir не підтримує інтерполяцію змінних як це було в PHP; натомість ви повинні використовувати конкатенацію:

var name = "peter";

echo "hello: " . name;

Статичні типи

Статичні типи дозволяють розробнику оголосити та використовувати змінні з певними типами, які доступні у C. Змінна, яка оголошена з статичним типом не може змінювати свій тип. Проте, це дозволяє компілятору провести кращу оптимізацію. Підтримуються наступні типи даних:

Тип Опис
array Структура, яка може бути використана як хеш, мапа, словник, колекція, стек, і т. д.
boolean Булевий тип виражає значення істини. Він може бути true або false.
char Найменша адресна одиниця машини, яка може містити символ з базового набору.
float/double Тип з рухомою комою подвійної точності. Розмір числа залежить від платформи.
integer Знакові числа. Розмір не менше 16 біт.
long Довге знакове число. Розмір не менше 32 біт.
string Рядок є послідовністю символів, де кожен символ є одним байтом.
unsigned char Той же розмір, що і char, але гарантовано беззнаковий.
unsigned integer Беззнакове ціле. Розмір не менше 16 біт.
unsigned long Той же розмір, що й long, але беззнаковий.

Boolean

Логічний тип boolean виражає значення істини. Він може бути true або false. На відміну від поведінки динамічного типу статичні логічні типи залишаються логічними (true or false), не залежно від того, яке значення їм призначається:

boolean a;
let a = true;
автоматично перетворюється на true
let a = 100;
автоматично перетворюється на false
let a = 0;
кидає виняток компіляції
let a = "hello";

Char/Unsigned Char

Змінна типу char найменша адресна одиниця машини, яка може містити символ з базового набору (як правило, 8 біт). Змінна типу char може використовуватися для зберігання будь-яких символів у рядку:

char ch, string name = "peter";
зберігає “t”
let ch = name[2];
Літерали типу char мають бути взяті в одинарні лапки
let ch = 'Z';

Integer/Unsigned Integer

значення типу integer схожі з аналогами в динамічних типах. Значення, присвоєні цілим змінним, залишаються цілими:

int a;

let a = 50,
    a = -70;
автоматично перетворюється на 100
let a = 100.25;
автоматично перетворюється на 0
let a = null;
автоматично перетворюється на 0
let a = false;
кидає виняток компіляції
let a = "hello";

Беззнакові цілі unsigned integer схожі на цілі числа integer, але вони не мають знака, це означає, що ви не можете зберігати від’ємні числа в таких змінних:

uint a;

let a = 50;
автоматично перетворюється на 70
let a = -70;
автоматично перетворюється на 100
let a = 100.25;
автоматично перетворюється на 0
let a = null;
автоматично перетворюється на 0
let a = false;
кидає виняток компіляції
let a = "hello";

Тип unsigned integer вдвічі більший стандартного integer. Присвоєння беззнакових цілих стандартним цілим (знаковим) може привести до втрати даних:

можлива втрата даних для b
uint a, int b;

let a = 2147483648,
    b = a;

Long/Unsigned Long

змінні типу long удвічі більші, аніж integer, тому вони можуть зберігати великі числа. Як і у випадку з integer, при присвоєнні значень змінним типу long, вони автоматично приводитимуться до цього типу:

long a;

let a = 50,
    a = -70;
автоматично перетворюється на 100
let a = 100.25;
автоматично перетворюється на 0
    let a = null;
автоматично перетворюється на 0
let a = false;
кидає виняток компіляції
let a = "hello";

Тип unsigned long схожий на long, але не має знаку. Це означає, що ви не можете зберігати від’ємні числа в таких змінних:

ulong a;

let a = 50;
автоматично перетворюється на 70
let  a = -70;
автоматично перетворюється на 100
let a = 100.25;
автоматично перетворюється на 0
let a = null;
автоматично перетворюється на 0
let a = false;
кидає виняток компіляції
let a = "hello";

Тип unsigned long вдвічі більший стандартного long; присвоювання даних типу unsigned long стандартному знаковому long може привести до втрати даних:

можлива втрата даних для b
ulong a, long b;

let a = 4294967296,
    b = a;

String

Рядок є послідовністю символів, де кожен символ є одним байтом. Як і в PHP, цей тип даних підтримує лише 256-символьний набір, а отже, не має підтримки Юнікоду.

Коли змінна оголошується як string вона ніколи не змінить свого типу:

string a;

let a = "";
рядкові літерали повинні бути взяті в подвійні лапки
let  a = "hello";
перетворюється в рядок “A”
let a = 'A';
автоматично перетворюється на “”
let a = null;