Pull to refresh

Comments 58

Что-то не совсем понял, как использовать void в параметрах функции.

То есть?
$x = 5;

function foo(void $x) : int {
   return $x; 
}


Вернет 5? Или данный код некорректен?
Так же void нельзя использовать как тип к параметру.
Так же void нельзя использовать как тип к параметру.

Данный код некорректен.
А, извиняюсь, неправильно прочитал.
> Добавлен новый псевдо-тип: «iterable»

Продолжаем потихонечку-потихонечнку двигаться вперёд.
В 8.1, наконец введут псевод-тип для объединения array и ArrayAccess
А что в PHP есть встроенные классы, которые реализуют только интерфейс ArrayAccess?
Насколько я помню (но могу и ошибаться), все кто реализует ArrayAccess так или иначе используют и Traversable интерфейс в конечном итоге. Например, тот же ArrayObject — он будет принят через «iterable» тип.
Другой вопрос самописные классы — но в них нет проблем добавить еще один дополнительный интерфейс Iterator или IteratorAggregate и все так же будет работать…
Но «возможность итерировать» и «хранилище с доступом по ключу», это разные интерфейсы.
Верно! Тогда почему от хранилища с доступом по ключу ждут возможность итерации (iterable)? )
foreach для ArrayAccess никогда работал — https://3v4l.org/8H8vR
Совершенно верно, никогда не работал и никто не ждёт.

Есть два интерфейса — перебор элементов и доступ к конкретному элементу по ключу. Они не взаимозаменяемые.

Нативный array «реализует» их оба.
И для итерирования, наконец, его слили с объектами с нужным интерфейсом.
А для доступа по ключу, опять забыли.
Вот теперь понял.
Да действительно, для примитивного типа array и ArrayAccess придется создавать свой псевдотип (например «hashable»?) и оно никак не будет пересекается с «iterable».
Пойти что-ли предложить им «hashable» RFC? ))

Тогда в php 9.2 можно ожидать наконец введения типов, как в некоторых других языках? =)


type likeArray = array|ArrayAccess;

function a(likeArray $a) { ... }

ну вот зачем отдавать преимущество {} перед [] для доступа к строке? ничего оно путать не будет, в других языках ведь как-то не путаются. а вот разные скобки задолбаешься ставить.


UPD: А не, они еще не решили


Скрытый текст

On the opposite side, it was also suggested that array access and string offsets are so closely-related concepts that we should recommend using '[]' in both cases and disable the alternate '{}' syntax for string offsets !


So, as the subject is controversial and very tangential to the subject of this RFC, it will be left for a future RFC.

Изменение работы isset() в 7.0.6 резко охладило мой пыл обновляться. То что разработчики могут без лишнего шума в минорной версии могут решить всё сломать не греет душу. Я в целом за то чтобы убирать грязь из движка, но вот так вот, в минорных версиях, без настроек, без этапа депрекации – это опасно. Я ж не могу за весь composer.json отвечать.
Ну проколы бывают у всех. Это хотели сломать еще в 7.0.0 — что было бы естественным.
Обьяснение
It is unfortunate that this change had to happen in a patch release, rather than in PHP 7.0.0. It's my fault that I did not notice during the pre-release cycle that this previously relatively harmless bug completely breaks the null-coalesce operator in PHP 7. However, that's how things went, and at this point a fix was critical.

For reference, the way to fix any issues with this change is to make sure your __isset() or offsetExists() functions behave correctly. If this change causes issues with your code, it indicates that you already have a broken __isset/offsetExists implementation, but it's brokenness did not previously surface (one bug canceling another...)

А вообще согласен, даже patch версии нельзя бездумно или автоматически обновлять, хотя бы не почитав changelog. )
А можете пожалуйста сказать, как именно изменили работу?
На хабре был пост: https://habrahabr.ru/post/283302/

Из него не совсем ясны последствия, но хотя бы понятно что у себя проверять.
и что рекомендуется использовать вместо mcrypt?
Кстати, это не значит что $x = someNethod(); не вернет ничего. Как и прежде в $x будет значение NULL

У авторов php шмаль явно лучше чем у меня.
Можно предположить, что это сделано для обратной совместимости.
Код, который имеет такое поведение уже написан и просто так ломать его не принесет успеха новой версии языка.

Хотя с другой стороны, было бы не плохо кидать какой-то warning для такого кода, чтобы фиксили активнее.
Простите, какая обратная совместимость? Речь о функции с возвращаемым типом void, который только-только вводится. В старых проектах таких ситуаций в принципе быть не может. Логично выкидывать предупреждение, если кто-то пытается присвоить значение функции с типом void.
Может быть, если решили обновить зависимости, которые используются в текущем «старом» коде.
UFO just landed and posted this here
PHP-программисты пишут всё с нуля и переписывают проект только целиком? Если использовать библиотеку, которая обновится и функция станет возвращать void, то это как раз тот случай.
Если использовать библиотеку, которая обновится и функция станет возвращать void,
то это как раз тот случай, когда лучше показать даже не ворнинг, а ошибку. Ведь если вызывающий код использовал значение, которое возвращала функция, то он никак не ожидает настолько кардинальной смены логики работы этой самой функции. Прикинуться валенком и продолжать работать — это худшее что может сделать интерпретатор в такой ситуации.
Так оно возвращало NULL и возвращает NULL, как понял.

Именно так. Смысл void только в том, чтобы помечать методы (функции) у которых де-факто отсутствует возвращаемое значение. Можно было конечно не изобретать новый псевдотип, а использовать null:


function a(): null {}

Но с другой стороны такая конструкция позволяет писать:


function a(): ?int {
    return random_int(0, 1) ?: null;
}

function b(): null {
  return a();
}

Что говорит о том, что ошибка может возникнуть в 50% случаях. А на void можно ругаться ещё на этапе парсинга тела метода\функции (скорее всего так и будет, я пока не пробовал войд на практике, не в курсе). Там не должно быть ничего кроме return; или же он (ретурн) просто должен отсутствовать, что избавляет от подобных проблем.

Зачем записывать в переменную значение возвращаемое функцией, если оно всегда было NULL? А если оно не всегда возвращало NULL, а теперь возвращает void, то логика поменялась, а вызывающий код получил мину замедленного действия в виде отсутствия явной ошибки.
Функции могут динамически подставляться
С разными типами возврата? Ну, право слово, PHP не обязательно использовать для извращений.
Фреймворк роутинга, который маппит HttpMethod + PATH [+MimeType] на функцию обработки.
Функция возвращает Объект, этот объект потом превращается в контент (к примеру в json или xml).

Функция может вернуть int, string, number, Object, null.

Пока не было типов функция могла ничего не возвращать, а просто записать что-то в хедеры и/или установить статус.
И? Вы не считаете такую архитектуру извращением?
Пока весь остальной мир идёт по пути унификации обработки веб-запросов (см. WSGI, Rack, Clack, Plug, WAI, etc.), Вы предлагаете из роутера передавать управление к разнородным функциям, которые хз что возвращают?
Ну, ok… ¯\_(ツ)_/¯
Посмотрел на WSGI и Rack (остальных не нашел), выглядит действительно не плохо! Но, как мне показалось, это то как на пхп писали еще лет 10 назад. Обработчик запроса, который устанавливает код ответа, хедеры и контент, и все это в одном месте. Для этого в пхп и фреймворки не нужны.

Описанный мною подход — это крайне упрощенный JAX-RS.
На выходе получается крайне простой и самодокументированный код, который не требует пояснений, который не содержит смеси бизнес-логики и формирования конента.

ps: вот пример из мира PHP, чтобы не было притензий, что я с монстроузорной java лезу тут: https://laravel.com/docs/5.3/routing
остальных не нашел
держите: Clack, Plug, WAI.

Но, как мне показалось, это то как на пхп писали еще лет 10 назад.
Нет, я 10 лет назад активно писал на PHP, и могу точно сказать, что ничего общего. Возможно, Вы не до конца поняли суть идеи…
Во-первых эти библиотеки не являются фреймворками, наоборот фреймворки (именно во множественном числе, т.е. это своеобразная спецификация, которую уважающий себя фреймворк обязан поддерживать) строятся поверх них.
Во-вторых, благодаря унификации обработчиков из их можно составлять цепочки произвольной длины, начиная с middlewares и заканчивая внутренними механизмами фреймворков. Кроме того, однажды написанную middleware можно опубликовать и люди смогут использовать её практически с любым веб-фреймворком в рамках данного ЯП, потому что никто из создателей фреймворков не стремится изобрести велосипед.

https://laravel.com/docs/5.3/routing
Прочитал… И какое-то смешанное ощущение, то ли документашка очень куцая, то ли роутинг в Laravel находится пока ещё в зачаточном состоянии. Во всяком случае описано мало возможностей и самое главное непонятно в чём профит от возможности возвращать разнородные данные из routing callbacks и как эти данные преобразуются в HTTP-ответ?
Спасибо за ссылки. Впечатление, что все эти библиотеки просто были списаны с одного примера и портированы на разные языки.

Но это уже пошел оффтоп. Моя позиция была в том, что такой подход используется в довольно популярных фреймворках и решение по $x = f(), где function f():void, вполне могут быть обоснованы обратной совместимостью.
Так же, я считаю, что в этом случае должна быть какая-то опция, чтобы можно было контролировать уровень ошибки для такого кода: игнорить, ворнинг, эррор, со значением «ворнинг» по-умолчанию.
Так же, я считаю, что в этом случае должна быть какая-то опция, чтобы можно было контролировать уровень ошибки для такого кода: игнорить, ворнинг, эррор, со значением «ворнинг» по-умолчанию.
Вот с таким подходом я полностью согласен.
Молодцы ребята, работают. Спасибо и за это!
UFO just landed and posted this here
Если работать через интерфейс, то более строгая имплементация ничего не поменяет. При этом, более строгая имплементация, сама по себе, запрещает коду сделать что-то не так.

Эта фича в простом коде не будет сильно использоваться, но дает гибкость для построения абстракции (при разработке фреймворков и библиотек).
UFO just landed and posted this here
Да, это кажется странным на первый взгляд, но на самом деле все довольно просто.

Интерфейс метода описывает максимальное допустимое множество значений, которые может обработать.
Имплементация может расширить это множество, скажем обрабатывать не только int, но еще и long, — это не сломает интерфейс int это подмножество множества long. А вот вместо int принимать short мы уже не сможем, т.к. множество short меньше множества int.
— а если работать через интерфейс, то сам интерфейс не позволит передать long, даже если в имплементации аргумент типа long.

Примерно такой же подход при возврате значения, мы можем Уменьшать множество ответов, но не можем его расширять. Уменьшать мы можем только, если меньшее множество ответов является подмножеством большего.
К примеру long в интерфейсе мы сможем заменить на int в имплементации, но вот заменить на bool — не сможем, bool — не является подмножеством множества long. (под bool подразумевается множество {true, false}, а не {1,0})

ps: примеры long, int, bool приведены как ограниченные множества, чтобы проще было понять идею, в реальности такие манипуляции могут не пройти.
UFO just landed and posted this here
У меня тут такой вопрос назрел: почему нельзя было сделать конструкцию
void Test() { ... }

как во многих языках программирования это реализовано. Зачем они сделали:
function someNethod(): void { ... }

?
Уж извините за такой вопрос, но он мне покоя не дает.
Подозреваю что это нужно чтобы не сломать старый код в которым такие функции(без типа результата) возвращают значение.
Ответ почему типы решили объявлять в конце функции, а не в начале есть тут.
В целом думаю ориентир был на Hack, где это уже было реализовано именно так (типа зачем плодить другие варианты).
Эх. А ведь частенько руки сами набирают что-то типа protected int getNumber() {}. Вообще не очень понятно, почему бы от function не отказаться. Парисить чуть сложнее разве что.
К примеру, чтобы легко было найти поиском «function Test» в десятке мегабайт кода.
Легко нахожу «function Test» в десятке мегабайт кода с помощью IDE.
Потому что это PHP, он не такой как все.

1) Js + FlowType
2) TypeScript
3) Haxe
4) ActionScript
5) ...


Ну да, уникальный в своём роде в этом случае.

Поэтому его все «любят»
Потому что обратная совместимость.
Потому что родитель был Perl, а не Си.
Потому что типизация пока по желанию.
UFO just landed and posted this here
Запрет на $this вне класса — сломается 1й Yii, там он в шаблонах использовался. Значит будем на 7.0.Х пробовать переезжать.
По факту в Yii все шаблоны исполняются внутри класса View, так что ничего не должно сломаться.
с чего взяли, что шаблоны YII1 вне класса работают? они инклудятся внутри метода
Sign up to leave a comment.

Articles