Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

PHP 5.6

Немного времени осталось до выхода PHP 5.6. Похоже, авторы взяли в привычку добавлять в каждой версии в язык несколько нововведений. Сейчас эта версия в стадии альфы, это означает, что до беты может добавиться что-то ещё, но то что уже есть, радует глаз.

Во-первых, появилась операция возведения в степень. Ничего особо примечательного, но циклы, где используется степень можно будет сделать побыстрее — вызов функции в ПХП относительно дорогая операция.

echo 2**3, "\n", // восемь
-2**2, "\n", // минус четыре
2 ** 3 ** 2; // 512

«Крышка» (^), которая во многих языках занята под степень, в ПХП занята под «исключающее или», поэтому сделали две «звёздочки», как в Пайтоне. Из приведённых примеров мы видим, что «вес» унарного минуса ниже, чем у степени — он применяется уже к результату, об этом надо помнить, лично я бы ожидал, что в степень будет возведено отрицательное число. И, кстати, сама операция является правоассоциативной (последний пример).

Во-вторых, у модуля gmp (модуль для работы с большими числами) появились перегруженные операторы. Вся арифметика (включая новопоявившуюся степень) работает привычным порядком, как у обычных чисел:

$a = gmp_init(2);
$b = gmp_init(3);

$c = $a**2 + $b;

echo $c, "\n"; // выведет 7
var_dump($c); // покажет объект класса GMP, у которого есть свойство num=7
echo array_sum([1,2,gmp_init(-3)]); // 3, печаль

Кроме этого, переход к объектам (от ресурсов) позволит сериализовать эти числа, что является хорошим бонусом. Увы, не всё ещё гладко — последний вызов (где суммируется массив) возвращает число три, а не ноль.

В-третьих, константы (задаваемые через ключевое слово const) теперь вычисляемые. Никакого противоречия тут нет — это по-прежнему не переменные, просто их значением может теперь быть вычисляемое единожды выражение. Это позволяет выражать одни константы через другие. Особого новшевства здесь нет — через define так можно было делать и раньше:

const alf = 2;
const bolk = alf*alf . alf; // работает новый синтаксис

echo bolk, "\n"; // 42

define("TEST", alf*alf . alf); // работает старый синтаксис
echo TEST, "\n"; // 42

В-четвёртых, в ПХП появился новый синтаксис функции с переменным количеством аргументов. Они были и раньше, но не было способа определения фукнции таким образом, чтобы остальные аргументы при вызове (сколько бы их не оставалось) попали в определённую переменную (для этого мы использовали func_get_args):

// сколько бы аргументов после первого не было, они попадут в $params массивом
function query($query, ...$params) {
    $stmt = $this->pdo->prepare($query);
    $stmt->execute($params);
    return $stmt;
}

Синтаксис с тремя точками используется в Си, Джаве и новой версии Джаваскрипта. Что интересно, с новым синтакисом работает и указание типа аргумента, и передача по ссылке. Ограничения этого синтаксиса вполне понятные — такой аргумент должен быть всегда последним (и/или единственным), задавать значения по-умолчанию нельзя:

// всё это неправильно:
function fn(...$args, $arg) // такой агрумент не первый
function fn(...$args1, ...$args2) // не единственный
function fn($arg, ...$args = []) // задано значение по-умолчанию

Выбор именно такого синтаксиса основывался на следующих вещах:

// выглядит как будто мы требуем, чтобы $args был массивом, что бесполезно — $args уже
// массив, по определению; на самом деле этот синтаксис должен иметь значение «каждый переданный
// в $args элемент — массив»
function fn(array $args...)
// будет путать ребят, которым приходится программировать и на Си тоже — очень похоже
// на указатель
function fn(Char *$args)
// в Си# используется ключевое слово «params», для ПХП не подходит, так как будет путаница
// с указанием типа
function fn(params $args)

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

$a = $b = 2;
$c = ['a', 'b'];

var_dump(call_user_func_array('compact', $c)); // прежний синтаксис
var_dump(compact(...$c)); // новый синтакисис
var_dump(compact(...$c, 'c')); // можно ещё и так, будут переданы как аргументы 'a', 'b' и 'c'

var_dump(...new ArrayIterator([1, 2, 3])); // даже так работает! утиная типизация во всей красе
var_dump(...[1 => 1, 3 => 1]); // будет переданы два параметра, без пропусков в номерации

var_dump([...$c, $a]); // а вот так, увы, нельзя
list($k, ...$d) = $c; // так тоже нельзя
echo ...$c; // даже так нельзя!

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

Но даже с этими недостатками, нововведение хорошее. Посмотрите как чудесно выглядит каррирование в новом синтаксисе:

function bind(callable $function, ...$boundArgs) {
    return function(...$args) use($function, $boundArgs) {
        return $function(...$boundArgs, ...$args);
    }
}

$arrayToLower = bind('array_map', 'strtolower');

$arrayToLower(['Foo', 'BAR', 'baZ']); // вернёт ['foo', 'bar', 'baz']
14 комментариев
Евгений Степанищев (bolknote.ru) 2014

Комментарий для PHP_boy:

И что эта картинка значит?

PHP_boy 2014

Целевая аудитория PHP

PHP_boy 2014

Вроде бы на дворе 2014 год, а разрабы
сделали такой неуклюжий синтаксис,
будто компилятор пыха написан на Turbo C.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для PHP_boy:

В чём же «неклюжесть» этого синтаксиса?

BOLVERIN 2014

В чём же «неклюжесть» этого синтаксиса?

«... ты виноват уж тем, что хочется мне кушать ...»

Опечатка 2014

Комментарий для Евгения Степанищева:

не было способа определения фукнции

Евгений Степанищев (bolknote.ru) 2014

Комментарий для Опечатка:

Спасибо, сейчас исправлю.

Евгений Степанищев (bolknote.ru) 2014

Комментарий для PHP_boy:

ПХП_бой, вы какой-то странный человек, разговаривающий картинками. Я совершенно не понимаю что вы хотите ими сказать. По таланту вы явно не Умберто Эко и даже не Дэн Браун, чтобы я на ваши загадки время тратил, хочется что-то сказать, скажите словами, чай не младенец, в картинку пальцем тыкать.

hshhhhh (hshhhhh.name) 2014

Комментарий для Евгения Степанищева:

Посмотрите как чудесно выглядит каррирование в новом синтаксисе:

Я вот всё ещё никак не могу понять зойчем это ваще каррирование существует. Применить его можно крайне редко, оно негативно сказывается на скорости, но это очень, очень, очень, очень важно!

Евгений Степанищев (bolknote.ru) 2014

Комментарий для hshhhhh.name:

В функциональном программировании частенько используется. Вы просто не сталкиваетесь, видимо, с ним. Например, когда при итерации нужна функция от меньшего количества аргументов, чем имеется. Просто чаще всего это всё не настолько явно.

Никто не говорит, что это «очень, очень, очень, очень важно», каррирование и в прежнем синтаксисе работало, просто было куда уродливее. С этой точки зрения пример и приведён.

(в примере, кстати, bind умеет не просто каррирование, а частичное применение)

plutov.by 2014

Ссылка в тему про нововведения в 5.6 — http://plutov.by/post/php5_6_release

Евгений Степанищев (bolknote.ru) 2014

Комментарий для http://plutov.by:

Это простое перечисление, вот здесь и то подробнее: http://php.net/archive/2014.php#id2014-08-28-1