Искусственный интеллект при формировании персональных рекомендаций маркетплейса

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

Для таких случаев неплохо подходит принцип коллаборативной фильтрации, который выстраивает прогнозы, основываясь на уже известных предпочтениях, и дает рекомендации еще неизвестных предпочтений совсем других пользователей. Принцип прост – однажды данная оценка явления или товара, оставленная ранее, является базисом для схожих оценок других явлений и товаров в будущем. Плюсом коллаборативной фильтрации является ее индивидуальная «заточенность» под каждого клиента, несмотря на то, что информационное обоснование для прогноза собрана из ответов тысяч других людей.

При таком подходе используются три метода создания рекомендательных систем. Первый – коллаборативная фильтрация, второй – контентно-основанные рекомендации, третий – гибридный.

Выглядит вся рекомендательная система при этом таким образом.

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

  • каждому пользователю присваивается вес, исходя из его активности и оценок;

  • производится выборка пользователей (соседей) с максимальным весом схожести активного пользователя;

  • подсчитывается вероятность тех или иных оценок активного пользователя пока еще не оцененных им товаров и явлений, основываясь на оценках соседей.

Метод, основанный на данной модели, измеряет параметры статмоделей с помощью метода байесовских сетей, латентной семантической модели, сингулярного разложения, скрытого распределения Дирихле, марковского процесса принятия решения на основе моделей, кластеризации. Разработка моделей производится в процессе интеллектуального анализа данных и машинного обучения. Результатом является обнаружение закономерностей на основе обучающих данных. Этот подход более точный, так как лучше обрабатываются разреженные матрицы, что улучшает процесс масштабирования больших наборов данных. Гибридный метод наиболее распространен при создании рекомендательных систем, но дорог в реализации и использовании с точки зрения большого количества вычислений.

Получить численное выражение рекомендации от множества пользователей – одна из задач. Делается при помощи выстраивания оценки каждого пользователя, выбранного числа товаров в вектор. После чего производится сравнение этого вектора с вектором других пользователей в рамках заданной выборки товаров. Сравнение можно проводить при помощи коэффициента корреляции Пирсона, Евклидового расстояния, косинусной меры и других методов. Наиболее подходящим и доступным является косинусная мера. При использовании косинусной меры рассчитывается это косинус угла между двумя векторами. Одним словом, достаточно будет заглянуть в учебник алгебры и начать высчитывать по формуле:

cos⁡(x ⃗,y ⃗)=(x ⃗*y ⃗)/(‖x ⃗ ‖_2×‖y ⃗ ‖_2 )

За счет коллаборативной фильтрации можно будет оптимизировать данные. Но лучше сокращать строки названий и использовать числовые идентификаторы товаров, а не названия. Чтобы сократить часть расходов можно делить пользователей на категории,  высчитывать только меры схожести в рамках одной категории. Также важно транспонировать матрицу и рассчитать наиболее схожие продукты при помощи косинусной меры. При этом выбор меры следует производить лишь при наличии результатов анализа данных.

Кто первый?

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

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

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

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

Весовая матрица работает таким образом: сигнал с 15 параметрами преобразуется на одном уровне с 15 нейронами, каждый из которых связан с 14 другими нейронами. В итоге образуется 210 (15х14) связей, каждая из которых получает свой «вес» или весовой коэффициент. Собранные веса заполняют матрицу взаимодействий. Самообучение основано на взаимодействии весов в матрице – их расположение задают запоминаемые векторы, образующие память. Этот процесс должен соответствовать уравнению:

Xi = WXi

Состояния сети Х в этом случае устойчиво, что делает ее устойчивой.

При заданной бинарности векторов, расчет веса проводится таким образом:

N – это N размерность векторов, mm – число запоминаемых выходных векторов, dd — номер запоминаемого выходного вектора, XijXij — i-я компонента запоминаемого выходного j-го вектора. Расчет этих весовых коэффициентов и есть процесс обучения сети.

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

Главное – подробная консультация

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

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

Безопасность

Рекомендательные системы такого типа заставляют серьезно задуматься о безопасности личных данных. Очевидно, что лидерами рынка онлайн-консультирования станут именно те компании, которые сумеют гарантировать хранение и защиту информации о своих клиентах. Для этого искусственный интеллект должен автоматически вырабатывать стратегию и тактику активной защиты. Такой подход позволит предотвращать атаки на серверы, а не «латать дыры» после того, как злоумышленники проникли в архивы.

Например, система выстраивает систему признаков, распознающих потенциальную угрозу – подозрительные IP-адреса, хеши вредоносных файлов и прочее. Все это соотносится с моделями поведения конкретных пользователей. И если будет замечена подозрительная активность в нетипичное время захода или из другой географической точки, то включится система отслеживания и безопасности. Такой подход более качественный и быстрый, так как хакеров блокируют в режиме реального времени за счет глубокого анализа потенциальной угрозы. То есть, искусственный интеллект постоянно создает новые варианты возможных атак со стороны злоумышленников и готовится к их отражению.

ссылка на оригинал статьи https://habr.com/ru/post/560134/

Что бы ещё напечатать на 3D-принтере?

Мы всё чаще слышим про использование 3D-печати для решения самых разных, порой неожиданных задачах. С одной стороны, 3D-печать позволяет снизить стоимость производства, особенно сложных деталей. С другой стороны, есть сомнения, что 3D-принтеры действительно заменят большую часть оборудования на производствах.

Рассмотрим несколько интересных примеров использования 3D-принтеров как для развлечения, так и на серьёзных предприятиях.

Начнём с развлечения и игрушек. Среди моделистов 3D-принтер уже давно не новинка. Технология 3D-печати с каждым годом набирает популярность и вытесняет модели из смолы. Почему бы не сделать модель Призрачного гонщика или целый завод по мотивам игры Red Alert 2:

Окрашенная модель "Призрачный гонщик", автор Игорь Седых
Окрашенная модель «Призрачный гонщик», автор Игорь Седых
Окрашенная модель завода из Red Alert 2, автор Игорь Седых
Окрашенная модель завода из Red Alert 2, автор Игорь Седых

Хобби — это здорово, но как насчёт действительно больших проектов? Что нам стоит дом построить? Нарисуем, будем жить!

Огромные 3D-принтеры, которые могут напечатать целые дома уже не фантастика, они существуют и работают. Перед вами несколько примеров таких работ:

Интересны проект, дома отлично вписываются в окружающий ландшафт
Интересны проект, дома отлично вписываются в окружающий ландшафт
Ярко и жизнерадостно
Ярко и жизнерадостно

Сложно сказать, насколько это экономически целесообразно, но выглядит процесс печати жилых домов достаточно интересно:

Что нам стоит дом построить? Нарисуем, будем жить!
Что нам стоит дом построить? Нарисуем, будем жить!

Но это всё же не более чем забавы. Намного интереснее применение 3D-печати в высокотехнологичных сферах, таких как гражданская и военная авиация. По данным портала Авиация России, наши инженеры активно внедряют этот подход в новых проектах, таких как МС-21, СУ-57 и производство беспилотников.

Внутренний корпус российского вертолетного двигателя ВК-2500. Применение аддитивных технологий для изготовления двигателя позволило сократить срок изготовления до 14 дней. 

Крупногабаритный корпус вертолетного двигателя «напечатан» на 3D-принтере
Крупногабаритный корпус вертолетного двигателя «напечатан» на 3D-принтере

В современных самолётах и вертолётах применяются разнообразные композитные материалы и технология 3D-печати становится всё более востребованной в отрасли. Недавно российскими учёными разработана технология изготовления керамических композиционных деталей на 3D-принтере. По сравнению с металлами керамические композиционные материалы выдерживают экстремально высокие температуры (1500°С — 2500°С) и обладают высокой прочностью. Именно поэтому их рассматривают в качестве основы создания конструкций в «горячих» частях перспективных двигателей. Например, камеры сгорания, сопла.

А в далёком уже 2015 году российские учёные впервые в мире напечатали щитовидную железу на отечественном 3D-биопринтере. В дальнейшем напечатанную по этой технологии щитовидную железу успешно пересадили мыши.

3D-печать щитовидной железы – событие важное. По оценкам ВОЗ, около 665 миллионов людей по всему миру страдают от заболеваний щитовидной железы – только в России их 140 000 человек.

ссылка на оригинал статьи https://habr.com/ru/company/timeweb/blog/559956/

Безуспешная попытка монетизации моего проекта в open source

Время от времени я пишу ПО в open source. У меня есть довольно популярный сейчас проект под названием faker.js. Я работаю над Faker уже больше десятка лет. Он имеет лицензию MIT.

В этом посте я расскажу о своей попытке монетизации проекта Faker при помощи облачного сервиса. Постепенно мы дойдём до инженеров из стартапа ценой 75 миллионов долларов, основанному Sequoia Capital. Джон и Партик Коллисоны зарегистрировались в моём облачном сервисе, протестировали его, скопировали концепцию, вставили ссылку на CDN моего бизнеса, а теперь CEO компании Дэвид Сюй не отвечает на мои письма. В целом это будет увлекательное и информативное чтиво.

Что такое Faker?

На высоком уровне Faker можно описать как своего рода интернационализированный словарь/энциклопедию сочетаний, управляемый надёжным генератором псевдослучайных чисел. Faker — это что-то вроде миниатюрной версии «Вавилонской библиотеки». Это чрезвычайно полезный обобщённый инструмент, используемый при разработке крупномасштабных интернациональных программных систем. Большинство компаний из списка Fortune 500 в той или иной степени пользуется Faker. Проект Faker имеет достаточно большой масштаб. Необходим приличный объём работ по модерации для управления потоком данных интернационализации и локализации, а также для того, чтобы сам проект оставался масштабируемым и не распухал.

Кто платит за разработку Faker?

Никто. Недавно мы начали получать спонсорскую помощь через такие сервисы, как Open Collective и Github Sponsors. Большинство таких пожертвований приходит от коллег-разработчиков, а не от компаний или корпораций. Эти пожертвования помогли тому, чтобы разработка Faker не прекратилась окончательно, но для стабильного развития их недостаточно. Мне нравится работать над Faker, но я не могу позволить себе работать бесплатно. Как и у многих из нас, у меня есть люди, которые зависят от меня, а также неоплаченные счета. Не желая сдаваться, я решил, что лучше всего будет попробовать монетизировать проект Faker, чтобы обеспечить ему устойчивое развитие в будущем.

План монетизации

Я подумал, что у разработчиков есть потребность в быстром и простом способе получения фальшивых/имитируемых/тестовых данных от конечной точки API без необходимости настройки бэкенд-серверов. Им нужен небольшой конструктор таблиц, возможность скачивания электронных таблиц, добавления форматов для всех крупных баз данных, получения данных через REST API. Не особо сложная схема. По сути, это облачная версия Faker с тарифами ежемесячной оплаты.

Примерно месяц я потратил на создание, проектирование и запуск fakercloud.com. Ровно столько времени, сколько необходимо для реализации MVP. Чего-то функционального, полезного и с работающими тарифными планами. Я хотел выпустить раннюю версию, которую можно было бы показать сообществу Faker, после чего начать перерабатывать концепцию на основе отзывов пользователей.

Отзывы пользователей

Примерно через две недели после начала мониторинга регистрации пользователей и записи экрана через Hot Jar я заметил, что в сервисе зарегистрировались два инженера из Retool.com. Оба они несколько раз заходили на сайт и тестировали все функции.

Название Retool показалось мне знакомым — оказалось, что компания была спонсором Faker, ежемесячно с января 2021 года платя по 500 долларов через Open Collective. На сегодняшний день благодаря этому Retool является вторым по сумме вкладов спонсоров Faker с общими пожертвованиями 2000 долларов. Я подумал, что Retool может заинтересоваться в Faker Cloud, и что, возможно, кто-то из компании напишет мне письмо.

Появляется новый соперник

Прошло ещё три недели. Я получил от Product Hunt уведомление о новом «инструменте api-generator». На день он стал самым популярным продуктом на Product Hunt. Опубликовавшими продукт оказались те же два инженера Retool, которые раньше пользовались Faker Cloud. Я увидел, что Retool создала новый продукт, делающий то же самое, что и Faker Cloud. Я увидел, что Retool использует для генерации данных своего сервиса Faker. Также я увидел, что Retool предлагает этот новый сервис бесплатно.

Тогда кто CDN?

Я зарегистрировался на сайте Retool, чтобы попробовать их новый api-generator, и заметил, что он может генерировать изображения-аватары для пользователей. Я сгенерировал фальшивый аватар пользователя Retool.com, вот ссылки, которые он генерирует:

image

Новый сервис Retool использует изображения, хостящиеся с fakercloud.com.

Дела.

Предзнаменование

Я почитал комментарии на Product Hunt и поискал в Twitter. Выяснилось, что около десятка разработчиков Retool из отделов развития, маркетинга и разработки продвигают новый сервис Retool.

Хм-м-м… Да, тяжело одному человеку конкурировать с компанией, получившей финансирование в размере 75 миллионов долларов. Особенно когда она совершенно законно может копировать твою интеллектуальную собственность.

Я никогда не надеялся, что Faker Cloud обретёт огромный бизнес-успех. Я надеялся, что Faker Cloud сможет привлечь небольшой сегмент рынка пользователей, чтобы помочь в финансировании разработки самого опенсорсного проекта Faker.

В каждом кризисе таятся великие возможности

Мне пришло в голову, что самым лучшим будет признать ситуацию и извлечь из неё хоть какую-то пользу. От работы Faker зависят тысячи разработчиков. Наша задача — продолжать поддержку проекта и его качественную работу. Даже небольшой изъян в инструменте с открытым исходным кодом может привести к миллионам долларов урона из-за потерянного времени.

Я решил написать письмо CEO компании Retool Дэвиду Сюй.

Здравствуйте, Дэвид! Поздравляю с успехом Retool, сервис выглядит отлично.

Я автор популярного проекта faker.js, github.com/Marak/faker.js, and www.fakercloud.com (сервиса хостинга тестовых данных/конечной точки api). Насколько я понимаю, ваши инженеры Retool уже знакомы с Faker.

Я пишу вам, потому что хотел бы продать компании Retool и open-source-проект faker.js, и сервис fakercloud.com. Думаю, это станет большим выигрышем для всех сторон, в том числе и для сообщества open-source. Faker.js требуется надёжное корпоративное руководство, и Retool кажется мне идеальным кандидатом.

Пожалуйста, напишите мне о своём мнении.

Со мной можно связаться по электронной почте или по мобильному телефону: ***-***-****

С уважением,
Marak

Дэвид Сюй ответил мне почти сразу же!

Здравствуйте, Marak, это интересно! Дайте мне один день, чтобы поработать над этим; скоро свяжусь с вами!

Думаю, многие из вас уже догадались, что произошло дальше.

Прошло восемь дней, ответа я так и не получил. CEO — занятые люди. Я написал ещё одно письмо, чтобы напомнить о себе.

Дэвид,

Хотел бы узнать, каково ваше мнение о Faker и Faker Cloud.

Вы уже подумали, как может выглядеть предложение? Я думаю о передаче интеллектуальной собственности Faker с последующим контрактом с Retool по предоставлению услуг консалтинга. В течение этого периода я мог бы консультировать компанию по любым внутренним проектам Retool, проводить обучение инженеров Retool и продолжать работать над Faker.

С уважением,
Marak

Прошло уже около месяца. Ответа я не получил.

Вот и всё. Не знаю, что будет дальше. Мне бы хотелось дождаться счастливого конца, от которого выиграют все заинтересованные, в том числе и сообщество разработчиков.


На правах рекламы

Эпичные серверы — это VDS для размещения сайтов от маленького интернет-магазина на Opencart до серьёзных проектов с огромной аудиторией. Создавайте собственные конфигурации серверов в пару кликов!

Присоединяйтесь к нашему чату в Telegram.

ссылка на оригинал статьи https://habr.com/ru/company/vdsina/blog/560116/

Лаконичный итератор для декларативного синтаксиса

Итератор (от англ. iterator ― перечислитель) — интерфейс, предоставляющий доступ к элементам коллекции (массива или контейнера) и навигацию по ним. В различных системах итераторы могут иметь разные общепринятые названия. В терминах систем управления базами данных итераторы называются курсорами.

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

Ну и судя по моим наблюдениям Хабр — ума палата, буду рад любым комментариям и предложениям, которые помогут протестировать или улучшить предлагаемое решение.

Стандартный итератор

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

Например в С++ это делается с помощью конструкций вида:

for (std::list<int>::iterator it = C.begin(),end = C.end(); it != end; ++it)

Или так:

std::for_each( C.begin(), C.end(), ProcessItem );

В Python так же любой пользовательский класс тоже может поддерживать итерацию. Для этого нужно определить метод __iter__(), который и создает итератор и метод next(), который должен возвращать следующий элемент.

for value in sequence:      print(value) it = iter(sequence) while True:     try:         value = it.next()     except StopIteration:         break     print(value)

В Java использование итераторов выглядит примерно также.

Iterator iter = list.iterator(); //Iterator<MyType> iter = list.iterator(); в J2SE 5.0 while (iter.hasNext())     System.out.println(iter.next()); 

или даже так

for (MyType obj : list)     System.out.print(obj);

Общепринятая логика у итератора следующая:

  1. После создания итератора, указатель сразу содержит актуальные данные
  2. Операции получения данных и перемещения указателя могут быть раздельными
  3. Большинство языков программирования поддерживают несколько управляющих конструкций с помощью которых может быть реализован перебор элементов коллекции с использованием итератора
  4. После завершения обхода всех элементов, итератор встает на позицию «за последним элементом», тем самым делая невалидной операцию чтения данных

Концепция итератора для нового языка

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

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

В большей степени из-за необходимости работать с объектами из базы данных, так же как с локальными объектами, итоговая концепция итератора немного (или наоборот много) отличается от общепринятой классической, вынесенной в заголовок статьи.

  1. При создании итератор не содержит актуальных данных, только необходимые параметры доступа к ним. Фактически, это можно интерпретировать как положение указателя на позиции «перед первым элементом». А реальная инициализация итератора происходит только при сбросе, который выполняется неявно при выполнении первого чтения данных.
  2. Перемещение указателя на следующий элемент выполняется всегда после получения новой порции данных автоматически. Если необходимо оставлять курсор на текущей позиции (т.е. считывать одни и те же данные постоянно), то после каждого чтения необходимо возвращать позицию курсора назад, на количество реально считанных данных.
  3. После завершения обхода коллекции, указатель итератора остается на последней позиции данных, а не переходит «за последний элемент» как в случае с классическими итераторами. Это сделано для того, чтобы операция чтения данных у завершившегося итератора всегда была валидной. Конечно, кроме того случая, когда данные отсутствуют изначально.

Для чего выбрана такая логика работы с итератором?

Создание итератора

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

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

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

Именно из-за этих особенностей было решено отделить «создание итератора» (в случае работы с базой данных, это будет описание способа доступа к данным из таблиц), от фактического доступа к данным, т.е. к первому элементу из всего набора. Поэтому, во время создания итератора, доступ к первому элементу данных не выполняется. Он происходит только при сбросе итератора, который может выполняться автоматически при первом чтении данных.

Автоматическое перемещение итератора

Как было указано выше, перемещение внутреннего указателя на следующий элемент данных выполняется всегда и автоматически, а если необходимо оставлять курсор на текущей позиции (т.е. считывать одни и те же данные постоянно), то после каждого чтения необходимо возвращать позицию курсора назад, на количество реально считанных данных. Фактически это повторяет логику работы итератора в Python (т.е. выполнение метода next).

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

Завершение работы итератора

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

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

Другими словами, если использовать такое поведение итератора, то при получении текущего значения становится неважно, к каким данным происходит обращение и использовать интерфейс итератора можно даже при обращении к обычным переменным (не коллекциям)!

Просто в этом случае всегда будет возвращаться её актуальное значение. Конечно, последующее перемещение курсора на очередной элемент данных не произойдет, но сами данные с точки зрения логики работы итератора будут корректны.

Синтаксис лаконичного итератора

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

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

Довольно часто в различных языках программирования встречается управляющая конструкция вида name? или ?name. При этом интуитивно понятно, что требуется вывести значение переменой в консоль или отладочный лог. Причем, данная конструкция выглядит очень естественно и согласуется с привычным использованием данного знака препинания (знак вопроса).

И приняв это за отправную точку, операция чтения данных из итератора в декларативном стиле получается следующая:

? — итератор возвращает весь набор элементов из коллекции в виде массива. Коллекция возвращается полностью, независимо от текущего положения курсора. Фактически, это означает, что перед каждым выполнением данного оператора, у итератора выполняется операция сброса в начальное состояние. Так же, с помощью конструкции вида ?(…) можно считывать произвольное количество возвращаемых элементов, например для пагинации.

! — итератор возвращает один текущий объект из коллекции и переводит указатель на следующий элемент (сброс/инициализация итератора выполняется неявно и автоматически при обращении к первого элементу). В данном случае, операция чтения итератора возвращает именно сам элемент, а не массив с одним элементом. Если необходимо считать элемент данных как элемент массива, то необходимо использовать конструкцию ?(1).

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

Хотя при необходимости, количество операторов для работы с итераторами может быть расширено. Например можно добавить оператор "!-" или "!!", который будет считывать один элемент данных и возвращать указатель на одну позицию назад, а оператор "??" считывать только остаток коллекции без принудительного сброса указателя в начало перед чтением данных.

Примеры использования

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

Таким образом, конструкция «name?» будет означать создание итератора и вывод всех элементов коллекции, причем слева от итератора указываются параметры его создания. В общем случае, это будет класс терминов для чтения или имя функции/переменной. Дополнительно, в качестве аргументов можно задать и другие параметры, например для фильтрации терминов по заданным критериям: «human(sex=man)?», но это уже зависит от реализации конкретного итератора.

Вообще все термины можно вывести с помощью конструкции "@term?", т.к. любой термин является производным от базового класса «term», поэтому строки «human(sex=man)?» и "@term(class=human, sex=man)?" будут эквивалентны.

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

human::brother(test=human!) &&= $0!=$test, $0.sex==male, @intersec($0.parent, $test.parent); human.brother?

ссылка на оригинал статьи https://habr.com/ru/company/timeweb/blog/559916/

PHP Дайджест № 204 (17 – 31 мая 2021)

Фото: Christian Münch.

В эти две недели core команда PHP активно обсуждала предложение по Partial function Application и в качестве альтернативы Никита Попов предложил более простой синтаксис для получения ссылки на любые функции. Также в уже принятые в PHP 8.1 енумы предлагается добавить статические свойства.

Symfony 6 будет требовать PHP 8.0, а вышедшая Doctrine 2.9 поддерживает указание метаданных в атрибутах вместо PHPDoc.

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

Приятного чтения!

PHP Internals

  • [RFC] First-class callable syntax

    В качестве альтернативы довольно сложному [RFC] Partial Function Application Никита предлагает более простое решение проблемы получения ссылки на любую функцию или метод.

    // Сейчас вот так $fn = Closure::fromCallable('strlen'); $fn = Closure::fromCallable([$this, 'method']); $fn = Closure::fromCallable([Foo::class, 'method']);  // Предлагается вот такое $fn = strlen(...); $fn = $this->method(...); $fn = Foo::method(...); 

    И соответственно, такой синтаксис можно будет применять везде, где ожидается Callable. Например, вот так:

    array_map(Something::toString(?), [1, 2, 3]); array_map(strval(...), [1, 2, 3]);  // вместо array_map([Something::class, 'toString'], [1, 2, 3]) array_map('strval', [1, 2, 3]); 

  • [RFC] Disable autovivification on false

    Сейчас PHP позволяет инициализировать массив из переменной со значением null или false. Предлагается для false все-таки бросать Fatal error:

    $a = true; $a[] = 'value'; // Fatal error: Uncaught Error: Cannot use a scalar value as an array  $a = null; $a[] = 'value'; // Ok  $a = false; $a[] = 'value'; // Сейчас это работает, но предлагается задепрекейтить 

    3v4l.org/UucOC

  • [RFC] Allow static properties in enums

    В PHP 8.1 будут енумы. Подробный разбор был video на стриме PHP-дайджеста и в тексте на php.watch.

    В енумах могут быть статические методы и константы, а предлагается добавить еще статические свойства.

    Пример использования

    enum Environment {     case DEV;     case STAGE;     case PROD;      private static Environment $currentEnvironment;      /**      * Read the current environment from a file on disk, once.      * This will affect various parts of the application.      */     public static function current(): Environment {         if (!isset(self::$currentEnvironment)) {             $info = json_decode(file_get_contents(__DIR__ . '/../../config.json'), true);             self::$currentEnvironment = match($info['env']) {                 'dev' => self::DEV,                 'stage' => self::STAGE,                 'prod' => self::PROD,             };         }         return self::$currentEnvironment;     }     // Other methods can also access self::$currentEnvironment } printf("Current environment is %s\n", Environment::current()->name); 

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

    Кстати, в релизе PhpStorm 2021.2 уже будет поддержка enum, а пощупать можно будет на этой неделе в выпуске 2021.2 EAP.

  • [PR] Поддержка HTTP Early Hint support

    По умолчанию, PHP поддерживает отправку только одного набора заголовков. Но статус коды HTTP 1xx могут потребовать отправки нескольких наборов хедеров. В частности, для использования 103, нужно сначала отправить заголовки Link, и затем, когда весь ответ будет готов, отправить обычные 200 OK.

    Сейчас такое можно сделать, но немного криво: заголовки 103 отправить, как обычно, через header(), а следующую порцию заголовков — вручную прям через echo.

    Никита предлагает добавить функцию для того, чтоб можно было отправлять несколько наборов заголовков. В пул-реквесте обсуждение API с участием команды Symfony и одним из авторов спецификаций HTTP.

  • check [RFC] Add IntlDatePatternGenerator

    Предложение принято. В PHP 8.1 будет класс IntlDatePatternGenerator для быстрого создания дат в локализированном формате. Подробнее в PHP Internals News #85 с автором RFC.

  • [RFC] Final class constants

    На голосовании.

  • В Internals обсуждается идея задепрекейтить багтрекер bugs.php.net

    Вместо него предлагается использовать issues на GitHub. У идеи есть как плюсы, так и минусы. Но как первый шаг, все баги документации теперь будут Гитхабе. Так что если вы нашли ошибку в мануале PHP, то можно просто создать issue в репозитории php/doc-en или php/doc-ru. Вот пример.

Инструменты

  • Doctrine ORM 2.9 — Большое обновление популярной ORM. Под капотом поддержка атрибутов PHP 8, типизированные свойства, и другое.
  • Flarum 1.0.0 — Релиз популярного движка для форума на PHP.
  • moneyphp/money 4.0 — Пакет для правильной работы с денежными значениями.
  • phpast.com — Просмотр дерева абстрактного синтаксиса PHP. Полезно при отладке инструментов на базе nikic/PHP-Parser. Код на гитхабе: ryangjchandler/phpast.com.
  • JBZoo/CI-Report-Converter — Всеядный конвертер отчетов для CI. Основное призвание утилиты — совместить самый разный результат линтеров с самыми разными CI (TeamCity, GitHub Actions, etc). Прислал smetdenis.
  • veewee/xml — Все для удобной работы с XML в одном пакете.

Symfony

Laravel

Статьи

Аудио/Видео

community Сообщество


Подписывайтесь на Telegram-канал PHP Digest.

Если вам понравился дайджест, поставьте, пожалуйста, ему плюс — это очень мотивирует продолжать делать.

Заметили ошибку или опечатку? Сообщите в личку хабра или телеграм.

Прислать ссылку можно через форму или просто написав мне в телеграм.
Поиск ссылок по всем дайджестам
Предыдущий выпуск: PHP-Дайджест № 203

ссылка на оригинал статьи https://habr.com/ru/post/560158/