LINUX.ORG.RU

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

 , , , ,


2

4

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

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

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

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

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

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

Что выбрать?

★★★★★

Любопытный набор ЯП на выбор. На Haskell с наскоку не написать ничего толком, если не знаешь языка, будут бесконечные муки сведения типов и поисков способа выкарабкаться из затруднительных ситуаций. Проблема «странных конструкторов в C++ и Rust» решается за пять минут созданием обёртки и явно не должна быть критерием выбора языка, можно попросить ChatGPT написать такую обёртку, если есть затруднения. Я бы всё же посоветовал Rust в данном случае, даже если полиморфизм в нём кажется ненормальным.

unC0Rr ★★★★★
()

Не надо стесняться. Хочешь запилить свой язычок — так и запиливай, зачем этот поиск оправданий. Правда, с популярностью могут быть проблемы.

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

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

Это я как раз смотрел. Вот скажите, они нормальные вообще? N у них size_t, а в примерах не больше 8..

Единственный пример с конструктором где N=70 - инициализировать можно только 64 бита, либо делать строку с символами из ноликов и единичек. А почему по нормальному нельзя инициализировать?

unDEFER ★★★★★
() автор топика

А что мешает на плюсах свелосипедить свой битовый массив, с продажными тяночками и блэкджеком?

class BoolArray{
  std::vector<uint64_t> data;
  int sz = 0;
public:
  void resize(int sz_){ sz = sz_; data.resize(sz/64+bool(sz%64), 0); } 
  int size() const { return sz; }
  bool get(int i) const { return data[i>>6]&(uint64_t(1)<<(i&0x3F)); }
  void on(int i){ data[i>>6] |= uint64_t(1)<<(i&0x3F); }
  void off(int i){ data[i>>6] &= ~(uint64_t(1)<<(i&0x3F)); } 
  bool any() const { for(uint64_t x: data){ if(x) return true; } return false; }
  void clean(){ for(uint64_t &x: data) x = 0; }
  void out(std::ostream &S) const { for(int i=0; i<sz; i++){ S<<(get(i)? 'y': 'n'); } S<<'='<<(any()? 'Y': 'N')<<' ';  }
};
AntonI ★★★★★
()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от unDEFER

Ты разве не этого хочешь?

#include <vector>
#include <iostream>
#include <cstdint>
#include <boost/dynamic_bitset.hpp>

int main()
{
	std::vector<uint8_t> v{0,0,0,0,0,0,0,0,0,0,8,0};
	boost::dynamic_bitset<uint8_t> b(v.begin(), v.end());
	std::cout << "vector size is " << v.size() << std::endl;
	std::cout << "bitset size is " << b.size() << std::endl;
	std::cout << "first non-zero bit number is " << b.find_first() << std::endl;
	return 0;
}

vector size is 12                                                                                                                                                                                                                                             
bitset size is 96                                                                                                                                                                                                                                             
first non-zero bit number is 83

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

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

И задача выбора сводится лишь к тому что проще реализовать битовые массивы или работу с изображениями. С массивами на самом деле проще, но с изображениями гораздо интереснее :-)

unDEFER ★★★★★
() автор топика

Вариант 1: С++/Qt, дописав свой велосипед для битовых массивов :)

Вариант 2: Сделай/перенеси на D библиотеку для изображений, поможешь не только себе.

// Да, предлагать другому человеку проделать объёмную работу не совсем честно, но я просто говорю, что я бы сделал именно так — не стал бы искать языки-серебряные пули (их нет), а взял бы ЯП, который я прилично знаю, и применил бы напильник для неочевидных случаев. Подход проверенный, надёжный, рабочий, хоть и не сулит быстроманящего результата.

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

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

Не знаю.

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

В общем да, пожалуй я решил.

Буду пилить свою библиотеку изображений для D. У меня ведь у самого формат изображений с гексагональными пикселями. И ознакомление с другими форматами будет весьма полезным. Может я чего и в свой формат захочу привнести?

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

Мне кажется это можно на любом ЯП сделать, я бы не стал смотреть на что то из коробки.

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

AntonI ★★★★★
()

Для «битовых» изображений есть 2 библиотеки на божественном С:

  1. leptonica (http://www.leptonica.org/)
  2. rapp (https://www.nongnu.org/rapp/doc/rapp/)
  3. QImage вроде умеет быть 1-бит-на-пиксель (Format_Mono, Format_MonoLSB).

В первом, и по-моему во втором варианте битики хранятся 32-битными кусками, а не 64, как тебе тут напоказывали, это потому что либки писались давно, но 32битными кусками хранить имеет преимущество, если захочешь перенести на GPU - там не бывает нативного uint64 за малый прайс до сих пор.

Первым вариантом вдохновлялся автор scantailor-a когда 15 лет назад писал его, просто портанул куски лептоники так как ему казалось правильным в С++.

Битовых массивов тут тебе показали, но вроде загугливается еще миллион вариантов с всякими SSE и avx.

Врядли битовые картиночки попадут в язычок, если это не Wolfram Language.

nikitos ★★★
()

C++ и Rust имеют очень странные конструкторы для битовых массивов.

ты программист или кто? в плюсах темплейт любого тебе нужного битового массива пишется за 10 минут с нуля. или ты собрался программировать только на стандарной библиотеке? тогда тебе в другую сторону.

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

выбирай плюсы и не морочь себе голову.

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

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

у тебя нет выбора. только плюсы, только хардкор.

alysnix ★★★
()
Ответ на: комментарий от unDEFER
#include <cstdint>
#include <iostream>

struct simple_bitset {
    union {
        struct {
            uint8_t b1 : 1;
            uint8_t b2 : 1;
            uint8_t b3 : 1;
            uint8_t b4 : 1;
            uint8_t b5 : 1;
            uint8_t b6 : 1;
            uint8_t b7 : 1;
            uint8_t b8 : 1;    
        } bitset;

        uint8_t value;
    };
};


int main() {
    simple_bitset x;
    x.value = 0x0F;

    std::cout << (int)x.bitset.b1 << (int)x.bitset.b2 
    << (int)x.bitset.b3 << (int)x.bitset.b4 
    << (int)x.bitset.b5 << (int)x.bitset.b6 
    << (int)x.bitset.b7 << (int)x.bitset.b8 << "\n";

    return 0;
}
sparks ★★★★
()
Ответ на: комментарий от unDEFER

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

Можно предварительно посчитать сумму Минковского двух массивов и потом задача для определения коллизий сведется к проверке одной точки в массиве-сумме.

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

Так один же из массивов всё время двигается :-)

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

Нашел иллюстрацию - https://doc.cgal.org/latest/Minkowski_sum_2/ms_tight.png

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

No ★★
()
Последнее исправление: No (всего исправлений: 1)

При таком выборе у Haskell есть отсутствие неопределённого поведения (UB) и таки нормальный полиморфизм. Но ниже скорость получившегося кода (если сравнивать с Си++).

Если скорость настолько важна, что можно мириться с UB, бери Си++. Иначе Haskell.

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

мириться с UB

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

При том, что код с UB может работать, а потом переставать это делать очень внезапно при минорном обновлении компилятора. И ты об этом узнаешь по внезапным кордампам.

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

Программные ошибки есть всегда. Но в Haskell или лиспе она вылезет только на тех данных, в которые попала ошибка. Более того, ошибочный код легко изолировать. А в Си++ легко возникает ситуация типа:

  { 
    int x = 5;
    f();
    cout << x; // выводит 42
  }
monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 2)