Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Базарная площадь
  
О разделе

Основная страница

Группы обсуждений


Тематический каталог обсуждений

Архив

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
 
 04:28 Geo
 
 
Во Флориде и в Королевстве сейчас  04:45[Войти] | [Зарегистрироваться]
Обсуждение темы:
Мысли об Обероне

На базарной площади довольно часто можно слышать высказывания об Обероне. Мне кажется, что на базарной площади пора появиться ветке об этой системе и языке, что-то вроде "Мысли об Обероне". Что это такое, перспективы этой системы, что полезного можно извлечь из него для программирования на Дельфи (например) и др.

Ivan

Количество сообщений на странице

Порядок сортировки сообщений
Новое сообщение вверху списка (сетевая хронология)
Первое сообщение вверху списка (обычная хронология)

Перейти на конкретную страницу по номеру


Всего в теме 4531 сообщение


Ссылки по теме "Оберон" и "Компонентный паскаль"



Отслеживать это обсуждение


Смотрите также обсуждения:
Free Pascal, Oberon, BlackBox
  • Разработка препроцессора gpre для delphi\freepascal.
  • Component Pascal и среда разработки BlackBox
  • FreePascal: реальная альтернатива или OpenSource — блажь?

  • <<<... | 3931—3922 | 3921—3912 | 3911—3902 | ...>>>
    Всего сообщений в теме: 4531; страниц: 454; текущая страница: 62


    № 3921   19-12-2005 00:01 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3903« (hugi)
    ___________________________

    Я обеими руками за классы. Аргументация следующая:

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


    Если мы хотим использовать модуль, то мы не должны объявить переменную экспортируемого модулем типа. Мы можем это сделать и то, если нам нужен экспортируемый тип, а не что-то другое. Но если сводить к работе с модулем исключительно как с АТД, то конечно, переменную нужно объявлять. Не думаю, однако, что это сильно вас смущает.

    Видимо вас смущает то, что в случае модулей (как вы считаете) обращение к методам (операциям) строится иначе в человеческом восприятии. Т.е. вместо "модуль.операция(параметры)" применяется "класс.метод(параметры)". В языках малого Оберон-семейства вторая форма так и выглядит. Более того, в языках Оберон-2 и Компонентный Паскаль использутся т.н. связанные процедуры (type-bound). Они "намертво" привязаны к типу. И в этом смысле являются методами-константами для всех экземпляров данного класса.


    2)В книге Т. Бадда "ООП" утверждается, что для эффективного построения иерархии наследования в предметной области нам нужно средство представления исключения из общего правила. (Там приводится пример с утконосом, который является млекопитающим, но тем не менее откладывает яйца.)
    Насколько я понял, даже при использовании концепции расширяемого типа данных, такое средство  не предосталяется (по крайней мере в том же Oberon'е его нет, опять же, насколько я понял).


    В языке Оберон (но не в Оберон-2 и не в КП) можно создавать класс, в котором у любого его экземпляра (забудем на время про производные классы) можно полностью заменить все методы. Заменить на лету, во время выполнения. Уж такой гибкости подавляющее большинство ООП-языков не дает. Это т.н. instance-oriented approach, который противопоставляется в чистом Обероне традиционному class-oriented approach. Это связано с тем, что поддержка классов в Обероне построена на расширении типа и процедурных переменных. В традиционных ООП-языках используются процедурные константы (методы). Именно поэтому можно считать чистый Оберон своеобразным ООП-ассемблером.

    3)Концепция интерфейсов. Примерно в том виде, в котором они существуют в COM, а точнее в Delphi'йской реализации COM. (Я имею в виду наличие в языке предложения "класс (или, если угодно, модуль) реализует интерфейс"; т.е. представление интерфейсов как отдельных сущностей, а не производных реализации класса (модуля).) В случае с модулями (в том же Oberon'е) использование интерфейсов в таком виде вряд ли возможно.

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

    Кроме того, у Оберон-модуля может быть только один интерфейс, хотя в языке Modula-3 интерфейсов у модуля может быть несколько. Думаю, про интерфейсы мы еще успеем детально поговорить. Здесь в самом деле у модулей есть ахилесова пята.

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



    № 3920   18-12-2005 22:56 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3912« (ASU)
    ___________________________

    Только больших систем, лучше, не касались бы...

    Не знаю, это ли имел в виду уважаемый коллега, но все когда-либо написанные мной программные продукты по объему не превосходили 10-15 тыс. строк исходного кода. Да и по качеству кода их можно отнести к посредственным.

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

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


    № 3919   18-12-2005 16:40 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3916« (AVC)
    ___________________________

    Наверное, мое восприятие ситуации слишком просто.
    Модуль расширения сам регистрирует свои услуги в соответствующих системных модулях.


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


    № 3918   18-12-2005 16:15 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3916« (AVC)
    ___________________________

    AFAIK, в BlackBox каждая подсистема может изменить меню, определив в подкаталоге Rsrc файл Menus.odc.
    Этот файл (как и другие ресурсные файлы -- Strings.odc и т.д.) не требует компиляции (и не компилируется).
    Подсистема устанавливается простым копированием каталога.
    Я рассматриваю здесь BlackBox как типичного в данном отношении представителя Обероновского семейства языков.
    Выходит, что в перекомпиляции нет необходимости.


    К сожалению, не знаком с BlackBox, и поэтому понимаю, что в таком форуме мои замечания, мягко говоря, не совсем к месту. Приношу извинения.

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

    Приведу еще один пример. Вы пишете транслятор с расширяемого языка. Дополняете язык новой конструкцией, скажем, условным оператором. Реализуете эту конструкцию в виде модуля. Этот модуль оставляет след во всех компонентах транслятора: в лексическом и синтаксическом анализаторе, в генераторе кода. Что он добавит в лексический анализатор? Вообще говоря, только допишет в таблицу три-четыре лексемы "if", "then", "else"… Хотелось бы, чтобы здесь сработал тот же механизм расширения, что и с плагинами, и с меню. Замечу, что два предыдущих примера (с меню и плагинами) предложил не я, а другие участники форума.

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

    Об ассоциативных конструкциях. На их более-менее аккуратное описание потребуются одна-две страницы. Мне кажется, я тут и так злоупотребляю пространством. Если хотите, посмотрите на мои примеры в "Открытых системах"

    http://www.keldysh.ru/dpt_19/grow.htm
    http://www.keldysh.ru/dpt_19/prep3797.htm
    http://www.osp.ru/os/1996/04/65.htm

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


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

    Второй: а надо ли делать именно так? Ведь загрузка модуля может оказаться излишней, если его возможности не будут использоваться.
    Возможно, здесь лучше использовать те самые ассоциативные конструкции, если я правильно догадываюсь, что это такое. :)
    (В упомянутой книге Рейзера и Вирта чтобы создать объект типа Ellipse пользователь мог бы явно вызвать команду Ellipses.Set, что, в случае необходимости, привело бы к загрузке модуля Ellipses.)


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

    Но ведь (пере)трансляция требует как минимум наличия исходных текстов. А если их нет?

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


    № 3917   18-12-2005 15:24 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3913« (hugi)
    ___________________________


    Один класс может реализовывать несколько интерфейсов. Можно ли наследовать от нескольких типов данных (или классов -- извините, не знаком с этим языком) в AO?

    В нем есть понятие аналогичное интерфейсам Явы, но на практике оно не используется (по крайней мере найти примеры в исходниках BlueBottle достаточно сложно).

    Реализации многоязыковых систем (а DLL и COM обеспечивают независимость от языка программирования) со столь же прозрачным механизмом взаимодействия мне не известны. (Вот про .NET ничего не могу сказать -- не знаком пока, но там, вроде, всё те же *.dll и *.exe). НО! Я совершенно не утверждаю, что подход Oberon'а не может быть реализован для многоязыковых систем! Однако примеры таких реализаций мне не известны.

    В ETH была диссертация посвященная интеграции Java (как языка) в среду BlueBottle. Наверно возможно сделать то же в отношении других языков этого класса (C#, Eiffel), по крайней мере с той же степенью успешности, с которой это сделано в .NET.


    № 3916   18-12-2005 14:55 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3901« (Горбунов-Посадов)
    ___________________________


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


    AFAIK, в BlackBox каждая подсистема может изменить меню, определив в подкаталоге Rsrc файл Menus.odc.
    Этот файл (как и другие ресурсные файлы -- Strings.odc и т.д.) не требует компиляции (и не компилируется).
    Подсистема устанавливается простым копированием каталога.
    Я рассматриваю здесь BlackBox как типичного в данном отношении представителя Обероновского семейства языков.
    Выходит, что в перекомпиляции нет необходимости.

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

    Наверное, мое восприятие ситуации слишком просто.
    Модуль расширения сам регистрирует свои услуги в соответствующих системных модулях.
    Остаются два вопроса.
    Первый: кто загрузит модуль расширения, чтобы он мог это сделать? :)
    Второй: а надо ли делать именно так? Ведь загрузка модуля может оказаться излишней, если его возможности не будут использоваться.
    Возможно, здесь лучше использовать те самые ассоциативные конструкции, если я правильно догадываюсь, что это такое. :)
    (В упомянутой книге Рейзера и Вирта чтобы создать объект типа Ellipse пользователь мог бы явно вызвать команду Ellipses.Set, что, в случае необходимости, привело бы к загрузке модуля Ellipses.)

    Если это с моей стороны не наглость, то
    Вопрос 1: что такое ассоциативные конструкции?
    Вопрос 2: действительно ли требуется перекомпиляция?


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


    Но ведь (пере)трансляция требует как минимум наличия исходных текстов. А если их нет?

     AVC


    № 3915   18-12-2005 14:42 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3912« (ASU)
    ___________________________

    Не скучно у вас здесь... по прежнему... Только больших систем, лучше, не касались бы... чтобы не смешить народ.

    Черт возьми, приятно слышать конструктивные слова от специалиста в области разработки больших систем.

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

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

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


    № 3914   18-12-2005 14:35 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3904« (Горбунов-Посадов)
    ___________________________

    Проблему автор чувствует достаточно глубоко. Однако находится в плену запрета на перекомпиляцию. В результате появляются динамические реестры и другие непростые конструкции. Неужели Вирт имел в виду нечто подобное?

    Здесь есть три момента:

    1. Сама по себе возможность расширения систем без перекомпиляции -- важное конкурентное преимущество данной технологии.

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

    3. Традиционная технологическая цепочка "компиляция" -- "компоновка" -- "загрузка" может быть сведена к минимуму: "компиляция" -- "загрузка". Более того, Микаэль Франц в своей диссертации [M.Franz. Code-Generation On-the-Fly: A Key to Portable Software (1994), http://www.oberon2005.ru/paper/eth10497.pdf ] показал, что в компиляторе можно отсечь кодогенератор и совместить его с линкующим загрузчиком. Это позволяет добиться крайне высокой мобильности кода. Кроме того, если брать схему Франца, то по сети передается абстрактное представление программы (абстрактные деревья Франца), являющееся результатом синтаксического и лексического анализа. А значит, можно просто передавать по сети исходный текст, который будет предварительно проходить всего лишь стадию статической верификации (псевдокомпиляции), чтобы гарантировать корректность компиляции на лету удаленным линкующим загрузчиком. В этом случае загрузчик может выполнять все три функции -- компиляцию, компоновку и собственно загрузку. Мы получаем совпадение между языковым модулем и операционным модулем! Это дает существенные преимущества в создании расширяемых систем (особенно, когда расширяемость осуществляется мобильными модулями-компонентами).


    № 3913   18-12-2005 14:33 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3910« (SAGE)
    ___________________________


    С позиции Oberon - минимализма явный перебор! :)

    Я не касался вопросов минимализма.


    В современной Java (Java2) возможно...


    Реализации ООП в Java я тоже не касался. Кто сказал, что она идеальна?

    Это как-же при этом раздуется синтаксис?!?!?
    Если вся эта четверка присутствует в одном классе, для его реализации как нельзя лучше подошел-бы Oberon-модуль. (ИМХО)

    И тогда вся эта четвёрка присутствовала бы в одном Oberon-модуле. Чем он в этом плане предпочтительнее *.class в Java?!

    Я с теорией ООП вообще-то знаком :)
    А процедур связанных с типом (Oberon-2) в этом случае не достаточно?

    Я Вас в незнании теории ООП вообще-то и не упрекал :)
    Я просто аргументировал свою точку зрения.
    И, кстати, Oberon-2 -- уже сдвиг в сторону ООП и, следовательно, классов. Под модулями я понимал чисто обероновские модули.

    А если через абстрактные типы?
    Немножко повторюсь...
    В диссертации Питера Мюллера http://oberon2005.ru/paper/eth14755.pdf есть раздел 3.6 Plugin Modules and Objects.
    Там изложена концеция создания драйверов устройств путем создания абстрактного интерфейса устройства interface module...
    Целая ОС на этом работает. Bluebottle называется. А что такое COM?
    Шутка :)

    Один класс может реализовывать несколько интерфейсов. Можно ли наследовать от нескольких типов данных (или классов -- извините, не знаком с этим языком) в AO?
    И вот опять Вы ссылаетесь на ОО язык. Oberon таким не является.

    Мне и самому не нравится COM. Но COM -- это только реализация КОП. Очень жаль, что она настолько дискредитировала ООП в Ваших глазах.

    И вообще, мне начинает казаться, что под модулем Вы понимаете просто способ физической организации программных сущностей (будь то классы или абстрактные типы данных с операциями). Если так, то, разумеется, подход Oberon предпочтительнее (очень простой и прозрачный для программиста механизм взаимодействия модулей (хотя в Java такой же, однако здесь много раз упоминалось, что многие её идеи заимствованы из Oberon) вместо хитроумного и чересчур запутанного в COM). Но... предпочтительнее для ОДНОГО языка, ведь, насколько я знаю, все Oberon-системы являются одноязыковыми. Реализации многоязыковых систем (а DLL и COM обеспечивают независимость от языка программирования) со столь же прозрачным механизмом взаимодействия мне не известны. (Вот про .NET ничего не могу сказать -- не знаком пока, но там, вроде, всё те же *.dll и *.exe). НО! Я совершенно не утверждаю, что подход Oberon'а не может быть реализован для многоязыковых систем! Однако примеры таких реализаций мне не известны.
     hugi


    № 3912   18-12-2005 14:24 Ответить на это сообщение Ответить на это сообщение с цитированием
    Ответ на »сообщение 3897« (Руслан Богатырев)
    ___________________________
    «Программирование-в-большом»... А потянете ли с таким грузом... стереотипов? Здесь глупо сравнивать языки а-ля Oberon vs. C++. Смысла нет, ибо с большой высоты отдельных деревьев не различить, даже если одно прямое, а другое кривое... И верить нельзя, даже признанным кумирам... даже в тех вопросах, где их авторитет особенно высок. Можно, конечно, податься на поиски «серебрянных пуль» или «священного Грааля»... Ф. Брукс попытался, но вернулся с пустыми руками. И многие пытались... Н. Вирт, в их числе... А нам «не моги»... страшно должно быть...
    Но чем интересно данное обсуждение... Начали говорить о «наследовании», договорились до отмены, как самого «наследования», так и «инкапсуляции». Стали обсуждать «Поли-Морфизм»... до, чего только не договорились... Можно смело публиковать в разделе «Нелепости», без внимания данные здесь «определения» не останутся... Перешли к «классам» и «модулям»... Смешно... Особенно глупо выглядят попытки мыслить за других, а-ля:
    «1. Все работают на классах
    2. Люди не дураки
    3. Я не дурак и буду работать на классах».

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

    Не скучно у вас здесь... по прежнему... Только больших систем, лучше, не касались бы... чтобы не смешить народ.


    <<<... | 3931—3922 | 3921—3912 | 3911—3902 | ...>>>
    Всего сообщений в теме: 4531; страниц: 454; текущая страница: 62




    Отслеживать это обсуждение

    Дополнительная навигация:
    Количество сообщений на странице

    Порядок сортировки сообщений
    Новое сообщение вверху списка (сетевая хронология)
    Первое сообщение вверху списка (обычная хронология)

    Перейти на конкретную страницу по номеру
      
    Время на сайте: GMT минус 5 часов

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

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

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

    Яндекс цитирования