LINUX.ORG.RU

Муки выбора языка программирования

 , , , ,


2

4

Пытаюсь выбрать язык программирования для личного проекта.

Хочется, чтобы у языка были:

  • библиотека для загрузки/выгрузки изображений с поддержкой широкого круга форматов
  • биндинги для sdl2
  • работа с битовыми массивами размером больше чем 64 элемента (с поиском единиц)
  • перегрузка оператора индекса в том числе при присвоении
  • ассоциативные массивы с лаконичным доступом к элементам
  • документацией с поддержкой мобильного просмотра в 2023 году-то
  • поддержкой компиляции для мобильных архитектур
  • нормальный полиморфизм, а не как в Rust
  • востребованность на рынке труда

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

C++ и Rust имеют очень странные конструкторы для битовых массивов. Может это проблема документации, но я с ходу не нашёл как мне создать битовый массив из готового байтового массива, чтобы каждый байт превратился в 8 бит.

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

Что выбрать?

★★★★★

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

Таков стандарт.

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

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

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

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

alysnix ★★★
()

Переписал одну утилиту на Rust.

Понравился полный контроль над преобразованием типов в вычислениях. Давно такое хотел, хотя поначалу мысли при виде этого: «ассемблер какой-то!». Вероятно из-за этого быстродействие моей программы в релизной сборке увеличилось почти вдвое, что не может не радовать.

Немного не понравилось: перевёрнутый sqrt (типа 2.0_f64.sqrt()), хотя никто не мешает создать свой fn вместо trait’а.

Не понравилось: оч. долго искал как сделать простейший cast из массива байтов в массив u64 и обратно. По пути даже нашёл компилирующееся, но почему-то обрезающее массив решение. Слава Богу нашёл и правильное и теперь не потеряю.

Очень не понравилось: debug сборки аж в 35 раз медленнее release’ных. Что не просто жесть, а жесть в кубе.. Наверное с этим можно как-то бороться, но я пока не нашел как. В D просадки не дебаге всего лишь раза в 3.

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

По поводу вечного цикла:

$ cat 1.cpp
#include <iostream>

[[ noreturn ]] void fn() {
#ifdef WITH_LOOP
        while (true);
#endif
}

int main() {
        fn();
}

void unreachable() {
        std::cout << "hello world" << std::endl;
}
$ clang++ -std=c++20 1.cpp -O2 -Wall
1.cpp:7:1: warning: function declared 'noreturn' should not return [-Winvalid-noreturn]
}
^
1 warning generated.
$ clang++ -std=c++20 1.cpp -O2 -Wall -DWITH_LOOP
$ ./a.out
hello world

В общем не надо рассказывать, что это норм, ну ЮБ (а стандарт то кто-нибудь видел на этот счет? может там и нет никакого ЮБ), чего ты хотел. Шланг противоречит сам себе - с noreturn атрибутом данный цикл его устраивает в качестве вечного и возврат из него не ожидается. Шланг сломан, на выходе такой бред:

fn():                                 # @fn()
main:                                   # @main
unreachable():                       # @unreachable()
pushq   %rbx
... #печать hello world
kvpfs ★★
()
Последнее исправление: kvpfs (всего исправлений: 1)
Ответ на: комментарий от hobbit

А просто не допускать UB в своём коде не вариант? Личная аккуратность, понимание, что ты пишешь, ну и статические анализаторы в помощь, это не зазорно.

Почитай мой тред про C, free() и UB, там очень много обсуждения на этот счёт.

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

  1. Статический анализатор не ловит всё. Даже динамические штуки типа UBSan не ловят всё, и остаётся только страдать.
  2. Штуки типа ПиВаСа довольно примитивны, на самом деле, и для полного статического анализа требуется натягивать на код ещё один язык программирования для описания инвариантов. И тут мы приходим к тому, что проще выкинуть C на помойку и взять язык с меньшим количеством проблем, чем писать на двух языках параллельно.
hateyoufeel ★★★★★
()
Ответ на: комментарий от kvpfs

а стандарт то кто-нибудь видел на этот счет?

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

На, почитай вот это: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1528.htm

hateyoufeel ★★★★★
()

Использую Visual Studio 2013 (1) у нас на предприятии древние системные блоки и ОС; 2) C/C++ «не высокоумный» )

SDL2-2.26.4.zip

За много лет работы первый раз получил ошибку компилятора
Ошибка 32 error C1064: ограничение компилятора: лексема переполнила внутренний буфер SDL\test\testautomation_math.c 1090

См. SDL\test\testautomation_math.c

 { 539.483, 1970107755334319939701129934673541628417235942656909222826926175622435588279443011110464355295725187195188154768877850257012251677751742837992843520967922303961718983154427294786640886286983037548604937796221048661733679844353544028160.0 },

gcc такую строку сумеет скомпилировать без ошибки?

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)

Неожиданно возник тот же вопрос.
Начальник отдела сказал - «За 1С забудь».
У меня многолетний опыт разработки в 1С 7.7 и 1С 8.3.

Спрашиваю - «Какой ЯП теперь использовать?».
«Любой, какой считаете нужным. Главное, чтобы ничего платного не было.»

С понедельника в отпуске.
Начну разработку GUI на OpenGL (разработку ЯП продолжу после разработки GUI).

QT для предприятий платный, ...

Какой ЯП буду использовать?
Для начала, попробую использовать свой GUI на Python и GO.

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

Я вот что думаю:

The implementation may assume that any thread will eventually do one of the following:
(1.1)
terminate,
(1.2)
make a call to a library I/O function,
(1.3)
perform an access through a volatile glvalue, or
(1.4)
perform a synchronization operation or an atomic operation.
[Note 1: This is intended to allow compiler transformations such as removal of empty loops, even when termination cannot be proven. — end note]

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

А вот с какой радости шланг решает исполнить недостижимую функцию - мне непонятно абсолютно.

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

я пишу пиши гуи на wxWidgets/C++.

API для создания динамических окон на основе каких-либо метаданных имеются?
Конечно все стандартные controls в нем имеются?
Удобный GUI?

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

API для создания динамических окон на основе каких-либо метаданных имеется? Конечно все стандартные controls в нем имеются? Удобный GUI?

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

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

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

Свой GUI мне нужен так как он будет использовать уже разработанный API для работы с метаданными, а в сторонних GUI придется тратить время на то, чтобы этот API был использован (а он весьма удобный).

Да и в целом «потянуло на графику».

Все же, можно ли в wxWidgets динамически создавать controls?
Скорее всего - можно.

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

Эффектов, (волатайл, ио, атомик, …) и, видимо, изменяемые данные в цикле не являются аргументом функций (в абстрактном смысле), которые делают эти действия, то можно вырезать.

это пустой цикл у них?

да, надо писать в volatile

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

Спасибо!

Динамические окна нужны для того, чтобы интерфейс был «не прибит гвоздями» к коду
на C++ (поиграюсь с Python и GO, а скорее всего буду использовать C++).

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

короче там тотальная динамика…

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

реакция окна на ивенты - вызовы Bind в конструкторе окна(привязка методов - обработчиков).

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

так то вообще все графика, отрисовка и ивенты ввода крутятся в главном треде.

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

А вот с какой радости шланг решает исполнить недостижимую функцию - мне непонятно абсолютно.

Он её не вызывает, он в неё «проваливается». Думаю там происходит многоходовочка примерно следующего плана: сначала выбрасывается эпилог main() потому как цикл бесконечный, а потом сам цикл потому как «таких не бывает».

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

Спасибо!!!

Фишка своего GUI будет в том, что малого того, что интерфейс «не будет прибит гвоздями к коду», а в том,
чтобы программист вообще не знал о каких-то там классах, ...

Так как вы рекомендуете wxWidgets, то попробую его в работе.

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

Очень не понравилось: debug сборки аж в 35 раз медленнее release’ных. Что не просто жесть, а жесть в кубе.. Наверное с этим можно как-то бороться, но я пока не нашел как. В D просадки не дебаге всего лишь раза в 3.

Ура! Я нашёл, вернее догадался, в чём причина. Это проверки на переполнение. Отключил и сразу просадка упала с 35 до 4 раз. При этом это ещё процентов на 15% быстрее Ди отладочного кода. Ну это очень круто что возможность такой проверки есть. Не раз я об это спотыкался.

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

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

Короче в попу шланг, какую-то лютую дичь творит, оправдать такое ЮБ’ом - тоже не впечатляет, лучше бы какой-нибудь аборт() сделал, если уж нормально не умеет. Если бы это была прошивка МК, которая сломала бы что-нибудь или привела к травмам после запуска чего-нибудь из-за провала в другую функцию? Осадочек останется надолго.

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

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

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

А это радует (да и SDL радует. Минута и все проекты собраны)!

У меня опыт разработки под Linux имеется, но в конторе это никому не нужно (все виндусятники).
В целом (исходя из своего опыта) под Visual Studio без проблем можно создавать кроссплатформенные проекты (так и делаю).

Forum0888
()
Ответ на: комментарий от alysnix

Ну я пока не совсем прям Rustaceans, слишком мало опыта. Но определенные плюсы у Rust явно имеются.

Из неотмеченного понравилось что cargo умеет находить проект из поддиректорий.

А не понравилось что локальное-thread хранилище создаётся через одно место. В D все глобальные переменные по умолчанию local thread. Могли бы и взять эту идею.

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

Короче в попу шланг, какую-то лютую дичь творит, оправдать такое ЮБ’ом - тоже не впечатляет

Всё сложно, на самом деле. Я когда-то давно приводил безобидный пример с for-loop’чиком, образцово показательным, кмк. Как Вы думаете - что напечатает

for (int i = 0; i < 4; ++i) {
   cout << i * 1000000000 << endl;
}

ПыСы. Собирать gcc с «-O3».

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

В D все глобальные переменные по умолчанию local thread.

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

Метаданные в добавок к всему позволяют вынести все enum в базу метаданных (много вкусных «плюшек»).
Любопытно то, что многие «рассуждают» о метаданных, а толком-то и не понимают «куда кобылу впрягать».

Forum0888
()
Ответ на: комментарий от kvpfs

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

Welcome to the real world ;) Меня там в соседнем треде некоторые «закидали какашками» за мысль о том что включение exceptions может много чего поломать… Ну да ладно :)

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

У меня так. Глобальная переменная в любом проекте лишь одна.

Одна, ни одна, но в Раст её ещё объявить суметь надо. Он заставляет все обращения к глобальным переменным оборачивать в unsafe. Я поплясал немного с бубном да и обернул свои переменные в структуру которую надо передавать к нужным методам.

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

Лениво парсить асм, почему так выходит?

PS: т.е. в чем логика компилятора после переполнения и чего он пытается добиться?

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

почему так выходит?

Попробовали? ;) Ножки растут из посыла «signed int overflow is an UB». Сначала заменяют i * 1000000000 на i += 1000000000, а потом говорят - signed ints у нас же не достигают 2^31+… И выбрасывают проверку. Замена на unsigned помогает. Ровно как и «-fno-strict-overflow». Я до сих пор воюю с нашим tech-committee чтобы включить (отключить?) это дело, но пока что в меньшинстве (народ считает что benefits overweights the risks).

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

Ясно, спс за пример. Я тут ещё нашел один пример с этой оптимизацией циклов без сайд эффектов:

#include <iostream>
 
bool fermat()
{
    const int max_value = 1000;
 
    // Endless loop with no side effects is UB
    for (int a = 1, b = 1, c = 1; true; )
    {
        if (((a * a * a) == ((b * b * b) + (c * c * c))))
            return true; // disproved :)
        a++;
        if (a > max_value)
        {
            a = 1;
            b++;
        }
        if (b > max_value)
        {
            b = 1;
            c++;
        }
        if (c > max_value)
            c = 1;
    }
 
    return false; // not disproved
}
 
int main()
{
    std::cout << "Fermat's Last Theorem ";
    fermat()
        ? std::cout << "has been disproved!\n"
        : std::cout << "has not been disproved.\n";
}

В общем на свежих компилях будет выводиться «has been disproved!», и в ГЦЦ. Честно говоря, я немного в шоке, они там совсем, чего они творят? Они хотят все сломать и сделать из крестов минное поле? Писец, куда их понесло, наркоманы …

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

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

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

Всё это делают санитары.

Предлагаете сделать санитара неотъемлемой частью программ на Си++? Запустите тест производительности с включенным санитаорм.

Вот как с питоном 2 быть? Получается, что он был сплошным юб раз его сломали?

Что значит «сломали»? В документации к питону 2 где-то написано, что если написан код «…», то может произойти что угодно?

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

Я же привёл пример.

Есть какой-нибудь цикл:

while(x) x = f(x);

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

Не только.

А зачем ещё? Для всего остального лучше языки без UB: от питона и хаскела до лиспа и джавы.

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

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

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

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

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

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

monk ★★★★★
()