@WASD1 отвечу на свой же комментарий, если позволите.
Почему-то нам с Вами в этой ветке не напомнили, что как только разгорается спор о терминах, применение которых разнится от источника к источнику, полезно обратиться к стандартам — воспользоваться терминами из стандарта, если он есть, или опубликовать новый стандарт, если о терминах ещё не договорились.
Итак, внимание!
ГОСТ 19781-90 Обеспечение систем обработки информации программное <...> Трансляция — преобразование программы, представленной на одном языке программирования, в программу на другом языке и в определенном смысле равносильную первой. Транслятор — программа или техническое средство, выполняющие трансляцию программы. Компиляция — трансляция программы с языка высокого уровня в форму, близкую к программе на машинном языке. Компилятор — программа или техническое средство, выполняющие компиляцию. <...> Переиздание. Январь 2010 г.
Спасибо @WASD1 за плодотворную дискуссию, обновил терминологию в соответствии с ГОСТ 19781-90, добавил Вас в благодарности! Пожалуйста, пишите, если ещё найдёте неточности. Улучшим.
Вы действительно сомневаетесь в том, что сегодня compiler в большинстве случаев употребляется как частный случай транслятора, когда целевой язык - бинарный \ объектный \ ассемблер (или другой язык платформы)?
К сожалению, у меня нет под рукой статистики, чтобы однозначно утверждать, что сегодня компилятор в большинстве случаев считают частным случаем транслятора — впрочем, однозначно утверждать, что это не так, я также без подтверждений в виде конкретных цифр не стану, и нигде выше по тексту, кажется, не утверждаю.
Мне встречался и тот, и другой подход к определению «компилятора» и «транслятора». Наверное, надо аккуратно измерить частоту встречаемости этих терминов на ресурсах сообществ по компиляторам, чтобы можно было сделать однозначный вывод, какой вариант более массовый? Персонализированная выдача Google для сбора такой статистики вряд ли подходит. Именно поэтому во избежание путаницы в самом начале статьи явно указано, каким конкретно определением компилятора, и из какой книги, мы будем пользоваться в пределах статьи, чтобы не вводить читателя в заблуждение. Мы можем заменить термин «компилятор» в предисловии и далее в статье, если на это есть веские основания, но надо понять, на какой именно термин и на какой именно приличный SSOT можно было бы сослаться.
Кстати, вот доводы в пользу того, что не всё так однозначно:
На главной странице проекта Babel указано, что «Babel is a JavaScript compiler», хотя данный инструмент транслирует JavaScript-код, в котором используются новые и экспериментальные синтаксические конструкции, в JavaScript-код, совместимый с не самыми новыми браузерами, такими как Internet Explorer 11. Такие инструменты иногда называют транспиляторами/транскомпиляторами, но авторы называют свой инструмент именно компилятором. Впрочем, этот довод на уровне доказательства ссылкой на «README.md случайного проекта на GitHub» можно пропустить, хоть проект и широко используемый.
В репозитории проекта Cython указано, что Cython — это «The most widely used Python to C compiler», при этом указано также, что «Cython translates Python code to C/C++ code». Впрочем, C иногда называют высокоуровневым ассемблером, поэтому данный пункт также можно пропустить. Хотя есть и managed-реализации C, например, Cesium.
В англо-русском словаре терминов по вопросам компиляции русскоязычного сообщества разработчиков компиляторов указано: «Compiler — компилятор, транслятор». То есть, здесь эти 2 термина считают взаимозаменяемыми, насколько я могу судить. Кстати, у сообщества есть чат в Telegram, можно обсудить терминологию ещё и там, помимо этой ветки комментариев, чтобы выяснить, почему написали именно так.
Обратите внимание, правки в соответствии с Вашими замечаниями в части п.2, п.3 и п.4 были ведь сразу внесены, а Вы на ad hominem переходите несколькими комментариями выше в связи с вопросами к п.1. Надеюсь, что цель обсуждения, всё же, в том, чтобы выяснить истину / сделать правильнее, а не в том, чтобы отстоять точку зрения :)
Сделать хорошую работу, и снабдить её разъяснительным текстом лет на 20 устаревшим?
А что именно устарело, не расскажете? Выше в вопросах терминологии компилятор/транслятор пока видно только «так принято». Кем принято, где и когда принято? Выше цитаты из учебников были попыткой намекнуть, что нужен более весомый источник, чем число результатов в поисковой выдаче Google или скопированный текст из README.md случайного проекта, причем источник желательно академического толка, если уж мы полемизируем с S.S. Muchnik и др.
А потом студенты тут на хабре пишут - нас учили всякой устаревшей фигне.
А можно поконкретнее? Определитесь, пожалуйста, «устарело» или «зумеры изобрели», а то, если честно, уже не улавливаю. Спасибо.
На 2-й картинке выше опечатка, без неё разница в количестве результатов несущественна:
Но это говорит только о распространенности обсуждаемых определений, правильно?
Конечно, студентам я рассказываю об исторически сложившихся определениях и разнице между ними (транслятор, транспайлер/транспилятор, компилятор, интерпретатор, ...), но в короткой обучающей статье, на мой взгляд, лучше сослаться на определение из классического учебника. Да и потом, после sed s/компилятор/транслятор статья выглядит уже не так интригующе. А цель — заинтересовать читателя, показать, что сделать свой DSL проще, чем кажется на первый взгляд!
Переводом кода с одного ЯП на другой занимается транслятор (иногда применяют термин "транспилятор"). Компилятор - частный случай транслятора: компилятор переводит код с высокоуровневого языка (обычно ЯП) в машинный \ объектный код.
Рискну предположить, что Вы, вероятно, используете определение компилятора из S.S. Muchnick, Advanced Compiler Design and Implementation, 1997, где компилятором называют «средство перевода программ, написанных на высокоуровневом языке, в эквивалентные программы в объектном коде или машинном коде, предназначенном для выполнения компьютером»? Однако, в начале статьи я намеренно акцентирую внимание читателя на том, что в статье мы используем более широкое определение компилятора из книги K.D. Cooper & L. Torczon, Engineering a Compiler, 2011:
Кроме того, в Advanced Compiler Design and Implementation S.S. Muchnick пишет следующее:
"Передним/задним планом" фронтэнд и бэкэнд называть не принято.
Так называют фронтенд и бэкенд компиляторов в отечественной научной литературе, например, в научных работах [1—3]. Убрал из статьи упоминание этих терминов, чтобы академическая терминология не вызывала вопросов у читателя!
Сегодня (начиная с llvm) компилятор делят на frontend / middleend / backend. Лексер + парсер - малая часть фронтэнда. Основная часть фронтэнда - построение AST и специфические (обычно глобальные) оптимизации над AST.
Постарался прояснить п.3 и п.4 в предисловии — надеюсь, в нынешней редакции статья улучшилась. Отдельное спасибо @Mingun за разъяснения по п.5 в соседнем комментарии!
Соглашусь! Есть ещё интересный момент — состояние peco можно переопределить, добавив новые поля, не сломав при этом уже реализованные peco-грамматики. Это позволит выполнять семантические действия при разборе и реализовать таким образом, например, lexer hack.
Возможно, это пока не окончательная версия библиотеки, и API ещё поменяется — поэтому автор не спешит с публикацией пакета в реестре PyPi.
Есть и другие примеры компиляторов без зависимостей, которые предоставляются только в виде исходного кода — например, компилятор XamlX, используемый в кроссплатформенном GUI-фреймворке AvaloniaUI для трансляции разметки интерфейса в низкоуровневое представление и не опубликованный в реестре NuGet.
Видимо, обновлять связанные репозитории иногда проще через git pull, чем через реестр пакетов. А переключиться на нужную версию библиотеки легко через git checkout :)
не могу понять, как вы пришли к тому заключению, откуда вы к примеру знаете что данный человек именно вам поставил минус, видя только counter?
Пожалуйста, обратите внимание на мой комментарий выше — там была указана цитата про ограничение анонимности при голосовании, которая была прокомментирована. Возможно, я неправильно понял комментарий.
Наличие счётчика же не ограничивает анонимность при голосовании, а просто является характеристикой профиля проголосовавшего? На Хабре, кажется, есть счётчики, которые считают минусы и плюсы и отключают голосование, если их становится слишком много, но такие счётчики скрыты. Ваша идея с их показом в списке проголосовавших звучит неплохо!
думаю что шаг в правильном направлении - это ограничение анонимности при минусовании, одно дело если человек открыто не согласен и выражает это, и несколько другое это возможность анонимно минусовать, зная что ответственности за это не несешь никакой
Чтобы потом можно было переходить в профиль этого человека и ставить минусы всем его комментариям подряд, или тем, с которыми Вы идеологически не согласны? Подобная система работает на ресурсах наподобие VC/TJ, и вот такие рейды минусов на почве несогласия с точкой зрения собеседника или обиды на минус там сплошь и рядом, никакого плюрализма мнений там нет. Имеет смысл рассмотреть ещё варианты.
Есть же ещё конструкции наподобие TaskBuilder и MaybeBuilder, которые позволяют делать optional и task chaining, но через переменные — как раз чтобы не обкладывать всё конструкциями match:
let onHello context =
maybe {
let! message = context.Update.Message
let! name = message.Chat.FirstName
sprintf "Hello, %s!" name
|> sendMessage message.Chat.Id
} |> ignore
Здесь, context.Update.Message — это Option<Message>. Аналогично с FirstName. В случае maybe после let! произойдён early return, если в option лежит None.
Может быть, будет уместным отметить, что для решения описанной задачи генерации IObservable из событий есть инструмент Pharmacist, который работает через ICSharpCode.Decompiler, и его версия в виде ObservableEventsSourceGenerator, которую всё никак не опубликуем.
Спасибо, что нашли время написать развёрнутый комментарий! Было очень интересно ознакомиться с содержательными аргументами и примерами насчёт того, как работают зависимости, и к каким последствиям могут приводить вне зависимости от типа стимула.
Вообще с командами в ReactiveUI работать несколько более удобно, чем с объектами типа Interaction. Привязывать команду модели представления к элементу интерфейса можно как в XAML-разметке — с помощью синтаксиса {Binding CommandName}, — так и в коде на языках программирования C#, F#, или Visual Basic, с помощью extension-методов ReactiveUI, включая методы Bind, BindCommand, OneWayBind, BindTo. То есть можно делать так:
this.BindCommand(
ViewModel,
vm => vm.AwesomeCommand,
view => view.AwesomeButton);
Последний вариант хорош тем, что при переименовании свойства модели представления, к которой мы привязываем данные, мы узнаем о том, что что-то пошло не так, уже на этапе компиляции приложения. Причём для WPF, Windows Forms и Xamarin Forms это более актуально, чем для UWP или Avalonia, которые поддерживают compiled-биндинги. А на Xamarin.Android или Xamarin.iOS других вариантов в общем-то и нет. Дополнительно, можно подписываться на исключения, выброшенные экземплярами ReactiveCommand, двумя способами — можно подписаться на исключения одной команды:
LoadUsers.ThrownExceptions.Subscribe(
exception => /* update property etc. */
);
Такой подход, с одной стороны, позволяет сделать приложение более отказоустойчивым и научить его отправлять отчёты об ошибках куда-нибудь для дальнейшего анализа, а с другой — позволяет не писать try { } catch { } блоки повсеместно в лямбдах, предлагая вместо этого написать реактивный пайплайн наподобие:
_errorMessage = Login // ReactiveCommand<TInput, TOutput>
.ThrownExceptions // Все исключения свалятся сюда.
.Select(exception => exception.Message)
.ToProperty(this, x => x.ErrorMessage);
Впрочем, впоследних версиях ReactiveUI должен быть доступен синтаксис BindInteraction, позволяющий привязывать Interaction к действиям более удобным образом:
// В файле *.xaml.cs:
this.BindInteraction(
ViewModel,
vm => vm.MyInteraction,
context => /* Обработчик взаимодействия. */);
Очень любопытно — у вас всё-таки получилось ознакомиться с научными исследованиями, опубликованными в peer-reviewed журналах, на которые ссылается ваш оппонент в последнем сообщении — можете как-то прокомментировать?
Ну то есть я понимаю, что обращать внимание на негативные стороны порноиндустрии сейчас немодно, но игнорировать неудобные результаты вполне приличных научных исследований, опубликованных в рецензируемых журналах, которые приводит ваш оппонент [1, 2, 3], как-то всё-таки ненаучно.
В треде же, кажется, хотели выяснить истину, а не отстоять свою точку зрения, да и что-то запрещать вроде бы никто не призывал. Заранее спасибо.
Для добавления атрибута с помощью генератора есть две причины. С одной стороны, мы должны ссылаться на генератор по-особенному, как на анализатор — если бы мы решили атрибут не генерировать, нам бы пришлось собирать два пакета — один был бы собственно генератором, а другой — содержал бы атрибут. Такой паттерн использовался, например, в библиотеке Pharmacist ещё до появления .NET 5 source generators. С другой стороны, сами генераторы исходного кода довольно тесно заинтегрированы в .NET CLI, Visual Studio, JetBrains Rider, в результате генерация происходит при любом изменении исходного файла. Выглядит это следующим образом:
Добавлю эту гифку в статью для контекста, спасибо за вопрос!
Вот, кстати, очень любопытно. Допустим, тернистый путь пройден — вы поступили, выучились, университет закончен, колоссальный объём знаний, позволяющий решать огромное количество сложных задач за вменяемое время, получен, престижный диплом — тоже. А что делать дальше? Ну, то есть, вы после окончания университета собираетесь в какую-то конкретную организацию идти работать по специальности? Наверняка уже есть планы — было бы интересно почитать. Apple, Microsoft, Google, или что-то более интересное и наукоёмкое в зарубежных НИИ?
Да, дебажили тестами. Генератор является вообще говоря обычной библиотекой с таргетом на .NET Standard 2.0, если на него сослаться классическим способом, а не как на анализатор (ProjectReference без OutputItemType="Analyzer").
Поэтому весь интересный код можно вынести в internal-объекты, расставить InternalsVisibleTo для проектов с тестами, и обложить эти объекты с интересным кодом тестами, чтоб в нетестируемом коде было нечему ломаться. Потом уже в JetBrains Rider гулять по коду с дебаггером, разбираясь, что и где пошло не так. Тесты, кстати, сейчас лежат тут: https://github.com/AvaloniaUI/Avalonia.NameGenerator/tree/main/src/Avalonia.NameGenerator.Tests (вообще стараюсь избегать ссылок на этот репозиторий в материале, потому что он скоро уедет в главный репозиторий Avalonia)
На самом деле всё не совсем так, как вы пишете. Да, действительно, с выходом .NET MAUI Xamarin.Forms отправится на свалку, потому что .NET MAUI и есть, по сути своей, эволюция Xamarin.Forms с новыми API. При этом, в Microsoft собираются сделать API .NET MAUI совместимым с API Xamarin.Forms. Подробнее о планах команды можно посмотреть в видео с виртуальной конференции ReactiveUI под названием Dualscreen, .NET MAUI and ReactiveUI. Там разработчик нового MAUI и старого Xamarin.Forms делится инсайдами о новом API.
Далее, на странице репозитория dotnet/maui мы видим сводку о поддерживаемых платформах, согласно которой Linux всё так же остаётся community-maintained. Это значит, что, ну, Microsoft Linux поддерживать не будет, а Avalonia уже поддерживает. Не исключено, что может появиться бакенд MAUI, основанный на Avalonia, с помощью которого можно будет обеспечить поддержку Linux — будем посмотреть.
Было бы любопытно посмотреть на что-то подобное, написанное на Xamarin.Forms и работающее на десктопах. Потому что есть мнение, что основной нишей Xamarin.Forms (и MAUI) останутся приложения попроще, больше ориентированные на мобильный сегмент, а не на высокопроизводительный десктоп.
А Uno пока, как говорят, needs more love. Но я слабо знаком с этим фреймворком — про производительность или сегмент, который оно покрывает, ничего не могу сказать. Надо пробовать.
@WASD1 отвечу на свой же комментарий, если позволите.
Почему-то нам с Вами в этой ветке не напомнили, что как только разгорается спор о терминах, применение которых разнится от источника к источнику, полезно обратиться к стандартам — воспользоваться терминами из стандарта, если он есть, или опубликовать новый стандарт, если о терминах ещё не договорились.
Итак, внимание!
Спасибо @WASD1 за плодотворную дискуссию, обновил терминологию в соответствии с ГОСТ 19781-90, добавил Вас в благодарности! Пожалуйста, пишите, если ещё найдёте неточности. Улучшим.
К сожалению, у меня нет под рукой статистики, чтобы однозначно утверждать, что сегодня компилятор в большинстве случаев считают частным случаем транслятора — впрочем, однозначно утверждать, что это не так, я также без подтверждений в виде конкретных цифр не стану, и нигде выше по тексту, кажется, не утверждаю.
Мне встречался и тот, и другой подход к определению «компилятора» и «транслятора». Наверное, надо аккуратно измерить частоту встречаемости этих терминов на ресурсах сообществ по компиляторам, чтобы можно было сделать однозначный вывод, какой вариант более массовый? Персонализированная выдача Google для сбора такой статистики вряд ли подходит. Именно поэтому во избежание путаницы в самом начале статьи явно указано, каким конкретно определением компилятора, и из какой книги, мы будем пользоваться в пределах статьи, чтобы не вводить читателя в заблуждение. Мы можем заменить термин «компилятор» в предисловии и далее в статье, если на это есть веские основания, но надо понять, на какой именно термин и на какой именно приличный SSOT можно было бы сослаться.
Кстати, вот доводы в пользу того, что не всё так однозначно:
На главной странице проекта Babel указано, что «Babel is a JavaScript compiler», хотя данный инструмент транслирует JavaScript-код, в котором используются новые и экспериментальные синтаксические конструкции, в JavaScript-код, совместимый с не самыми новыми браузерами, такими как Internet Explorer 11. Такие инструменты иногда называют транспиляторами/транскомпиляторами, но авторы называют свой инструмент именно компилятором. Впрочем, этот довод на уровне доказательства ссылкой на «README.md случайного проекта на GitHub» можно пропустить, хоть проект и широко используемый.
В репозитории проекта Cython указано, что Cython — это «The most widely used Python to C compiler», при этом указано также, что «Cython translates Python code to C/C++ code». Впрочем, C иногда называют высокоуровневым ассемблером, поэтому данный пункт также можно пропустить. Хотя есть и managed-реализации C, например, Cesium.
В англо-русском словаре терминов по вопросам компиляции русскоязычного сообщества разработчиков компиляторов указано: «Compiler — компилятор, транслятор». То есть, здесь эти 2 термина считают взаимозаменяемыми, насколько я могу судить. Кстати, у сообщества есть чат в Telegram, можно обсудить терминологию ещё и там, помимо этой ветки комментариев, чтобы выяснить, почему написали именно так.
Обратите внимание, правки в соответствии с Вашими замечаниями в части п.2, п.3 и п.4 были ведь сразу внесены, а Вы на ad hominem переходите несколькими комментариями выше в связи с вопросами к п.1. Надеюсь, что цель обсуждения, всё же, в том, чтобы выяснить истину / сделать правильнее, а не в том, чтобы отстоять точку зрения :)
А что именно устарело, не расскажете? Выше в вопросах терминологии компилятор/транслятор пока видно только «так принято». Кем принято, где и когда принято? Выше цитаты из учебников были попыткой намекнуть, что нужен более весомый источник, чем число результатов в поисковой выдаче Google или скопированный текст из README.md случайного проекта, причем источник желательно академического толка, если уж мы полемизируем с S.S. Muchnik и др.
А можно поконкретнее? Определитесь, пожалуйста, «устарело» или «зумеры изобрели», а то, если честно, уже не улавливаю. Спасибо.
На 2-й картинке выше опечатка, без неё разница в количестве результатов несущественна:
Но это говорит только о распространенности обсуждаемых определений, правильно?
Конечно, студентам я рассказываю об исторически сложившихся определениях и разнице между ними (транслятор, транспайлер/транспилятор, компилятор, интерпретатор, ...), но в короткой обучающей статье, на мой взгляд, лучше сослаться на определение из классического учебника. Да и потом, после sed s/компилятор/транслятор статья выглядит уже не так интригующе. А цель — заинтересовать читателя, показать, что сделать свой DSL проще, чем кажется на первый взгляд!
Спасибо за развёрнутый комментарий!
Рискну предположить, что Вы, вероятно, используете определение компилятора из S.S. Muchnick, Advanced Compiler Design and Implementation, 1997, где компилятором называют «средство перевода программ, написанных на высокоуровневом языке, в эквивалентные программы в объектном коде или машинном коде, предназначенном для выполнения компьютером»? Однако, в начале статьи я намеренно акцентирую внимание читателя на том, что в статье мы используем более широкое определение компилятора из книги K.D. Cooper & L. Torczon, Engineering a Compiler, 2011:
Кроме того, в Advanced Compiler Design and Implementation S.S. Muchnick пишет следующее:
Так называют фронтенд и бэкенд компиляторов в отечественной научной литературе, например, в научных работах [1—3]. Убрал из статьи упоминание этих терминов, чтобы академическая терминология не вызывала вопросов у читателя!
Аветисян А.И., Курмангалеев К.Ю., Курмангалеев Ш.Ф. Динамическое профилирование программы для системы LLVM // Труды Института системного программирования РАН. – 2011. – Т. 21. – С. 71-82.
Советов П.Н. Разработка компиляторов предметно-ориентированных языков для спецпроцессоров // Труды Института системного программирования РАН. – 2020. – Т. 32. – № 5. – С. 35-56.
Стасенко А.П. Модели и реализация транслирующих компонентов системы функционального программирования: дис. // Институт систем информатики им. АП Ершова СО РАН, 2009.
Постарался прояснить п.3 и п.4 в предисловии — надеюсь, в нынешней редакции статья улучшилась. Отдельное спасибо @Mingun за разъяснения по п.5 в соседнем комментарии!
Соглашусь! Есть ещё интересный момент — состояние peco можно переопределить, добавив новые поля, не сломав при этом уже реализованные peco-грамматики. Это позволит выполнять семантические действия при разборе и реализовать таким образом, например, lexer hack.
Спасибо!
Возможно, это пока не окончательная версия библиотеки, и API ещё поменяется — поэтому автор не спешит с публикацией пакета в реестре PyPi.
Есть и другие примеры компиляторов без зависимостей, которые предоставляются только в виде исходного кода — например, компилятор XamlX, используемый в кроссплатформенном GUI-фреймворке AvaloniaUI для трансляции разметки интерфейса в низкоуровневое представление и не опубликованный в реестре NuGet.
Видимо, обновлять связанные репозитории иногда проще через
git pull, чем через реестр пакетов. А переключиться на нужную версию библиотеки легко черезgit checkout:)Этот новояз обязательно было добавлять? Как-то не очень конструктивно Хабр превращать в TJournal.
Пожалуйста, обратите внимание на мой комментарий выше — там была указана цитата про ограничение анонимности при голосовании, которая была прокомментирована. Возможно, я неправильно понял комментарий.
Наличие счётчика же не ограничивает анонимность при голосовании, а просто является характеристикой профиля проголосовавшего? На Хабре, кажется, есть счётчики, которые считают минусы и плюсы и отключают голосование, если их становится слишком много, но такие счётчики скрыты. Ваша идея с их показом в списке проголосовавших звучит неплохо!
Чтобы потом можно было переходить в профиль этого человека и ставить минусы всем его комментариям подряд, или тем, с которыми Вы идеологически не согласны? Подобная система работает на ресурсах наподобие VC/TJ, и вот такие рейды минусов на почве несогласия с точкой зрения собеседника или обиды на минус там сплошь и рядом, никакого плюрализма мнений там нет. Имеет смысл рассмотреть ещё варианты.
Есть же ещё конструкции наподобие TaskBuilder и MaybeBuilder, которые позволяют делать optional и task chaining, но через переменные — как раз чтобы не обкладывать всё конструкциями
match:Здесь,
context.Update.Message— этоOption<Message>. Аналогично сFirstName. В случае maybe послеlet!произойдён early return, если в option лежит None.Может быть, будет уместным отметить, что для решения описанной задачи генерации IObservable из событий есть инструмент Pharmacist, который работает через ICSharpCode.Decompiler, и его версия в виде ObservableEventsSourceGenerator, которую всё никак не опубликуем.
Спасибо, что нашли время написать развёрнутый комментарий! Было очень интересно ознакомиться с содержательными аргументами и примерами насчёт того, как работают зависимости, и к каким последствиям могут приводить вне зависимости от типа стимула.
Вообще с командами в ReactiveUI работать несколько более удобно, чем с объектами типа
Interaction. Привязывать команду модели представления к элементу интерфейса можно как в XAML-разметке — с помощью синтаксиса{Binding CommandName}, — так и в коде на языках программирования C#, F#, или Visual Basic, с помощью extension-методов ReactiveUI, включая методыBind,BindCommand,OneWayBind,BindTo. То есть можно делать так:Или так:
Последний вариант хорош тем, что при переименовании свойства модели представления, к которой мы привязываем данные, мы узнаем о том, что что-то пошло не так, уже на этапе компиляции приложения. Причём для WPF, Windows Forms и Xamarin Forms это более актуально, чем для UWP или Avalonia, которые поддерживают compiled-биндинги. А на Xamarin.Android или Xamarin.iOS других вариантов в общем-то и нет. Дополнительно, можно подписываться на исключения, выброшенные экземплярами
ReactiveCommand, двумя способами — можно подписаться на исключения одной команды:Или на исключения всех команд и OAPH в приложении сразу:
Такой подход, с одной стороны, позволяет сделать приложение более отказоустойчивым и научить его отправлять отчёты об ошибках куда-нибудь для дальнейшего анализа, а с другой — позволяет не писать
try { } catch { }блоки повсеместно в лямбдах, предлагая вместо этого написать реактивный пайплайн наподобие:Впрочем, впоследних версиях ReactiveUI должен быть доступен синтаксис
BindInteraction, позволяющий привязыватьInteractionк действиям более удобным образом:Очень любопытно — у вас всё-таки получилось ознакомиться с научными исследованиями, опубликованными в peer-reviewed журналах, на которые ссылается ваш оппонент в последнем сообщении — можете как-то прокомментировать?
Ну то есть я понимаю, что обращать внимание на негативные стороны порноиндустрии сейчас немодно, но игнорировать неудобные результаты вполне приличных научных исследований, опубликованных в рецензируемых журналах, которые приводит ваш оппонент [1, 2, 3], как-то всё-таки ненаучно.
В треде же, кажется, хотели выяснить истину, а не отстоять свою точку зрения, да и что-то запрещать вроде бы никто не призывал. Заранее спасибо.
Для добавления атрибута с помощью генератора есть две причины. С одной стороны, мы должны ссылаться на генератор по-особенному, как на анализатор — если бы мы решили атрибут не генерировать, нам бы пришлось собирать два пакета — один был бы собственно генератором, а другой — содержал бы атрибут. Такой паттерн использовался, например, в библиотеке Pharmacist ещё до появления .NET 5 source generators. С другой стороны, сами генераторы исходного кода довольно тесно заинтегрированы в .NET CLI, Visual Studio, JetBrains Rider, в результате генерация происходит при любом изменении исходного файла. Выглядит это следующим образом:
Добавлю эту гифку в статью для контекста, спасибо за вопрос!
Вот, кстати, очень любопытно. Допустим, тернистый путь пройден — вы поступили, выучились, университет закончен, колоссальный объём знаний, позволяющий решать огромное количество сложных задач за вменяемое время, получен, престижный диплом — тоже. А что делать дальше? Ну, то есть, вы после окончания университета собираетесь в какую-то конкретную организацию идти работать по специальности? Наверняка уже есть планы — было бы интересно почитать. Apple, Microsoft, Google, или что-то более интересное и наукоёмкое в зарубежных НИИ?
Да, дебажили тестами. Генератор является вообще говоря обычной библиотекой с таргетом на .NET Standard 2.0, если на него сослаться классическим способом, а не как на анализатор (
ProjectReferenceбезOutputItemType="Analyzer").Поэтому весь интересный код можно вынести в
internal-объекты, расставитьInternalsVisibleToдля проектов с тестами, и обложить эти объекты с интересным кодом тестами, чтоб в нетестируемом коде было нечему ломаться. Потом уже в JetBrains Rider гулять по коду с дебаггером, разбираясь, что и где пошло не так. Тесты, кстати, сейчас лежат тут: https://github.com/AvaloniaUI/Avalonia.NameGenerator/tree/main/src/Avalonia.NameGenerator.Tests (вообще стараюсь избегать ссылок на этот репозиторий в материале, потому что он скоро уедет в главный репозиторий Avalonia)А, ещё можно делать
context.ReportDiagnostic.На самом деле всё не совсем так, как вы пишете. Да, действительно, с выходом .NET MAUI Xamarin.Forms отправится на свалку, потому что .NET MAUI и есть, по сути своей, эволюция Xamarin.Forms с новыми API. При этом, в Microsoft собираются сделать API .NET MAUI совместимым с API Xamarin.Forms. Подробнее о планах команды можно посмотреть в видео с виртуальной конференции ReactiveUI под названием Dualscreen, .NET MAUI and ReactiveUI. Там разработчик нового MAUI и старого Xamarin.Forms делится инсайдами о новом API.
Далее, на странице репозитория dotnet/maui мы видим сводку о поддерживаемых платформах, согласно которой Linux всё так же остаётся community-maintained. Это значит, что, ну, Microsoft Linux поддерживать не будет, а Avalonia уже поддерживает. Не исключено, что может появиться бакенд MAUI, основанный на Avalonia, с помощью которого можно будет обеспечить поддержку Linux — будем посмотреть.
Далее, ниши у Xamarin.Forms (или MAUI) и AvaloniaUI (или WPF) принципиально разные. Про производительность Avalonia в сравнении с WPF можно посмотреть в Core2D rendering performance WPF vs Avalonia+Direct2D,SkiaSharp,Cairo vs WPF+SkiaSharp. На Avalonia уже пишут сложные кроссплатформенные редакторы наподобие таких:
Было бы любопытно посмотреть на что-то подобное, написанное на Xamarin.Forms и работающее на десктопах. Потому что есть мнение, что основной нишей Xamarin.Forms (и MAUI) останутся приложения попроще, больше ориентированные на мобильный сегмент, а не на высокопроизводительный десктоп.
А Uno пока, как говорят, needs more love. Но я слабо знаком с этим фреймворком — про производительность или сегмент, который оно покрывает, ничего не могу сказать. Надо пробовать.