Привет!
Меня всегда напрягало то, как PHP преобразует строки в числа. Классический пример:
$value = (int)"32px"; // 32
$value = (int)"kg32"; // 0
Я понимаю, что такое поведение намеренно и в некоторых случаях бывает полезным.
Но… в результате можно получить вполне корректное целое число, при этом информация о том, что исходная строка содержала что-то ещё (важное или не очень), бесследно теряется.
Я думал над тем, как можно было бы решить эту проблему, и пришёл к одной идее.
Что, если добавить к значениям признак reliable / unreliable (надёжное / ненадёжное)?
Представим, что наш PHP-движок УМЕЕТ автоматически устанавливать специальные флаги времени выполнения для любых значений.
Например, помечать значение как unreliable, если при его преобразовании возникли сомнения.
Этот флаг будет сохраняться при присваивании и вычислениях:
$a = (int)"32kg"; // 32, unreliable
$b = $a * 2; // 64, всё ещё unreliable
$c = $b + 10; // 74, всё ещё unreliable
Флаг можно устанавливать и снимать явно:
$a = (unreliable)42;
$a = (reliable)$a;
В обычном режиме этот флаг ни на что не влияет. Код продолжает работать как прежде.
При необходимости можно проверить значение с помощью is_reliable($value) и принять соответствующие меры:
if (!is_reliable($x = (int)$UserInput)) {
....
}
Но можно предусмотреть и более строгий режим - с помощью языковой конструкции reliable / catch, по аналогии с try/catch:
$a = (int)"32kg"; // 32, unreliable
reliable {
echo $a; // Попытка использовать unrel значение - исключение!
} catch (Error $e) {
// Обрабатываем исключение
}
Или включить строгую проверку для всего последующего кода.
Такой режим работает по принципу этакого fail-fast: никаких блоков catch() - просто выбрасывается
необработанное исключение, которое прерывает выполнение.
$a = (int)'hello'; // 0, unreliable
$b = $a + 1;
reliable on; // языковая конструкция, включить строгий режим
...
$c = $b; // Исключение: попытка использовать unrel значение
...
Примеры выше - это все про строки. Но ureliable может происходить и в других сценариях, например, мы конвертим объект в число, а объект не имеет соответствующего магического метода __toInt.
Или мы ковертим массив во float, (т.е. (float)[‘a’ => 0, 2]) и так далее.
А ТЕПЕРЬ, ВНИМАНИЕ, ВОПРОС:
Мне было бы интересно узнать, что думают об этом те, кто пишет на PHP.
Как вам такая идея? Кажется ли она полезной? Или это просто добавление сложности там, где на самом деле нет никакой проблемы?
Спасибо!



