Re[10]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 10:36
Оценка:
Здравствуйте, eao197, Вы писали:

E>Так вот интересно выслушать соображения о том, в каких случаях выгодно писать internal DSL (здесь уже как раз можно затронуть вопросы предпочтения одного языка другому в конкретных условиях), а в каких таки лучше предпочесть external DSL. Соответственно, узнать, что за цену придется платить в этом случае.


Так заведи соответствующую дискуссию Что ты, собственно, и сделал ниже.

O>>А за разворачивание чересчур уж бурной дискуссии я ответственности не несу — я всего лишь защищался


E>Оправдания -- признак признания вины


Хорошо, что ты не в суде работаешь

E>Nemerle как раз в тему (я сам первым его название здесь упомянул ), но не в качестве противопоставления Nemerle rulez forever!, а C++ must die!

E>Было бы интересно как раз примеры DSL на Nemerle видеть. Скажем о примере с размерностями. Для меня в нем самым интересным является как раз небольшой фрагмент с описанием одних величин через другие. Вот это выглядит интересно. Имхо, это то, что действительно можно считать удачным декларативным DSL.

Это и дальше — +1.

А насчёт external DSL... боюсь, что их писать тяжелее, чем internal. Т.е. я уверен, что тяжелее, но боюсь, что намного. Я, например, из статьи так и не понял, насколько сложно с помощью описанного инструмента создать собственный DSL. Т.е., например, прикрутить DSL, подобный использованному мной, к C++ имхо будет непросто — прийдётся писать как минимум файл грамматики для какого-то парсера вроде Coco/R или ANTLR вместе с кодом, который по AST будет как-то генерить C++-код. Вот мне в итоге непонятно, насколько это будет проще с использованием MPS... примеры из статьи ничего мне не показали в этом плане.
http://rsdn.org/File/27948/bf.gif
Re[12]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 10:39
Оценка:
Здравствуйте, adontz, Вы писали:

A>def acc = phys-value[Time / (Length ^ 2)](1)

A>Я не очень понял, что это

Должен заметить, что я, конечно, могу и на Nemerle написать макрос, с которым можно было бы писать что-то вроде

def acc : custom-unit[1, -2, 0] = 1

и это будет даже проще в реализации, но я сознательно не стану этого делать, поскольку запись будет менее интуитивной.
http://rsdn.org/File/27948/bf.gif
Re[11]: Языково-ориентированное программирование: следующая
От: adontz Грузия http://adontz.wordpress.com/
Дата: 17.04.06 10:39
Оценка:
Здравствуйте, Oyster, Вы писали:

O>
O>def acc = phys-value[Time / (Length ^ 2)](1)
O>


Ой да ладно. Вот это
value[Time / (Length ^ 2)](1)
что такое? Что это за (1)? Передача липового параметра в конструктор переменной единственный смысл которой задать выражению тип? И где тут аналогичный код? У меня тип задаётся слева. Никакого аналогичного кода я пока не увидел.

O>Это я к тому, что тут шаблоны C++ не спасают и на Nemerle присутствует лучшее решение


Только я его так и не увидел. Я ведь ясно сказал
def acceleration_derivative_by_distance : ?что тут писать? =
   (acceleration2 - acceleration1) / (coord2 - coord1)

Вставлять надо туда, где написано "?что тут писать?". а твоё решение как выглядит?
def acceleration_derivative_by_distance =
   phys-value[1 / (Time ^ 2)]((acceleration2 - acceleration1) / (coord2 - coord1));

И это типа лучше?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[16]: Языково-ориентированное программирование: следующая
От: adontz Грузия http://adontz.wordpress.com/
Дата: 17.04.06 10:40
Оценка: -2
Здравствуйте, Oyster, Вы писали:

O>Сравниваются определение типа и определение типа. Жаль, что ты это не понял до этого момента.


Влад назвал это оператором приведения типа.

A>>Во-вторых, мой способ гибче, потому что я не принимаю Си за точку отсчёта и ничто не мешает написать

A>>
typedef physical_value_t<1, 0, 0, double, 100, 1, 1, 1, 1, 1> phys_meter_t;
A>>typedef physical_value_t<1, 0, 0, double, 1, 1, 1, 1, 1, 1> phys_centimeter_t;

O>Где же его большая гибкость, в таком случае?

Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM.

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


O> Отличная отмазка


У тебя есть данные, что новые типы определяются так же часто как используются?

O>Кстати, сам автор исходной библиотеки на C++ признаёт, что такое решение коряво
Автор: CrystaX
Дата: 06.04.06
.


Это другая библиотека
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[12]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 10:42
Оценка:
Здравствуйте, adontz, Вы писали:

A>Ой да ладно. Вот это
value[Time / (Length ^ 2)](1)
что такое? Что это за (1)? Передача липового параметра в конструктор переменной единственный смысл которой задать выражению тип? И где тут аналогичный код? У меня тип задаётся слева. Никакого аналогичного кода я пока не увидел.


Тип слева
Автор: Oyster
Дата: 17.04.06
. Доволен?

O>>Это я к тому, что тут шаблоны C++ не спасают и на Nemerle присутствует лучшее решение


A>Вставлять надо туда, где написано "?что тут писать?". а твоё решение как выглядит?


См. выше. И не придирайся к техническим мелочам
http://rsdn.org/File/27948/bf.gif
Re[17]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 10:48
Оценка: +1
Здравствуйте, adontz, Вы писали:

A>Влад назвал это оператором приведения типа.


Ты бы прочитал про мою библиотеку для начала. Кстати, где это Влад целую строку моего DSL назвал оператором приведения типа? Он говорил чисто про [ kg ], что преобразуется в унарный оператор. В целом же строка задаёт орт массы в системе СГС с коэффициентом нормализации.

A>Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM.


Отлично. Но кто тебе мешает вместо

def vol = 100 m * 10 cm

писать

def vol = Si.Mass(100) * Cgs.Mass(10)

???

A>У тебя есть данные, что новые типы определяются так же часто как используются?


У меня есть данные о том, что записанные с помощью шаблонов юниты тяжело "читать".

O>>Кстати, сам автор исходной библиотеки на C++ признаёт, что такое решение коряво
Автор: CrystaX
Дата: 06.04.06
.


A>Это другая библиотека


Но решение похоже — согласись. Потому что C++ принуждает мыслить одинаково и набор его инструментов ограничен.
http://rsdn.org/File/27948/bf.gif
Re[17]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 10:52
Оценка:
Здравствуйте, adontz, Вы писали:

A>Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM.


Кстати, в моей библиотеке никто тебе не мешает написать не

basisUnits (Si)
(
    // ...
    Length[ m ],
    // ...
),

// ...

units (Cgs)
(
    // ...
    Length[ cm ] - 1.0 / 100.0,
    // ...
)

а

basisUnits (Si)
(
    // ...
    Length[ m ] - 100.0,
    // ...
),

// ...

units (Cgs)
(
    // ...
    Length[ cm ],
    // ...
)

т.е. считать не 1 м, а 1 см нормальной единицей измерения длины. Впрочем, ты должен понимать, что это совершенно непринципиально.
http://rsdn.org/File/27948/bf.gif
Re[13]: Языково-ориентированное программирование: следующая
От: adontz Грузия http://adontz.wordpress.com/
Дата: 17.04.06 10:57
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Тип слева
Автор: Oyster
Дата: 17.04.06
. Доволен?


Абсолютно. Хотя лично мне 1 1 -2 и понятнее, подтверждаю, что ты (наконец то) привёл аналогичное решение.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[18]: Языково-ориентированное программирование: следующая
От: adontz Грузия http://adontz.wordpress.com/
Дата: 17.04.06 10:58
Оценка:
Здравствуйте, Oyster, Вы писали:

A>>Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM.

O>Кстати, в моей библиотеке никто тебе не мешает написать не

Это не гибкость. Гибкость это когда не надо переделывать библиотеку
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[14]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 11:01
Оценка:
Здравствуйте, adontz, Вы писали:

A>Абсолютно. Хотя лично мне 1 1 -2 и понятнее,


Как ты понимаешь, так на Nemerle тоже можно
Автор: Oyster
Дата: 17.04.06
. Но я не знаю, кому ещё такое будет понятнее.

A>подтверждаю, что ты (наконец то) привёл аналогичное решение.


Ну слава Богу!
http://rsdn.org/File/27948/bf.gif
Re[19]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 11:01
Оценка:
Здравствуйте, adontz, Вы писали:

A>>>Гибкость в том, что CM теперь, без коэффициентов, а M = 100 CM.

O>>Кстати, в моей библиотеке никто тебе не мешает написать не

A>Это не гибкость. Гибкость это когда не надо переделывать библиотеку


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

В общем, к чему была эта фраза — не понял совершенно
http://rsdn.org/File/27948/bf.gif
Re[14]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 11:06
Оценка:
Здравствуйте, adontz, Вы писали:

O>>Тип слева
Автор: Oyster
Дата: 17.04.06
. Доволен?


A>Абсолютно. Хотя лично мне 1 1 -2 и понятнее, подтверждаю, что ты (наконец то) привёл аналогичное решение.


В таком случае, ты готов признать свою неправоту
Автор: adontz
Дата: 16.04.06
?:

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


Я имею в виду — ты согласен с тем, что для решения этой задачи, для указания типов явно и гибко скалярные параметры шаблонов не необходимы? И что аналогичное или превосходящее по гибкосте код на C++ решение можно написать на Nemerle?

Я хочу убедиться в том, что ты понял всё то, о чём я говорил, чтобы впредь подобные "дискуссии" не повторялись
http://rsdn.org/File/27948/bf.gif
Re[15]: Языково-ориентированное программирование: следующая
От: adontz Грузия http://adontz.wordpress.com/
Дата: 17.04.06 11:09
Оценка: :)
Здравствуйте, Oyster, Вы писали:

O>Я имею в виду — ты согласен с тем, что для решения этой задачи, для указания типов явно и гибко скалярные параметры шаблонов не необходимы?


Да

O>И что аналогичное или превосходящее по гибкосте код на C++ решение можно написать на Nemerle?


Выделеное вычёркиваем и я согласен.

O>Я хочу убедиться в том, что ты понял всё то, о чём я говорил, чтобы впредь подобные "дискуссии" не повторялись


А можно канфету в награду?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[16]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 11:19
Оценка: +1
Здравствуйте, adontz, Вы писали:

O>>Я имею в виду — ты согласен с тем, что для решения этой задачи, для указания типов явно и гибко скалярные параметры шаблонов не необходимы?

A>Да

Ок

O>>И что аналогичное или превосходящее по гибкосте код на C++ решение можно написать на Nemerle?

A>Выделеное вычёркиваем и я согласен.

Почему вычёркиваем? Сваргать описание юнитов, подобное моему
Автор: Oyster
Дата: 10.04.06
, на C++, а потом вычеркнем. Или заявишь, что моё описание менее удобно?

O>>Я хочу убедиться в том, что ты понял всё то, о чём я говорил, чтобы впредь подобные "дискуссии" не повторялись

A>А можно канфету в награду?

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

Некрасиво писать про невозможность решение чего-либо на каком-либо языке (например, на Nemelre, в котором нет "нормальных шаблонов"), не попробовав (или спросив) об этом предварительно. Особенно если то, что написал, — ложь.
http://rsdn.org/File/27948/bf.gif
Re[12]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 11:48
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Хмм... это идея хорошая, не спорю. Думаю, я даже попробую, как будет время. Правда, тут есть один момент — моя лень Да и статьи я не то чтобы очень часто пишу (скорее, даже не пишу вообще).

В любом случае, спасибо за идею и уверенность в том, что статья найдёт своего издателя — с такими начальными условиями можно и попробовать А уж читателя она найдёт — в этом я точно уверен Пусть эта библиотека никому и не нужна, зато используется в ней много всего.
http://rsdn.org/File/27948/bf.gif
Re[13]: Языково-ориентированное программирование: следующая
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.04.06 12:25
Оценка:
Здравствуйте, Oyster, Вы писали:

O>Хмм... это идея хорошая, не спорю. Думаю, я даже попробую, как будет время. Правда, тут есть один момент — моя лень Да и статьи я не то чтобы очень часто пишу (скорее, даже не пишу вообще).


Лень говоришь? Значит создавать такой объемный код не лень, а описать его лень? Нда...

С написанием статьи я помогу. Это не проблема. Ты хоть как-то напиши, а я подправлю/допишу.
... << RSDN@Home 1.2.0 alpha rev. 637>>
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: Языково-ориентированное программирование: следующая
От: Oyster Украина https://github.com/devoyster
Дата: 17.04.06 12:35
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Лень говоришь? Значит создавать такой объемный код не лень, а описать его лень? Нда...


То ж другое дело Доступно объяснить другим тяжелее, чем написать, естественно.

VD>С написанием статьи я помогу. Это не проблема. Ты хоть как-то напиши, а я подправлю/допишу.


Ну я попробую
http://rsdn.org/File/27948/bf.gif
Re[11]: Языково-ориентированное программирование: следующая
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 17.04.06 12:40
Оценка: 31 (5) +1
Здравствуйте, Oyster, Вы писали:

O>А насчёт external DSL... боюсь, что их писать тяжелее, чем internal. Т.е. я уверен, что тяжелее, но боюсь, что намного.


Все зависит от того, что за DSL мы хотим получить. Могу говорить исходя только из собственного опыта. Когда-то давно, в 2000 году был у меня опыт создания external DSL для вот этого инструмента
Автор(ы): Евгений Охотников
Дата: 31.03.2006
Данная статья знакомит читателя с проектом SObjectizer -- инструментом для агентно-ориентированного программирования на C++. Раcсказывается о его истории, текущем состоянии и ближайших перспективах. Обсуждаются некоторые преимущества, которые дает SObjectizer, а также некоторые его недостатки и проблемы.
. В нем агент HelloWorld, описанный в статье выглядел бы вот так:
unit hello_world;

uses so_lib;

class cHelloWorld {
  event evtStart;

  state stNormal event evtStart;
};

event cHelloWorld.evtStart {{
  std::cout << "Hello, world!" << std::endl;

  SoSendMsgToAgent( "aScadaObjectizer", "msgNormalShutdown", "aScadaObjectizer", 0 );
}}

agent aHelloWorld of cHelloWorld {
  event evtStart
    priority 0
    message aScadaObjectizer.msgStart;
}


Это все. Определение C++ класса и его реализация генерировалась компилятором этого DSL. Можно сравнить с тем примером, который приведен в статье

Но у external DSL было несколько недостатков.
— диагностика ошибок времени компиляции сгенерированного C++ кода. Хоть в C++ код и вставлялись соответствующие инструкции #line, все равно сообщения были трехэтажные из-за хитрых имен классов и методов
— отладка. В общем-то не так уж и страшно, т.к. код события практически один в один совпадал с кодом, укзанным в описании события в {{...}}. Но вот найти это место в горах автосгенерированного кода...
— DSL был предназначен только для статических конфигураций, когда агенты не создаются и не удаляются в процессе работы динамически (сказалась заточенность под АСУТП задачи, где эта ситуация -- обычное дело).

Самый большой недостаток external DSL -- это то, что это был собственный язык, который нуждался в собственном парсере и процессоре. Поэтому при реинкарнировании этого проекта в виде SObjectizer я очень серьезно думал, имеет ли смысл иметь DSL для описания агентов и их классов. В результате, из-за хронического недостатка времени было решено, что на реализацию транслятора нет ресурсов. Действительно, internal DSL на макросах C++ был сделан всего за пару дней. А первоначальный вариант транслятора показанного выше языка с использованием yacc разрабатывался несколько недель. Хотя основная трудоемкость была не в самом синтаксисе языка, сколько в создании корректного и полного кодогенератора.

Тем не менее, при наличии соответствующих ресурсов и/или упрощающих дело инструментов external DSL может быть очень удобным. Из-за того, что:
— external DSL может быть нейтральным по отношению к целевому языку. Например, IDL, из которого может генерироваться код для C++, Java, C#, Smalltalk и т.д.;
— external DSL может быть очень выразительным и не содержать синтаксического оверхеда, который проникает в internal DSL из-за особенностей host-языка. Скажем, в Ruby для DSL используются объекты Symbol (для записи которых приходится использовать нотацию :identifier, хотя лидирующее двоеточие легко пропустить), объекты Hash (при использовании которых приходится использовать нотацию key => value, хотя '=>' в ряде случаев желательно было бы опускать), жестко заданный порядок следования аргументов (хотя в некоторых случаях было бы желательно иметь возможность какой-то аргумент опустить) или же оформлять составные аргументы в виде дополнительных Array или Hash;
— external DSL могут позволять получать абстрактное представление описания (что-то вроде AST или какой-нибудь прикладной модели данных). Причем для разных задач можно получать разные модели. Скажем для статического анализа корректности связей между объектами -- одну модель, для рефакторинга -- другую, для построения документации -- третью. В случае internal DSL получение таких моделей может быть сильно затруднено;
— external DSL могут не иметь проблем при интеграции в один проект нескольких DSL. Например, просто из-за того, что в рамках одного описания нельзя будет смешивать несколько DSL Либо же наоборот, DSL позволяет вставлять в себя вставки "непрозрачного" для него кода, который сохраняется на выходе. Что делает возможным организацию pipeline DSL-преобразований. Скажем, из одного DSL получается cpp-файл, который подается на вход следующему транслятору DSL, на выходе которого следующий cpp-файл и т.д. Хоть и звучит это сложно, но вполне возможно. Например, вот здесь
Автор: eao197
Дата: 08.09.05
я приводил пример external DSL, который генерирует C++ код, содержащий еще один DSL внутри -- комментарии в соответствии с правилами Doxygen-а. А это делает возможным сгенерировать по результирующему C++ коду Reference Manual;
— external DSL может позволять скрывать исходные тексты от клиента/заказчика в некоторых случаях. Например, для решения какой-то прикладной задачи мы используем external DSL и наши собственные, внутренние инструменты для его обработки. На выходе получаем набор исходных текстов для target-языка, по которым нельзя восстановить исходный DSL. Заказчику передается уже сгенерированный код, но не DSL-тексты. В результате мы можем иметь высокоэффективный внутренний инструмент, который мы не обязаны отдавать кому-либо даже при передаче всех исходников прикладной системы заказчику. Для которых языков программирования (для того же Ruby) сокрытие internal DSL от заказчика может быть просто не возможно.

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

В общем, если для поддержки external DSL есть необходимые ресурсы/специалисты/инструменты, то external DSL в некоторых случаях могут быть весьма удобнее internal DSL. Не могу сказать, что это за случаи. Есть подозрение, что когда требуется описание нетривиальной предметной области или же одновременная поддержка нескольких target-языков.

А вообще, это нужно на месте, в зависимости от конкретной задачи, конкретной команды и степени самоуверенности конкретного архитектора DSL принимать решение

Одно для меня очевидно: internal DSL -- это, по сути, еще один способ оформления API (т.е. это больше Domain Specific language). А вот external DSL -- это уже создание отдельного языка (т.е. это больше Domain Specific Language).

O>Я, например, из статьи так и не понял, насколько сложно с помощью описанного инструмента создать собственный DSL. Т.е., например, прикрутить DSL, подобный использованному мной, к C++ имхо будет непросто — прийдётся писать как минимум файл грамматики для какого-то парсера вроде Coco/R или ANTLR вместе с кодом, который по AST будет как-то генерить C++-код. Вот мне в итоге непонятно, насколько это будет проще с использованием MPS... примеры из статьи ничего мне не показали в этом плане.


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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[6]: Языково-ориентированное программирование: следующая п
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.04.06 12:53
Оценка:
Здравствуйте, eao197, Вы писали:

Замени в своих словах Немерле на Руби и попробуй найти 10 отличий.
... << RSDN@Home 1.2.0 alpha rev. 637>>
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Языково-ориентированное программирование: следующая п
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.04.06 12:53
Оценка: +1
Здравствуйте, Oyster, Вы писали:

O>Да и те, другие, вопросы, тоже обсуждаются. Разговор ведь пошёл о Nemerle потому, что появилась идея, что всё это нагромождение из тулзов, предложенное товарищем из JetBrains, возможно, не нужно, а достаточно языка, который позволяет посать обработчики любых DSL на себе.


Именно. Кто-то тоже самое сказал о Руби. И заметь их не нразвали фанатами.

O>Да, Nemerle гибок, но недостаточно для создания любого внешнего (в терминах Фаулера) DSL. Да и возможностей рефакторинга у него ноль на данный момент... Но это не означает, что в этой теме Nemerle лишний на 100%.


Глупость сказал. Создавать внешний ДСЛ можно на любом языке. Темболее на функциональном, так как они просто заточены на парсинг и генерацию.

O>А за разворачивание чересчур уж бурной дискуссии я ответственности не несу — я всего лишь защищался


Дисскуссия развернулась в основном с Адонцом. При этом она идет в общем-то не вокруг того плох Немерле или нет, а вокур того оправдан ли подход основанный на ДСЛ-ях. Естественно что в качесте примера приводится опыт из того языка который лучше всего подходит для ДСЛ-естроителства с нашей точки зрения. Зверек, как я понимаю, соглашаясь со мной в качестве языка для создания подразумевал использование Руби.
... << RSDN@Home 1.2.0 alpha rev. 637>>
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.