LINUX.ORG.RU

Vim или Emacs? А LISP в 2021?

 , ,


1

4

https://www.youtube.com/watch?v=8Q9YjXgK38I&t=42s

Парень в определённых кругах, личность известная.
посмотрел я его ролик, стал ковыряться по истории:

А ведь Crashbandicoot была годной игрой…

Что выбрать? Vim или Emacs?
Изучать в 2021 году Lisp? Если изучать, какой? Практика?
А не засмеют сотрудики?

Времени в сутках маловато, на всё не хватает.


Ответ на: комментарий от monk

Java, Haskell и C# работают намного быстрее любого языка с без статической типизации.

Мне всегда нравились такие высказывания. Главное, foldl авовремя применить ;)))

B0B
() автор топика
Ответ на: комментарий от monk

Не функцию, а версию библиотеки. Например, есть ndarray. Где найти ndarray_unchecked, который не будет проверять размерность переданных матриц при каждой операции?

Зачем для этого аж целую отдельную библиотеку городить? Достаточно uchecked версии некоторых (не всех) методов. И при беглом просмотре что-то uchecked в ndarray попадается. Может и недостаточно, спорить не буду.

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

Хороший (быстрый и безошибочный) код совсем без усилий вообще редко получается. К слову, в одной из подобных тем задавался вопросом - это мне не повезло или никто в С++ не использует at у вектора. Убеждали, что таки не повезло и во многих проектах о безопасности заботятся и соответствующие методы используют. Вот и думай кому верить. (:

Языки в общем случае и отличаются умолчаниями

Это да. В контекста раста вопрос иначе стоит: что легче писать на расте быстро или на С++ безопасно. И заодно как много производительности съедают проверки, имеющиеся по умолчанию.

И в этом смысле умолчания Rust слегка озадачивают

Как по мне, так всё логично: нет смысла от быстрой программы, если она выдаёт мусор.

DarkEld3r ★★★★★
()
Ответ на: комментарий от monk

Тогда нужен тип «индекс массива», привязанный к массиву (его размеру).

Без зависимых типов это всё равно ничего не гарантирует.

Так Rust же вроде как системный.

Зависит от того как ты определяешь «системный язык». К примеру, википедия в этот список включает D и Nim, то есть языки со сборкой мусора, ну и Swift.

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

Будет гораздо надёжнее и не придётся писать unsafe где ни попадя.

Мне и не приходится.

А «гораздо надёжнее» почему? Я бы понял, если бы ты сказал проще или удобнее.

Возвращать Option. А значение возвращать в get_unchecked.

Я не об этом спрашивал: вот пишешь ты а[1], получаешь Option и дальше что? Не говоря уже об этом, что это не избавляет от проверки (то есть «тормозов»).

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

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

Опять же, просишь ты мегабайт памяти - облом, просишь половину - снова нет. И что дальше?

DarkEld3r ★★★★★
()
Ответ на: комментарий от byko3y

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

Интересный у тебя показатель грамотного кода.

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

Нет, не по этой.

замедление разработки вряд ли стоит того

Я вот не стал бы спешить с выводами на чём писать быстрее: на расте или на плюсах. Или ты с каким-нибудь C# сравниваешь? Ну так его раст, вроде как, и не пытается «заменять».

DarkEld3r ★★★★★
()
Ответ на: комментарий от byko3y

и внезапно твоя «безопасность» помножается на ноль.

Так скоро и до «царя» дорастёшь.

либо, как поступили разрабы раста, иногда возвращать ошибку, иногда падать с паникой.

Нет.

DarkEld3r ★★★★★
()
Ответ на: комментарий от B0B

Главное, foldl авовремя применить

Не foldl, а IO. Тогда будет быстро.

И в программе должно быть достаточно много достаточно больших функций. Иначе Node JS всё инлайнит, выводит типы и работает почти как со статической типизацией.

monk ★★★★★
()
Ответ на: комментарий от DarkEld3r

А «гораздо надёжнее» почему? Я бы понял, если бы ты сказал проще или удобнее.

Потому что для любой нетривиальной структуры в Rust приходится писать unsafe. А как только его пишешь, получаешь все риски UB, унаследованные от C/C++.

На нормальных языках песочница не протекает, если не использовать FFI.

Я не об этом спрашивал: вот пишешь ты а[1], получаешь Option и дальше что? Не говоря уже об этом, что это не избавляет от проверки (то есть «тормозов»).

Зато нет паники. И есть стимул использовать get_unchecked, чтобы не писать проверку, если она не нужна. Или писать явно unwrap, если согласен на панику в случае неудачи.

monk ★★★★★
()
Ответ на: комментарий от monk

В std::vector есть operator[] без проверки и метод at() с проверкой.
То есть a[x] для сишного массива и для std::vector даёт одинаковый код, а не добавляет внезапно проверку

Вот, и в STL от MS это дело пофиксили, натыкав в такие места assert-ы. И еще в кучу сишных функций, вроде strncpy_s.

И лиспы оптимизируют, и Lua, и JS.

Лисп без declare type работает примерно в 10 раз медленнее, чем с declare type

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

Я могу сказать точно по поводу питона, что бесконечное число костылей в плане динамичности выполнения не дает возможности выводить типы, инлайнить функции, и скаляризовать данные — хотя это возможно для диалектов и вполне себе делается PyPy через подмножество RPython. Я могу точно сказать, что аналогичный трюк реализован с JS, подмножество называется asm.js, и оно не сильно уступает нативному коду по скорости выполнения. Там главная проблема — это как оттранслировать программу в asm.js и RPython. Что не дает сделать трассирующую JIT-оптимизацию аля JVM или оптимизацию подмножества для лиспа — не могу сказать.

Java, Haskell и C# работают намного быстрее любого языка с без статической типизации.
То есть сборщик мусора даёт умножение времени выполнения на 2, отсутствие статических типов ещё на 10

Я тебя удивлю, но V8 сравнивается оп скорости выполнения с Java, при этом часто потребляет меньше оперативы. А ты думал почему Electron/Node.js схавали всё IT? Есть же жава кроссплатформенная, на ней даже андроид бегает! Почему жавой один гугл пользуется?

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

невозможность эффективного описания новых сложных типов средствами самого языка. То есть, то, для чего в питоне делают сишные расширения

??? Это какой сложный тип можно описать на Си и нельзя на Питоне?

Можно, но ползать это будет настолько чудовищно медленно... Причем, та же проблема есть и в JS, но там хотя бы есть какая-то надежда на asm.js, а в CPython — только сиха.

Множественные наследования бесплатны

С dynamic_cast, vtable, 15 циклов процессора для операции, эквивалентной mov eax, [ebx+0xf4]?

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

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

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

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

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

byko3y ★★★★
()
Ответ на: комментарий от DarkEld3r

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

Использовал ты at вместо индекса — дальше что? Ловить исключение? Лишняя ветвь выполнения? Я уже давно иллюзий не строю по этому поводу: если ветвь исключения не протестирована, то она, скорее всего, отработает неправильно. И ты по итогу меняешь шило на мыло. Потому мне нравится подход Microsoft — программа просто падает.

Вот at и не используют.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

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

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

С типами лисп верит, что программист гарантирует правильность типов в функции.

Я тебя удивлю, но V8 сравнивается оп скорости выполнения с Java, при этом часто потребляет меньше оперативы.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/javascript.html : памяти ест больше везде. От Java на некоторых задачах отстаёт в 3 раза.

А ты думал почему Electron/Node.js схавали всё IT?

Не из-за скорости, а из-за готовой отрисовки через браузер.

С dynamic_cast, vtable, 15 циклов процессора для операции, эквивалентной mov eax, [ebx+0xf4]?

Ну сравни, сколько тактов занимает GTK_IS_TREE_VIEW (tree_view). А эквивалент — это не dynamic_cast, а reinterpret_cast.

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

Что мешает использовать эти структуры из си++?

Только в «любом языке» ты не будешь мономорфные алгоритмы реализовывать как выбор по полю структур «чтобы красивее была архитектура»

В смысле, мономорфные? Если тип точно известен, делай reinterpret_cast.

monk ★★★★★
()
Ответ на: комментарий от byko3y

Использовал ты at вместо индекса — дальше что? Ловить исключение?

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

Потому мне нравится подход Microsoft — программа просто падает.

Поэтому gcc делает программы, которые работают быстрее.

monk ★★★★★
()
Ответ на: комментарий от DarkEld3r

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

Интересный у тебя показатель грамотного кода

Я в растосрачах детально пояснял, что Rust нужен для того и только для того, чтобы бить по рукам намеренно пишущего говнокод индуса, заметающего мусор под ковёр. Отдельные кадры даже создавали тикеты с предложениями опции компилятора для запрета по умолчанию на использование unsafe в код — то есть, вообще фашистский режим вводить. Да, в расте есть вкусные плюшки, но этого мало для того, чтобы резко бежать выбрасывать кресты и начинать писать на расте, который компилируется еще медленнее крестов. Особенно если учесть, что в самих крестах нынче идут подвиги в сторону выпиливания UB из языка.

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

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

Нет, не по этой

Ну посмотри на Firefox. Тоже куча наследия, но переписали же часть на Rust. А команда хрома вполне конкретно высказалась по поводу миграции... примерно так же, как Торвальдс про переписываниt ядра на Rust.

Я вот не стал бы спешить с выводами на чём писать быстрее: на расте или на плюсах. Или ты с каким-нибудь C# сравниваешь? Ну так его раст, вроде как, и не пытается «заменять»

А я бы сказал, что если выдерживать все требования по растовой безопасности, то писать на расте дольше и сложнее.

byko3y ★★★★
()
Ответ на: комментарий от DarkEld3r

либо, как поступили разрабы раста, иногда возвращать ошибку, иногда падать с паникой.

Нет

Что «нет»? Обратился по неверному индексу — получил панику. Вот так вот просто алгоритмическая ошибка превратилась в панику. Обрабатывать каждый доступ к любому контейнеру через Option?

byko3y ★★★★
()

Посмотрел видео, пошел учить лисп в надежде, что уж он-то наведет порядок в моем мозгу и снимет пелену с глаз (с)

А так он все верно сказал: вим - это текстовый редактор и точно не ИДЕ(по крайней мере для плюсов), а вот емакс вполне даже может быть ИДЕ. Идеально зашел мне Doom Emacs(с evil модом офк).

Keltir
()
Ответ на: комментарий от monk

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

Интересная история. Почему даже питон при посредстве транслятора PyPy смог не проверять типы аргументов в иерархиях вызовов, а лисп — не смог?

https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/javascrip... : памяти ест больше везде. От Java на некоторых задачах отстаёт в 3 раза

не везде есть больше. В большинстве случаев они очень близки, кроме двух — binary-tree и k-nucleotide. Причем, условия последней прямо запрещают колхозить собственных хэш-таблицы, хотя все решения из топа именно это и сделали. Да, Java хорошо себя показывает на деревьях... а ты часто думаешь «почему бы не написать реализацию бинарных деревьев на лиспе... или может лучше питон?». Бинарные деревья — это совсем не та структура, с которой работают на высокоуровневых языках, так что результат неудивителен.

Не из-за скорости, а из-за готовой отрисовки через браузер

А Java не рисуется по-твоему? Нестандартные элементы управления на браузере будет посложнее сделать, чем на жаве.

С dynamic_cast, vtable, 15 циклов процессора для операции, эквивалентной mov eax, [ebx+0xf4]?

Ну сравни, сколько тактов занимает GTK_IS_TREE_VIEW (tree_view). А эквивалент — это не dynamic_cast, а reinterpret_cast

reinterpret_cast — эквивалент mov eax, [ebx+0xf4]? Формально — да, но чтобы сделать эту операцию — нужно знать, что перед тобой правильный тип. А как ты это узнаешь? G_TYPE_CHECK_INSTANCE_TYPE/dynamic_cast/etc. А нужны они потому, что вместо передачи аргументов в полиморфные функции (конкретизируемые во время компиляции), мы используем мономорфные функции с базовым классом/интерфейсом в качестве аргумента — очень популярный в ООП прием, и очень непопулярный, например, в хаскеле.

Что мешает использовать эти структуры из си++?

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

В смысле, мономорфные? Если тип точно известен, делай reinterpret_cast

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

byko3y ★★★★
()
Ответ на: комментарий от monk

Поэтому gcc делает программы, которые работают быстрее

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

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Почему даже питон при посредстве транслятора PyPy смог не проверять типы аргументов в иерархиях вызовов

В смысле? У тебя в одном модуле

def foo(x, y):
  return x+y

В другом вызывается m.foo(10, 20) и m.foo(a, b), где у b определён __radd. Вызов m.foo(10, 20) сможет превратиться в 30? А если чуть выше написано if ...: m.foo = bar? Или что значит «в иерархиях вызовов»?

А Java не рисуется по-твоему? Нестандартные элементы управления на браузере будет посложнее сделать, чем на жаве.

В Java нет нативного GUI не уступающего HTML5+CSS3.

мы используем мономорфные функции с базовым классом/интерфейсом в качестве аргумента — очень популярный в ООП прием, и очень непопулярный, например, в хаскеле.

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

И вызов с базовым классом/интерфейсом требует dynamic_cast только если в алгоритме требуется приведение к классу-наследнику, что для ООП вообще-то нетипичная ситуация. В типичной просто дёргаешь функцию через vtable интерфейса и всё.

monk ★★★★★
()
Ответ на: комментарий от monk

В другом вызывается m.foo(10, 20) и m.foo(a, b), где у b определён __radd. Вызов m.foo(10, 20) сможет превратиться в 30?

RPython запрещает использование многих методов с подчеркиваниями. потому __radd__ будет оттранслировано. Там, где можно однозначно вывести тип и всё заинлайнить, m.foo(10, 20) превратится в 30. Там, где код более полиморфен, сложение будет заменено явным запросом методов.

В Java нет нативного GUI не уступающего HTML5+CSS3

А давай поставим вопрос так: почему в браузерах, и даже в .NET появился развитый нативный GUI, а в жаве — нет? Да возьми даже адоб флеш, который утёр нос жаве в свое время.

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

Но я напоминаю, что C++ возник именно как «Си с классами». Не «Си с шаблонами». И вот именно от этого «Си с классами» все проблемы: убери Си и классы из крестов — получится удобный и современный ЯП.

И вызов с базовым классом/интерфейсом требует dynamic_cast только если в алгоритме требуется приведение к классу-наследнику, что для ООП вообще-то нетипичная ситуация. В типичной просто дёргаешь функцию через vtable интерфейса и всё

Сорта говна — dynamic_cast не через vtable делается? Просто меньше движений нужно сделать, но если метод однострочный, то их все равно сильно больше, чем нужно.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Там, где можно однозначно вывести тип и всё заинлайнить, m.foo(10, 20) превратится в 30. Там, где код более полиморфен, сложение будет заменено явным запросом методов.

Он будет инлайнить из другого скомпилированного модуля?

А что будет, если

def bar():
  return m.foo(10, 20)

def baz():
  m.foo = lambda x,y: x-y

def main():
  if readYN(): baz()
  print(bar())

?

bar инлайнится, но как компилятор определит, что его надо перекомпилировать после выполнения baz?

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

почему в браузерах, и даже в .NET появился развитый нативный GUI, а в жаве — нет?

Потому что пользователей браузеров на пару порядков больше, чем пользователей программ на жаве. А какой такой в .NET? Вроде Electron и его вытеснил.

Но я напоминаю, что C++ возник именно как «Си с классами». Не «Си с шаблонами».

Си с классами был Objective C. С++ родился с шаблонами.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Он будет инлайнить из другого скомпилированного модуля?

Да, из другого модуля, через всю программу — в этом и смысл RPython. Я начинаю понимать, почему так тяжело оптимизировать программу на лиспе, но все же не решаюсь на какую-то конкретику.

bar инлайнится, но как компилятор определит, что его надо перекомпилировать после выполнения baz?

Вызов функции не меняет алгоритма, если эта фнукция не вызывается в другом месте. Грубо говоря, ты написал:

def main():
  if readYN(): m.foo = lambda x,y: x-y
  print(m.foo(10, 20))

Я не знаю, какое решение здесь примет компилятор PyPy. Он анализирует ветки выполнения и зависимости данных, потому при условии отсутствия доступа к этим переменным извне достаточно развитый оптимизатор выдаст:

if readYN():
  print(-10)
else:
  print(30)

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

Посмотри на питоноподобную джулию — она вполне себе наступает находится на уровне Java/C# по производительности. То есть, динамичность языка — это не такая уж и непреодолимая проблема для оптимизации, как наличие GC или неудобные базовые структуры данных — да, последние капли производительности уже определяются языком, а не компилятором.

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

Потому что пользователей браузеров на пару порядков больше, чем пользователей программ на жаве. А какой такой в .NET? Вроде Electron и его вытеснил

Почему пользователей браузеров на пару порядков больше? Не так давно ведь жава аплеты стояли чуть ли не на каждой машине. В .NET валом реализаций гуев: WinForms, WPF, UWP. Та же Visual Studio на дотнете нынче.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

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

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

Вызов функции не меняет алгоритма, если эта фнукция не вызывается в другом месте. Грубо говоря, ты написал:

То есть, хочешь сказать, что RPython собирает исходники всех модулей подстановкой в одну программу и потом оптимизирует? А если там сишные модули? А если eval? Они же тоже могут изменять функции.

И если библиотечная функция на тысячу строк вызывается в сотне мест, она везде будет инлайниться?

Посмотри на питоноподобную джулию — она вполне себе наступает находится на уровне Java/C# по производительности.

В случае использования типов. Также как и лисп с declare type.

В этом смысле меня больше удивляет Node JS. Без указания типов теряет всего лишь десятки процентов производительности, а не десятки раз как php/python/perl/ruby/lua

Почему пользователей браузеров на пару порядков больше?

Браузером пользуется каждый пользователь Интернета. Программами на жаве около 1%.

Не так давно ведь жава аплеты стояли чуть ли не на каждой машине.

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

В .NET валом реализаций гуев: WinForms, WPF, UWP.

В жаве тоже: Swing, AWT, SWT. Только на фоне HTML5/CSS3 что .Net что Java проигрывают.

не такая уж и непреодолимая проблема для оптимизации, как наличие GC

На тесте binary trees самая быстрая программа на malloc/free (C) отрабатывает 8,5 секунд, а с использованием GC (Java) — 2,5 секунды.

monk ★★★★★
()
Ответ на: комментарий от byko3y

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

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

monk ★★★★★
()
Ответ на: комментарий от monk

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

Так почему же весь язык построен на основе того, что любая переменная одновременно является char *? Причем, это даже определено в стандарте. Типа алиасинг с char можно, а с машинным словом — уже нельзя.

Был целый тред срача по этому поводу. Из этого треда я могу дать такую выжимку: стандарт неоднозначен по поводу того, является ли небезопасное приведение типа UB или нет. Стандарт написан исходя из некого абстрактного выполнителя, но сам выполнитель стандартом не определен. Таким образом, мы не можем сказать, является ли операция &((int*)val)[1] (взятие указателя на первый элемент массива int, к которому были приведена val) доступом к первому элементу массива или нет. Если не является, то это не UB. Если является, то это UB. То есть, стандарт определяет UB второго порядка — неопределенная реализация неопределенности или определенности поведения. Отсюда разрабы компиляторов пошли кто в лес, кто по дрова: MSVC как обычно предпочло самый безопасный вариант, GCC как обычно предпочло самый безумный вариант UB, который невозможно обнаружить в отладочной сборке.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

В списке UB есть:

Addition or subtraction of a pointer into, or just beyond, an array object and an integer type produces a result that does not point into, or just beyond, the same array object1

&((int*)val)[1] === ((int*)val) + 1

Так что если val не является указателем на массив элементов типа int длиной не менее двух, будет UB.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

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

Вот. Каждая лишняя фича языка — это в том числе абуза, создающая как новые возможности, так и новые проблемы. И как ты думаешь, почему даже C# с горячей подменой функций предпочитает в рантайме полный инлайн и вывод типов? На нынешний момент это самая оптимальная реализация, и полноценного REPL она не подразумевает — а зачем? «Польза» от возможности глубокого переписывания кода «на ходу» в том числе убила производительность питона. Ведь именно глобальные изменяемые состояния, в том числе классов (манкипатч и просто изменение классов в рантайме), всякие __getattr__ и прочие хуки сделали задачу оптимизации настолько сложной, что даже у гугла не нашлось денег на реализацию проекта (Unladen Swallow).

То есть, хочешь сказать, что RPython собирает исходники всех модулей подстановкой в одну программу и потом оптимизирует? А если там сишные модули? А если eval? Они же тоже могут изменять функции

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

И если библиотечная функция на тысячу строк вызывается в сотне мест, она везде будет инлайниться?

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

В этом смысле меня больше удивляет Node JS. Без указания типов теряет всего лишь десятки процентов производительности, а не десятки раз как php/python/perl/ruby/lua

Сквозной вывод типов, как у PyPy. И условием этому является JS-only код (в крайнем случае знакомые оптимизатору библиотечные функции) и отсутствие высокодинамичных операций (изменения всего и вся на ходу). Когда-то там был LuaJIT, который не отставал от Java/C# — он и явился прототипом для JIT-оптимизаторов, вроде того же V8, то есть Node.js. Наличие тех же прототипов в JS очень усложнило задачу оптимизации:
https://mathiasbynens.be/notes/prototypes#classes
PyPy тоже по стопам LuaJIT создан, но PyPy требует сильно больше ресурсов на разработку, чем V8 — как я писал, даже у гугла столько ресурсов нет.

Браузером пользуется каждый пользователь Интернета. Программами на жаве около 1%
Возможность запуска - да. А чтобы на них что-то запускали - я не помню. Кроме некоторых клиентов интернет-банков

Во-о-от, платформа стоит на всех компьютерах, но ею никто не пользуется — почему? Я когда-то много голову ломал по этому поводу, и большую часть ответа я тебе уже выдал. Еще раз: это было не так совсем недавно, совсем недавно браузерами пользовались не так много, а жавой пользовались намного чаще. Была даже возможность запустить жаву без браузера, но через интернет — WebStart или как-то так оно называлось.

В жаве тоже: Swing, AWT, SWT. Только на фоне HTML5/CSS3 что .Net что Java проигрывают

На виндовых платформах гуй на базе дотнета очень активно используется. «Проигрывает» он только потому, что является платформозависимым. Если у кого-то стоит задача разработки win-only гуя, то тут выбор однозначен: Electron отправляется в мусорку и берется WPF. Другое дело, что win-only нынче почти никто не делает, Java очень плоха, потому остается только Electron.

На тесте binary trees самая быстрая программа на malloc/free (C) отрабатывает 8,5 секунд, а с использованием GC (Java) — 2,5 секунды

Остальные реализации просто используют кастомный манагер памяти, оптимизированный под дерево. Между прочим, даже стандартные манагеры памяти для malloc/free бывают разные, и у glibc далеко не самая эффективная реализация. Тот же Hoard умеет эффективно обрабатывать маленькие блоки одинаковых размеров. Короче говоря, binary-trees тестирует эффективность менеджера памяти в отношении деревьев.

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

byko3y ★★★★
()
Ответ на: комментарий от monk

Addition or subtraction of a pointer into, or just beyond, an array object and an integer type produces a result that does not point into, or just beyond, the same array object

Это выход за пределы массива. Раздел стандарта по этому поводу — 6.5, параграф 6 и 7, а не раздел 6.5.6, на который ты указываешь и который говорит про арифметику:

http://port70.net/~nsz/c/c99/n1256.html#6.5p6

Параграфы 6 и 7 — это два кратких абзаца про то, что тип у данных должен оставаться тот, с которым был произведен доступ. Что такое «доступ» — не определено стандартом. Здесь особенно я хотел бы подчеркнуть веселый пункт в параграфе 7:

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
...
* an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union)

На основе этого пункта плюс неопределенности понятия «доступ» можно додумывать и догадывать бесконечное число конкретных вариантов интерпретаций стандарта. Например, я кастанул double в struct {int, double} — это корректное преобразование согалсно стандарту, но даже без ломающих выполнение оптимизаций strict aliasing в GCC этот код может неправильно выполняться, если я внезапно попытаюсь прочитать double как поле int в struct {int, double}.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Поддержка eval похожа на онный у лиспа — если есть интерпретатор в рантайме. то можно, если нету, то eval недоступен.

У лиспа он есть всегда. И, в частности в eval можно изменить любую функцию.

Но, вполне возможно, будет мономорфизоваться.

То есть на каждую комбинацию типов по новому экземпляру?

но PyPy требует сильно больше ресурсов на разработку, чем V8 — как я писал, даже у гугла столько ресурсов нет.

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

Я когда-то много голову ломал по этому поводу, и большую часть ответа я тебе уже выдал. Еще раз: это было не так совсем недавно, совсем недавно браузерами пользовались не так много, а жавой пользовались намного чаще. Была даже возможность запустить жаву без браузера, но через интернет — WebStart или как-то так оно называлось.

Ответ прост. Написать интерфейс на жаве намного сложнее, чем нарисовать его на HTML. Поэтому делали только там, где за это платили много денег. С таким же успехом можно интересоваться, почему на Си так мало сайтов.

Если у кого-то стоит задача разработки win-only гуя, то тут выбор однозначен: Electron отправляется в мусорку и берется WPF.

https://www.electronjs.org/apps/photoscreensaver

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

Это понятно. Так-то и на GC можно сделать заранее массив и выделать элементы в нём. Но без дополнительных настроек на достаточно большом классе задач GC может работать быстрее чем malloc/free или new/delete.

monk ★★★★★
()
Ответ на: комментарий от byko3y

До доступа не доходит. У тебя UB будет при вычислении адреса.

http://port70.net/~nsz/c/c99/n1256.html#6.5.6p8

В Undefined behavior явно указано, что результат сложения/вычитания должен указывать на элемент массива или на элемент сразу после массива.

В своём утверждении я чуть неправ был. Массив должен быть размера не менее 1. То есть, если в val хранится адрес переменной типа int, то UB нет.

monk ★★★★★
()
Ответ на: комментарий от byko3y

Например, я кастанул double в struct {int, double} — это корректное преобразование согалсно стандарту

??? В структуру кастовать нельзя!

monk ★★★★★
()
Ответ на: комментарий от monk

Например, я кастанул double в struct {int, double} — это корректное преобразование согалсно стандарту

??? В структуру кастовать нельзя!

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

byko3y ★★★★
()
Ответ на: комментарий от byko3y

ты кастуешь между двумя совершенно разными типами, и по стандарту это корректное поведение

Нет. Оно даже не скомпилируется. https://gcc.godbolt.org/z/rnEE3Gxjb

По стандарту кастовать можно только совместимые типы.

monk ★★★★★
()
Ответ на: комментарий от monk

У лиспа он есть всегда. И, в частности в eval можно изменить любую функцию

Да ладна тебе — есть же компиляторы, которые выдают чистый натив.

Но, вполне возможно, будет мономорфизоваться.

То есть на каждую комбинацию типов по новому экземпляру?

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

но PyPy требует сильно больше ресурсов на разработку, чем V8 — как я писал, даже у гугла столько ресурсов нет.

Вот опять скорость программы зависит от языка при равных алгоритмах в компиляторе

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

Написать интерфейс на жаве намного сложнее, чем нарисовать его на HTML. Поэтому делали только там, где за это платили много денег. С таким же успехом можно интересоваться, почему на Си так мало сайтов

Не согласен. Hello world на обоих инструментах сделать несложно. По мере роста сложности выясняется, что у веб браузера удивительно ограниченный набор выразительных средств: ты можешь нарисовать статичную страничку с картинками, но любая минимально нестандартная логика требует кучи кода. Например, ты не можешь сделать развитую работу с текстом — по этой причине уже есть либы на чистом JS, которые умеют грузить и отрисовывать шрифты TrueType/OpenType/WOFF. Сделать кастомный разделитель блоков с изменением размера или даже банальную нестандартную логику полоскы прокрутки — снова приходим к голому JS и обработке низкоуровневых событий мыши (mousedown/mousemove/mouseup).

По факту, если ты посмотришь, что же легко пишется на Electron и пользуется популярностью, то увидишь какие-нибудь месенджеры, чатики, софтины для заметок, в том числе для коллективной работы с заметками, клиенты почты — то есть, всё то, что большую часть времени просто рисует HTML. Но даже Telegram написан на крестах-Qt, потому что огромное количество логики для ихнего протокола писать на JS тяжело и работать это будет медленно, а HTML может отобразить и Qt. Нет, IDE не легко пишется на электроне, там буквально каждую буковку приходится отдельно рисовать на JS и каждое движение мышки обрабатывать на JS, и даже после долгой и нудной работы не всё работает гладко, потому что JS не располагает к стабильности и поддерживаемости кода. Потому VS Code написан на TS и работает значительно стабильнее, чем Atom. Нет, фотошоп (Photopea) требует огромного количества библиотек и рисование на HTML5 Canvas «с нуля» на JS. Google Docs тоже всё форматирование документов сделали с нуля на JS.

По факту, Electron — это удобный инструмент только если тебе нужно отобразить по большей части статичную HTML страничку.

Если у кого-то стоит задача разработки win-only гуя, то тут выбор однозначен: Electron отправляется в мусорку и берется WPF.

https://www.electronjs.org/apps/photoscreensaver

Это что, killer app? Скринсейвер для тех, кто не научился в отключение экрана по бездействию?

Но без дополнительных настроек на достаточно большом классе задач GC может работать быстрее чем malloc/free или new/delete

Спорное заявление, если принять во внимание современные менеджеры памяти с детерминированным O(1) выделения и высвобождения, с минимальной фрагментацией и хорошей масштабируемостью многопотока. В число которых, как я уже писал, не входит стандартный менеджер glibc — который оптимизирован на минимизацию потребления памяти, а не на производительность.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от monk

В своём утверждении я чуть неправ был. Массив должен быть размера не менее 1. То есть, если в val хранится адрес переменной типа int, то UB нет

А если там хранится struct {char, double, int}, то каст корректен. И не важно, что там выравнивания пляшут — вот же, int есть в структуре.

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Ты первый раз на сихе пишешь?

Ты читай, что сам пишешь: «я кастанул double в struct {int, double} …»

В примере кастуется указатель на double в указатель на struct {int, double}.

monk ★★★★★
()
Ответ на: комментарий от byko3y

А если там хранится struct {char, double, int}, то каст корректен. И не важно, что там выравнивания пляшут — вот же, int есть в структуре.

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

monk ★★★★★
()
Ответ на: комментарий от monk

Можно цитату из стандарта, что можно разыменовывать получившийся указатель?

Можно:

http://port70.net/~nsz/c/c99/n1256.html#6.5p6


The effective type of an object for an access to its stored value is the declared type of the object, if any.75) If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:76)

    a type compatible with the effective type of the object,
    a qualified version of a type compatible with the effective type of the object,
    a type that is the signed or unsigned type corresponding to the effective type of the object,
    a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
    an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
    a character type. 
byko3y ★★★★
()
Ответ на: комментарий от monk

В C++ явно запрещено (https://timsong-cpp.github.io/cppwp/basic.compound#4)

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

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Да ладна тебе — есть же компиляторы, которые выдают чистый натив.

Так eval в чистом нативе доступен. Фактически, если его нет, то его можно самому написать и compile для этого не обязателен.

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

А у всех остальных проблемы с оформлением. Вот сделай на Java анимацию меню и кнопки с скруглёнными углами и фоном.

но любая минимально нестандартная логика требует кучи кода

Она в любой библиотеке требует кучи кода. Хочешь сказать, что нестандартная логика полосы прокрутки в жаве проще делается?

Потому VS Code написан на TS и работает значительно стабильнее, чем Atom.

Но ведь VS Code всё равно на электроне.

По факту, Electron — это удобный инструмент только если тебе нужно отобразить по большей части статичную HTML страничку.

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

monk ★★★★★
()
Ответ на: комментарий от byko3y

an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union)

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

monk ★★★★★
()
Ответ на: комментарий от monk

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

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

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

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Аргумент «это же херотень какая-то, в этом нет смысла, как это реализовывать?» не принимается, потому что «конкретизируйте ваши претензии, пожалуйста».

То есть пример конвертации double* в (struct {int; char; double})* никто не привёл? Очень странно.

Я всегда думал, что такие ловушки только в законодательстве попадаются (иначе юристам и бухгалтерам будут намного меньше платить). Но даже в законодательстве на любую неоднозначность есть статья-разъяснение какого-нибудь уважаемого юриста «законодатель имел в виду …, поэтому статью закона … надо трактовать как …».

P.S. Нашёл трактовку: https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

Так eval в чистом нативе доступен. Фактически, если его нет, то его можно самому написать и compile для этого не обязателен

Можно реализовать != всегда есть в наличии.

А у всех остальных проблемы с оформлением. Вот сделай на Java анимацию меню и кнопки с скруглёнными углами и фоном

Джава — это бесмопощный мусор, я уже написал. На дотнете или Qt скругленные углы и анимации прекрасно делаются.

Хочешь сказать, что нестандартная логика полосы прокрутки в жаве проще делается?

Да, я хочу сказать, что на любом GUI тулките нестандартная логика полосы прокрутки делается намного легче, поскольку намного проще встроиться в отрисовку и обработку событий. Даже в WPF/UWP, которые содержат отдельный поток рендера, в который, тем не менее, можно встроиться, в отличие от браузера, где вся отрисовка и обработка событий — это черный ящик со строго ограниченным набором торчащих наружу рычажков. Собственно, там по всем фронтам примерно тот же самый черный ящик с несколькими рычажками — именно в этом и вся проблема.

Потому VS Code написан на TS и работает значительно стабильнее, чем Atom.

Но ведь VS Code всё равно на электроне

Да. поскольку MS нужна была кроссплатформа. Win-only у них на дотнете, ни на какой электрон его портировать они даже не думают.

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

Ты же понимаешь, что в любом более-менее сложном проекте «из одного лишь GUI» неизбежно придется рисовать всё на Canvas голым JS? И тогда чем браузер облегчает задачу? То же самое на Qt можно сделать намного эффективнее и поддерживаться оно будет проще — именно к этому выводу приходят люди. которые по глупости начали писать на браузере свой сложный кроссплатформенный гуй «ну потому что все так делают», например:

http://deplinenoise.files.wordpress.com/2017/03/webtoolspostmortem.pdf

byko3y ★★★★
()
Ответ на: комментарий от monk

Я всегда думал, что такие ловушки только в законодательстве попадаются (иначе юристам и бухгалтерам будут намного меньше платить). Но даже в законодательстве на любую неоднозначность есть статья-разъяснение какого-нибудь уважаемого юриста «законодатель имел в виду …, поэтому статью закона … надо трактовать как …»

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

Нашёл трактовку: https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule

Ну да, это подборка из очевидных вещей + фактического положения + немного собственных додумок. Моя основная претензия к оптимизациям strict aliasing — они ломают работающую в старых компиляторах, они не обнаруживаются в отладке, нет никаких предупреждений от компилятора о возможных проблемах наложения данных. Мой основной аргумент — если оптимизация ломает программу, то оптимизация некорректна. Стандарт сильно неоднозначен для того, чтобы хотя бы сказать «мы ломаем обратную совместимость, теперь старый код не будет работать на новых компиляторах» — потому что комитет ни за что бы этого не признал. Но фактически GCC сделал именно это — сломал старый код на новых версиях компилятора. Ты и мне хочешь скзаать, что это «корректная оптимизация»?

byko3y ★★★★
()
Ответ на: комментарий от byko3y

Ты же понимаешь, что в любом более-менее сложном проекте «из одного лишь GUI» неизбежно придется рисовать всё на Canvas голым JS? И тогда чем браузер облегчает задачу?

Тогда уже ничем. Но подавляющая доля интерфейсов отлично ложится на HTML/CSS. Какая доля сайтов написана на Canvas+JS?

«ну потому что все так делают»

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

monk ★★★★★
()
Ответ на: комментарий от monk

Вы такую пургу пишете. Вам не надоело?

Мало того, обезьяна была уличена в полной некомпетентности. Ты, монах, тоже слишком много пишешь. Смотри…

Я бы этот флуд прекращал. Но я не вы.

B0B
() автор топика
Последнее исправление: B0B (всего исправлений: 1)
Ответ на: комментарий от B0B

Ладно, согласен. Уже ушли в оффтопик второго порядка. Если бы хоть elisp обсуждали…

monk ★★★★★
()
Ответ на: комментарий от monk

Тогда уже ничем. Но подавляющая доля интерфейсов отлично ложится на HTML/CSS. Какая доля сайтов написана на Canvas+JS?

Давай лучше поставим вопрос так; какая доля сайтов отображает что-то большее, чем статичный текст с картинками и ссылками? 1%? 2%?

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

На Qt/Larazur прототипы тоже прекрасно набрасываются, и очень быстро. Другое дело, что в среднем по палате говнокод на JS имеет сильно больше шансов заработать, чем на паскале или C++, плюс у Qt слабая поддержка мака. То есть, всё дело тупо во входном барьере. Когда мне нужно было набросать быстро софтину для себя, то я брал Delphi — просто потому, что я мог много чего очень быстро сделать именно на нем.

Я тебе могу сказать 100% объективную причину, почему конторы, вроде того же Microsoft, предпочтут Electron — если у них есть веб-сайты, всякие облачные сервисы, которые могут работать в frontend-only режиме, при этом у них есть квалифицированные JS программисты (это ОЧЕНЬ важно, как ты мог узнать из упомянутой ссылки). Мой последний проект с рабства именно потому выбрал, даже не Electron, а браузерное приложение с опциональным бэкэнд кодом на целевом устройстве.

Всё, если ты делаешь не переиспользуешь код в своих веб сайтах/сервисах, если у тебя не команда из JS макак, то оправдания использованию электрона нет вообще никакого. «Я — бездарная макака, которая когда-то тыкала JS и больше ничего не хочет изучать» — это, на самом деле, не оправдание. Писать кастомную логику на JS не проще, чем на C++. Отображать HTML можно и в Qt и в Lazarus — ради бога, пиши на HTML, кто ж запрещает. Сейчас куча игр поставляются с внутриигровыми браузерами для просмотра профилей, просмотра магазина с донатом, и прочего: Steam, Origin. Origin на куте написан, к слову, и при этом через кутю же отображает HTML контент. Steam использует свой собственный VGUI, в который встроен хром для отображения HTML. Зачем здесь электрон — скажи мне?

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от byko3y

А ты не можешь остановиться? Так странно читать некомпетентного.

И ты не можешь ничего предоставить, кроме домыслов.

B0B
() автор топика
Последнее исправление: B0B (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.