Что такое генерация в информатике

Что такое генераторы в программировании

Они лениво раз за разом вычисляют новые значения, но не помнят, что было до этого.

В программировании есть инструмент, который позволяет экономить память и при этом обрабатывать огромные массивы данных. Это генераторы. Мы рассмотрим работу генераторов на примере языка Python, но они есть и в других языках.

Классический подход к обработке — итераторы

Допустим, мы хотим вывести числа от 1 до 10 и для этого пишем такой код:

for i in range(1,10):
print(i)

Это один из вариантов реализации цикла. Что делает компьютер, когда обрабатывает такое:

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

Но что, если нам понадобится несколько переменных с диапазоном значений? Например, так:

a = range(1,100)
b = range(1000,2000)
for i in a:
print(a[i-1] + b[i])

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

👉 Итератор в данном случае — это цикл, который обращается к диапазону значений и берёт по очереди оттуда данные. При этом все данные уже есть в памяти.

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

Генераторы — вычисление данных «на лету»

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

Чаще всего генераторы используют как функции. Каждый раз, когда обращаются к такой функции-генератору, она делает так:

Обычно функции возвращают результат своей работы с помощью команды return(), а для генераторов есть специальная команда — yield().

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

Пример из практики

Генераторы часто применяют для одноразовой обработки данных по каким-то правилам. Например, в проекте с генератором текста на цепях Маркова у нас был такой фрагмент кода:

А вот что произошло здесь по шагам:

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

👉 Главный плюс генераторов — их можно указывать в качестве диапазона в циклах. На каждом шаге цикл получает новое значение от генератора и работает уже с ним. Как только у генератора заканчиваются варианты и он останавливается — цикл тоже останавливается.

Вот как мы работаем с этой переменной дальше:

Здесь алгоритм работает так:

❌ Если бы мы не знали про генераторы, нам бы пришлось делать отдельный массив с парами слов и выделять под него память. В нашем проекте так сделать можно, но в реальных задачах с перебором большого количества данных такой подход может съесть всю память.

И что, всё теперь нужно делать на генераторах?

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

Источник

Генерация кода

Смотреть что такое «Генерация кода» в других словарях:

автоматизированная генерация кода — 3.5 автоматизированная генерация кода (automated code generation): Функция автоматизированных инструментов, позволяющая преобразовывать проблемно ориентированный язык в форму, пригодную для компиляции или выполнения. Источник … Словарь-справочник терминов нормативно-технической документации

Компилятор — Эта статья включает описание термина «Компиляция»; см. также другие значения. Компилятор программа или техническое средство, выполняющее компиляцию.[1][2][3] Компиляция трансляция программы, составленной на исходном языке высокого… … Википедия

Кодогенерация — Кодогенерация часть процесса компиляции, когда специальная часть компилятора, кодогенератор, конвертирует синтаксически корректную программу в последовательность инструкций, которые могут выполняться на машине. При этом могут применяться… … Википедия

Open Watcom — Тип Среда разработки программного обеспечения Разработчики Watcom, Sybase, SciTech Software, Открытое сообщество Операционная система Кроссплатформенное программное обеспечение … Википедия

Метапрограммирование — Парадигмы программирования Агентно ориентированная Компонентно ориентированная Конкатенативная Декларативная (контрастирует с Императивной) Ограничениями Функциональная Потоком данных Таблично ориентированная (электронные таблицы) Реактивная … Википедия

Watcom C compiler — Open Watcom Тип Среда разработки программного обеспечения Разработчики Sybase, SciTech Software, Открытое сообщество ОС Кроссплатформенное программное обеспечение Версия 1.8 21 февраля 2009 … Википедия

Watcom C — Open Watcom Тип Среда разработки программного обеспечения Разработчики Sybase, SciTech Software, Открытое сообщество ОС Кроссплатформенное программное обеспечение Версия 1.8 21 февраля 2009 … Википедия

Watcom C++ — Open Watcom Тип Среда разработки программного обеспечения Разработчики Sybase, SciTech Software, Открытое сообщество ОС Кроссплатформенное программное обеспечение Версия 1.8 21 февраля 2009 … Википедия

Watcom Fortran — Open Watcom Тип Среда разработки программного обеспечения Разработчики Sybase, SciTech Software, Открытое сообщество ОС Кроссплатформенное программное обеспечение Версия 1.8 21 февраля 2009 … Википедия

ГОСТ Р МЭК 60880-2010: Атомные электростанции. Системы контроля и управления, важные для безопасности. Программное обеспечение компьютерных систем, выполняющих функции категории А — Терминология ГОСТ Р МЭК 60880 2010: Атомные электростанции. Системы контроля и управления, важные для безопасности. Программное обеспечение компьютерных систем, выполняющих функции категории А оригинал документа: 3.25 N версионное программное… … Словарь-справочник терминов нормативно-технической документации

Источник

Генераторы Python: что это такое и зачем они нужны

Генераторы используют, чтобы оперативная память не давилась большими объёмами информации. В Python это фишки, экономящие память.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Допустим, у вас есть файл, который весит десяток гигабайт. Из него нужно выбрать и обработать строки, подходящие под какое-то условие, а то и сравнить со строками другого большого файла.

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

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

Что делать? Хранить такие объёмы данных в компьютере нереально: они не поместятся в оперативную память — а некоторые и на жёсткий диск. Выход один — обрабатывать информацию небольшими порциями, чтобы не вызывать переполнения памяти. В Python на этот случай есть специальный инструмент — генераторы.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Программист, консультант, специалист по документированию. Легко и доступно рассказывает о сложных вещах в программировании и дизайне.

Что такое генератор и как он работает?

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

Рассмотрим пример: создадим объект-генератор gen с помощью так называемого генераторного выражения. Он будет считать квадраты чисел от 1 до 4 — такую последовательность создаёт функция range(1,5).

Когда мы выведем на консоль переменную gen, то увидим лишь сообщение, что это объект-генератор.

При четырёх вызовах метода next(a) будут по одному рассчитываться и выводиться на консоль значения генератора: 1, 4, 9, 16. Причём в памяти будет сохраняться только последнее значение, а предыдущие сотрутся.

Когда мы попытаемся вызвать next(gen) в пятый раз, генератор сотрёт из памяти последний элемент (число 16) и выдаст исключение StopIteration.

Всё! Генератор больше не работает. Сколько бы мы ни вызывали next(gen), ничего считаться не будет. Чтобы запустить генератор ещё раз, придётся создавать его заново.

И что, для вычисления генератора придётся много раз вызывать next()?

Нет, значения можно вычислять в цикле for. В этом случае метод next() вызывается неявно. Например:

Когда весь цикл пройден, произойдёт исключение StopIteration. Хотя на консоль сообщение об этом не выводится, но генератор помнит о нём и больше работать не будет. То есть цикл for можно запускать только один раз, во второй раз не получится. Нельзя об этом забывать.

И чем помогут генераторы в наших задачах?

Для этого сначала рассмотрим упрощённый способ создания генератора — с помощью генераторного выражения.

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

( выражение for j in итерируемый объект if условие)

Где for, in, if — ключевые слова, j — переменная.

Пример генераторного выражения мы рассмотрели выше. Теперь посмотрим, как можно применить его для обработки большого файла.

Перед нами задача: на сервере есть огромный журнал событий log.txt, в котором хранятся сведения о работе какой-то системы за год. Из него нужно выбрать и обработать для статистики данные об ошибках — строки, содержащие слово error.

Такие строки можно выбрать и сохранить в памяти с помощью списка:

Здесь path — путь к файлу log. В результате сформируется список вида:

[строка1, строка2, строка3, ….. ]

В списке e_l содержатся все строки со словом error, они записаны в память компьютера. Теперь их можно обработать в цикле. Недостаток метода в том, что, если таких строк будет слишком много, они переполнят память и вызовут ошибку MemoryError.

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

Рассмотрим следующий код:

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

Как ещё можно создавать генераторы?

Генераторные выражения — это упрощённый вариант функций-генераторов, также создающих генераторы.

Функция-генератор отличается от обычной функции тем, что вместо команды return в ней используется yield. И если return завершает работу функции, то инструкция yield лишь приостанавливает её, при этом она возвращает какое-то значение.

При первом вызове метода next() выполняется код функции с первой команды до yield. При втором next() и последующих до конца генератора — код со следующей после yield команды и до тех пор, пока yield не встретится снова.

Чтобы было понятнее, рассмотрим небольшой пример:

Здесь функция f_gen(5) при вызове создаёт генератор a. Мы видим это, когда выводим a на консоль.

Посчитаем значения генератора в цикле for.

Как видим, значения переменных n и s между вызовами сохраняются.

Yield — инструмент очень гибкий. Его можно несколько раз использовать в коде функции-генератора. В этом случае команды yield служат разделителями кода: при первом вызове метода next() выполняется код до первого yield, при следующих вызовах — операторы между yield. При этом в генераторной функции необязательно должен быть цикл, все значения генератора и так посчитаются.

Как создать бесконечную последовательность

Рассмотрим, как можно с помощью генератора создать математическую последовательность, например, программу, генерирующую простые числа (напоминаем, это числа, не имеющие делителей, кроме 1).

Наша программа будет последовательно анализировать целые числа больше 1. Для каждого числа n программа ищет делители в диапазоне от 2 до √n. Если делители есть, программа переходит к следующему числу. Если их нет, значит, n — число простое, и программа выводит его на печать.

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

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

Какие ещё методы есть у генераторов?

Когда-то был один next(), но в Python 2.5 появилось ещё три метода:

Рассмотрим пару небольших примеров.

С помощью этих методов можно создавать сопрограммы, или корутины, — это функции, которым можно передавать значения, приостанавливать и снова возобновлять их работу. Их обычно используют в Python для анализа потоков данных в корпоративной многозадачности. Генераторы позволяют создавать сложные разветвлённые программы для обработки потоков.

Что ещё можно сказать

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

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

Изучить генераторы и другие объекты Python можно на курсах в Skillbox. Вы получите серьёзные теоретические знания и практический опыт. С самого начала обучения будете участвовать в реальных проектах. Те, кто успешно окончит курсы, станут программистами middle-уровня, а мы поможем найти хорошую работу.

Веб-скрапинг (web scraping) автоматизированное получение данных с веб-страниц.

Источник

Как компьютер генерирует случайные числа

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

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

Определение того, что именно является случайностью, может быть довольно сложной задачей. Существуют тесты (например, колмогоровская сложность), которые могут дать вам точное значение того, насколько случайна та или иная последовательность. Но мы не будем заморачиваться, а просто попробуем создать последовательность чисел, которые будут казаться несвязанными между собой.

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

Создание случайных чисел из семени

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

Давайте поэкспериментируем с этой идеей и посмотрим, куда она нас приведёт.

Функция искажения будет принимать одно значение, а возвращать другое. Назовём её R.

Числовой круг

Посмотрим на циферблат часов: наш ряд начинается с 1 и идёт по кругу до 12. Но поскольку мы работаем с компьютером, пусть вместо 12 будет 0.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Теперь начиная с 1 снова будем прибавлять 7. Прогресс! Мы видим, что после 12 наш ряд начинает повторяться, независимо от того, с какого числа начать.

Здесь мы получаем очень важно свойство: если наш цикл состоит из n элементов, то максимальное число элементов, которые мы можем получить перед тем, как они начнут повторяться это n.

Теперь давайте переделаем функцию R так, чтобы она соответствовала нашей логике. Ограничить длину цикла можно с помощью оператора модуля или оператора остатка от деления.

Если вы попробуете несколько разных значений, то сможете увидеть одно свойство: m и с должны быть взаимно простыми.

До сих пор мы делали «прыжки» за счёт добавления, но что если использовать умножение? Умножим х на константу a.

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

Эти свойства вместе с правилом, что m и с должны быть взаимно простыми составляют теорему Халла-Добелла. Мы не будем рассматривать её доказательство, но если бы вы взяли кучу разных значений для разных констант, то могли бы прийти к тому же выводу.

Выбор семени

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

Конечный результат

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

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

В разных языках программирования реализация линейного конгруэнтного метода отличается, то есть меняются значения констант. Например, функция случайных чисел в libc (стандартная библиотека С для Linux) использует m = 2 ^ 32, a = 1664525 и c = 1013904223. Такие компиляторы, как gcc, обычно используют эти значения.

Заключительные замечания

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

Генерация случайных чисел имеет множество приложений в области информатики и особенно важна для криптографии.

Источник

Генерация кода во время работы приложения: реальные примеры и техники

Эта статья основана на докладе Raffaele Rialdi (Twitter: @raffaeler) на конференции DotNext 2017 Moscow. Вместе с Рафаэлем мы проанализируем реальные способы использования кодогенерации. В отдельных случаях они позволяют очень сильно улучшить производительность приложения, что в свою очередь приводит нас к дилемме — если сгенерированный код так полезен и мы собираемся его часто использовать, то как же отлаживать этот код? Это один из фундаментальных вопросов, возникающих в реальных проектах.

Рафаэль — практикующий архитектор, консультант и спикер, имеющий MVP в категории Developer Security начиная с 2003 года, который прямо сейчас занимается бэкендами enterprise-проектов, специализируясь на генерации кода и кроссплатформенной разработки для C# и C++.

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

Мы знаем, что программа с рефлексией по определению будет работать медленно. Ей необходимо загрузить метаданные ECMA-335 и интерпретировать их. Они представляют из себя очень компактный набор бинарных данных, их чтение достаточно сложное. Они должны быть компактными, поскольку не должны занимать слишком много памяти после сборки. После того, как эти артефакты развертываются, производительность оказывается неудовлетворительной, поскольку мы имеем дело с очень низкоуровневым API. Кстати говоря, рефлексии можно избежать, если загружать все эти артефакты напрямую из сборок. Об этом я не буду говорить в сегодняшнем докладе, но, если вам это интересно, такой метод я уже применял, чтобы избежать постоянной загрузки и сборки в памяти; можно освободить память от всего, кроме информации о типах.

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

В каких именно случаях может быть необходима генерация кода? Например, при использовании предикатов LINQ. Билдеры предикатов доступны уже давно. Или при использовании формул, скажем, из Excel. Или при загрузке типов из плагина, или при использовании Reactive Extensions. Кто из вас знаком с Reactive Extensions? Это замечательная библиотека, которая позволяет создавать потоки данных и применять выражения, способные фильтровать группы и изменять эти данные. Я покажу многие из этих примеров чтобы продемонстрировать возможности рефлексии.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Чтобы не заскучать, давайте перейдем к демонстрациям. Изначально я не хотел писать средство для синтаксического анализа, поскольку это скучно, такая программа обычно получается медленная, и есть библиотеки, которые выполняют эту задачу лучше, чем самописный код. Мне нужно было нечто небольшое и легко изменяемое. А при написании средств синтаксического анализа приходишь к тому, что надо писать грамматику, приходится использовать много библиотек. Кроме того, хотелось написать инструмент таким образом, чтобы созданные после анализа узлы были похожи на то, что Expressions выражают на самом деле. В итоге я пришел к тому, чтобы представить, к примеру, выражение x + y (которое вы видите в коде) в форме текста, и затем распознать его.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Всё это выглядит неплохо, но хочется попробовать нечто более сложное. Следующий пример пришел ко мне во сне. Я хочу создать лямбду, которая, будучи скомпилированной, преобразует данные в словаре (возможно, JSON) в определенном порядке. Задача достаточно обычная.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Попробуем решить эту проблему другим образом. Здесь в коде создается объект `Order, элементы которого будут поставлены в соответствие с поступающим на вход в класс словарем.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Итак, посмотрим на нашу лямбду после компиляции.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Такого рода операция может быть очень полезной, помогает задуматься, а что за чертовщину я тут написал? При выделении отдельного узла дерева в окне справа появляются свойства и их значения, что весьма удобно. Открываем вкладку «Show the decompiled source» («Показать декомпилированный источник»). Перед нами код, который я написал бы, если бы обладал той информацией, которая была передана генератору кода.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Если скомпилируем с отладкой (нажатием «F11»), мы войдем в автоматически сгенерированный метод, которого мы своими руками не писали. Впечатляет, не правда ли? Здесь видны текущие значения переменных, можно проверить, нет ли ошибок в Expressions. Как видим, значения Description во входном аргументе не было, так что метод TryGetValue был использован не зря.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

В конце рассматриваемой функции мы получаем переменную order с правильным числом значений.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Вот артефакты компиляции:

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Код достаточно запутанный, перекомпилировать его не удастся, поскольку компилятор, Mono.Cecil, не может создать идеальную декомпиляцию. Возможно, ему это будет по силам в будущем. Кроме того, проблема здесь в том, что для Task необходимо сделать инъекцию внешней функции. Это нужно потому, что Expressions были созданы до асинхронных библиотек и до изменений в компиляторе для поддержки async/await. Поэтому невозможно провести генерацию с компилятором и воспользоваться await. Компилятор выполняет все волшебство, так что если вы воспользуетесь ILSpy и посмотрите на артефакт, созданный при помощи await, то увидите там колбек с продолжением. Код получается очень усложненным.

Итак, на чем мы остановились? Мы создали Expressions для генерирования определенных предикатов, функций, достаточно сложных кусков кода с конструкциями if-then-else, throw-catch и многого другого. Давайте теперь поговорим о Roslyn.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Таким образом, у нас доступно достаточно много инструментов, но есть проблема. В Roslyn нет строгой типизации. Есть синтаксические узлы, и они очень просты в использовании, поскольку любой элемент является синтаксическим узлом. Нет необходимости тратить внимание на то, чтобы соединять узлы друг с другом. Но у этого есть обратная сторона. Без той самой жесткой типизации, которая так сильно действует на нервы, когда работаешь с Expressions, мы никогда не знаем наверняка, будет ли правильно работать код, который мы пишем. Поэтому с Roslyn больше шансов возникновения ошибок, чем в коде, написанном с Expressions.
И все же, преимущества Roslyn велики. Им покрывается весь язык, т. е. создавать можно любые конструкции. Например, к Roslyn можно обратиться, если необходимо создавать новые типы во время выполнения программы. Предположим, я хочу создать DTO (Data Transfer Objects) несуществующего объекта во время выполнения. Я не хочу прибегать к помощи AutoMapper, поскольку AutoMapper обычно пользуются во время разработки. Созданный тип должен будет способен фильтровать события, каждое из которых будет различного типа. Если вы хотите указать Expression, его необходимо создать и затем работать с типом, представляющим эти данные. А для их десериализации понадобится DTO.

Первый и наиболее простой способ генерировать код при помощи Roslyn — средство синтаксического анализа, у которого есть API.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Если этой функциональности недостаточно, можно воспользоваться SyntaxGenerator. Это мощный высокоуровневый API, под ним есть синтаксическая фабрика. В нем можно объявлять пространства имен, классы, атрибуты, параметры, иначе говоря, это полноценный язык. А при помощи команды node.AdjustWhitespace() можно сделать стандартные пробелы между узлами.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Второй пример с Roslyn также очень простой.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Мы можем сравнить сгенерированный код в переменной text :

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

И то, как он стал выглядеть после форматирования ( text2 ):

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Я беру кусок сгенерированного кода:

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Таким образом, код можно изменять в зависимости от необходимости. Это несложно и дает огромное количество возможностей.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

В данном примере создается POCO в качестве DTO, очень удобно.

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

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

В конструкторе генерируется код, в поле HashSet

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Там, в свою очередь, происходит создание тривиального свойства. Несмотря на то, что свойство тривиальное, метод получился большой. Причина этого проста. Обычно у свойств есть backfield. Чтобы сделать свойство тривиальным мне необходимо удалить часть кода и заменить его более простой аннотацией. Именно поэтому получение и указание Accessor занимает по три строчки.

Есть вещи, которые в такой ситуации можно автоматизировать. Ведь, в сущности, наша работа сводится к автоматизации различных задач. Mono.Cecil — очень мощное средство. Оно позволяет извлекать инструкции, декомпилировать, фильтровать, просматривать, анализировать их содержимое, рассматривать аргументы инструкций. Представим сценарий, в котором необходимо опознать все вызовы из определенного участка кода. Похожих сценариев очень много, на GitHub много инструментов, выполняющих похожие задачи. Итак, я буду ждать вызовы и искать выполняющий их код. Но вместо того, чтобы при отладке нажимать «F11» на каждый вызов, я хочу инструментировать этот код IL, чтобы осуществлялось логирование.

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

Что такое генерация в информатике. Смотреть фото Что такое генерация в информатике. Смотреть картинку Что такое генерация в информатике. Картинка про Что такое генерация в информатике. Фото Что такое генерация в информатике

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

В заключение скажу, что, в моем видении, будущее генерирования кода скорее всего будет связано с искусственным интеллектом. Признаю, в этом есть нечто пугающее. Я вижу такую схему: своего рода контракт из очень маленьких библиотек, способных генерировать необходимый код, и над ними алгоритмы, движимые ИИ. Это может стать очень мощной машиной. Что из этого возникнет? Сказать не могу. Я пока только изучаю это поле, если вы хотели бы заняться этим вместе со мной, я буду только рад.

Подведу итоги. Не используйте генерацию кода где попало, освобождайте от нее наиболее часто используемые участки кода. Есть важный инструмент, который я предлагаю вам протестировать — Roslyn Quoter. Если в него вбить некоторое выражение, он покажет вызовы, которые понадобятся Roslyn, чтобы создать это выражение. Мне пришла в голову жуткая мысль, попробовать вбить в Roslyn Quoter полученные из него же вызовы, и это привело к переполнению стека генерации кода.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *