И да в portfile по ссылке никакой "чудовищной сложности" нету. Думаю в конфигурации правильных асм листингов под зоопарк платформ и работы с сетью (да в опенссл есть сеть) сложности больше
Так vcpkg это аналог pkgbuild из арча, deb скриптов и подобного. Т.е. тут обертка вокруг ./configure && make install а не переписываниею autotools, perl и прочего на симейк. Обертку сделать в разы проще чем портировать миллион скриптов на симейк. И вообще если там требуется действительно что то сложное заскриптовать, то симейк как язык по сравнению с перлом это убожество.
Вредительство это сам виндовс и его поддержка. Чтобы его поддерживать требуется портить код. Он постоянно падает в BSOD, не поддерживает правильное поведение и сохраняет баги в поведении, отказываясь его фиксить Если компания разрешает только виндовс - это её проблемы. Linux опенсорс в отличие от закрытого виндовс, поддерживает С++ лучше, программы работают обычно на 30%+ быстрее
ой, кстати, да, как реализовать рейндж всех нечётных интов одним iota, без фильтра?
можно cделать трансформ из n в 2*n + 1
а то вы так долго напирали, что у меня немощно и плохо всё
так вы повоторите хоть то что в iota есть. Если бесконечный ренж неподдерживается то ладно, я вроде такое не просил.
Только в очередной раз не сделали их размер определяется наличием имени,
там проблема наверное в том что старые итераторы в уже существующем коде хотели продолжать поддерживать, в новом коде iterator_category определяется.
Хоспаде, ну наконец-то!
Я ничего сложного не просил. Просто есть вектор vec, r1 = vec | transform(f) известен размер и есть доступ к элементам, r2 = vec | filter(g) тут размера нету есть только forward итератор. Есть например
auto foo(range auto r) { return r | transform(h); }
Сохраняются свойства и при передаче r1 и r2, удобно.
На уровне реализации во всех этих рефах хранится указатель, поэтому атомарность бесплатная.
Если передаётся рефы всё равно вопрос как их менять. Либо копировать, либо менять инплейс.
В раст я не понял как этим пользоваться. Из статьи и кода бенчмарка непонятно. Как будет индексироваться Vector3<f32x4>, индексами от 0 до 3 или от 0 до 12?
Это ForeignPtr. GC знает, что и как финализировать.
Ок, получается имплементировать эту часть на языке не надо т.к. она встроена в язык. В джава или C# я такой штуки не знаю (но может есть).
Так за iota и рандомного доступа нет, поди пойми, что вам надо.
Для чисел есть
Зачем сюда Range? У нас тут отдельная ветвь дискуссии, где мы обсуждаем голые функции.
Вы почему-то продолжаете делать вид что не понимаете разницу между контейнерами, функциями и ренжами.
А если у меня там будет pair<width, height> size()?
Никто не запрещает в С++ делать именованные маркеры. А так да, подходы разные, и это уже другая тема. В расте с трейтами аналогичную проблему всё же как-то решают.
Ненене, вы саму zip_transform напишите. На плюсах же с шаблонами всё просто, так что как это будет выглядеть?
zip_transform принимает сколько угодно ренжей, жду для начала вариадиков в хаскеле.
а оно не sized_range
Это недоработка реализации. Бесконечный размер на уровне типов приравнен к неизвестному размеру. Ваш пример с zip кстати как раз неизвестный размер тоже не покрыл.
Если игнорировать нюансы со ссылками то можно повторить ваш искуственный пример как-то так
template<typename F>
struct Unbounded {
F f;
};
template<typename F>
struct Bounded {
F f;
size_t len;
};
template<typename T>
concept HasLen = requires(T x) {
x.len;
};
auto zipWith(auto f, HasLen auto a, HasLen auto b) {
return Bounded([=](size_t i) { return f(a.f(i), b.f(i)); }, std::min(a.len, b.len));
}
auto zipWith(auto f, HasLen auto a, auto b) {
return Bounded([=](size_t i) { return f(a.f(i), b.f(i)); }, a.len);
}
auto zipWith(auto f, auto a, HasLen auto b) {
return Bounded([=](size_t i) { return f(a.f(i), b.f(i)); }, b.len);
}
auto zipWith(auto f, auto a, auto b) {
return Unbounded([=](size_t i) { return f(a.f(i), b.f(i)); });
}
Так делать не надо потому что это не реализует нужных концептов для итераторов/ренжей.
Хотя я пока писал понял что смысла в таком Unbounded нету совсем. У нас либо рандом аксесс и тогда мы знаем границы, либо не знаем границ и достаём по-одному. Получается бестолковый пример обсуждаем :/
Мутируете, делаете freeze, кладёте в TVar или что-то подобное, в другой транзакции достаёте, делаете thaw, мутируете.
сложность thaw O(n), т.е. оно делает копию. Вообще продолажая тему про IORef я не понял как там атомарно поменять что-то размером больше инта.
В сложных примерах я не замечу, что два раза читаю из IORef
Если есть гарантия что владение переменной однопоточное, то в чём проблема?
Если можете как человек гарантировать, что это безопасно,
Посыл нашего обсуждения что гарантировать должен компилятор, а не человек.
запилят поддержку линейных типов.
Поэтому раст тут получается впереди, о чём изначально и говорилось по ссылке. Борроу чекер в паре с send/sync даёт больше выразлительности.
А как такое работает? ptr это что? Обычно массив это внтуренний примитив и ссылку на место где лежит элемент взять так просто нельзя. Или язык должен предоставлять специальный примитив для этого, который поидее и будет содержать ссылку на сам массив. Иначе как гц узнает связь между (ptr+i) и аллокацией c началом ptr?
Получается Vector это вью для последовательной аллокации? Тогда его всё равно нельзя использовать как параметр для ренжа с O(1) доступом, потому что за iota нету никакой аллокации. Зачем вы мне его предлагали?
Зачем для этого тайпкласс? Композицию функций уже отменили? transform :: (Int -> a) -> (a -> b) -> (Int -> b)
Не вижу как сюда передать объект типа Range, или какой вы там создали?
toList
В тот момент когда надо писать такие явные преобразования код перестаёт быть женерик.
А как вы там в типах отличаете ограниченные и неограниченные рейнджи?
По наличию перегрузки size()
auto x = zip_transform(std::plus{}, iota(3, 10), iota(3, 20));
static_assert(sized_range<decltype(x)>);
std::println("{}", x.size());
auto y = zip_transform(std::plus{}, iota(100), iota(200));
static_assert(!sized_range<decltype(y)>);
Потому что контейнер тегирован s, которая должна иметь возможность быть произвольной во всём скоупе runST (об этом говорит тип runST). Как только вы его куда-то кладёте, оно больше не может быть произвольным.
Т.е. у меня контейнер создаётся и умирает вместе с runST? Или создаётся мутабельный вью?
Я хочу взять например вектор, мутировать его в одном потоке, потом мувнуть его в другой поток и продолжить мутировать там.
А подёргать STM внутри runST тоже нельзя, потому что STM дёргается через atomically , которая живёт в IO, и которую нельзя поэтому дёргать внутри runST.
А как мне писать код который одновременно и читает что то из тред-сейф объекта расшареного и на основе этого модифицирует тред-локальный стейт?
Речь же про Си, там даже если выкинуть мсвц, найдутся другте компиляторы. Не знаю что опенссл поддерживает если честно
Вижу вы так и не поняли что вам хотел сказать @Kelbon
Фиговые дефолты это проблема многих долгоживущих проектов. Проблема мсвц что и после напарываешься на баги, а не четыре флага в симейке
даже если предположить что что-то пофиксят, то сколько еще ждать пока потенциальные пользователи обновлять компилятор?
Так об универсальном стандарт-онли решении говорили вы, и привели пример с гну расширением.
самое ли это популярное среди спонсоров опенссл?
И да в portfile по ссылке никакой "чудовищной сложности" нету. Думаю в конфигурации правильных асм листингов под зоопарк платформ и работы с сетью (да в опенссл есть сеть) сложности больше
Так vcpkg это аналог pkgbuild из арча, deb скриптов и подобного. Т.е. тут обертка вокруг ./configure && make install а не переписываниею autotools, perl и прочего на симейк.
Обертку сделать в разы проще чем портировать миллион скриптов на симейк. И вообще если там требуется действительно что то сложное заскриптовать, то симейк как язык по сравнению с перлом это убожество.
Вредительство это сам виндовс и его поддержка. Чтобы его поддерживать требуется портить код. Он постоянно падает в BSOD, не поддерживает правильное поведение и сохраняет баги в поведении, отказываясь его фиксить
Если компания разрешает только виндовс - это её проблемы. Linux опенсорс в отличие от закрытого виндовс, поддерживает С++ лучше, программы работают обычно на 30%+ быстрее
[[gnu::noinline]]и как это будет работать по мсвц? Из-за поддержки зоопарка компиляторов оно всё и усложняетсяТак вот где находится gut feeling
Эту статью писал ллм
"Btw I use arch"
Мало кто знает что "r" в scrum не читается
можно cделать трансформ из n в 2*n + 1
так вы повоторите хоть то что в iota есть. Если бесконечный ренж неподдерживается то ладно, я вроде такое не просил.
там проблема наверное в том что старые итераторы в уже существующем коде хотели продолжать поддерживать, в новом коде iterator_category определяется.
Я ничего сложного не просил. Просто есть вектор vec,
r1 = vec | transform(f)известен размер и есть доступ к элементам,r2 = vec | filter(g)тут размера нету есть только forward итератор. Есть напримерСохраняются свойства и при передаче r1 и r2, удобно.
Если передаётся рефы всё равно вопрос как их менять. Либо копировать, либо менять инплейс.
Я не вижу как одна фича противоречит другой.
В раст я не понял как этим пользоваться. Из статьи и кода бенчмарка непонятно. Как будет индексироваться
Vector3<f32x4>, индексами от 0 до 3 или от 0 до 12?Апд исправил форматирвание
Мне лень участвовать в демагогии что конструктивно а что нет.
Фичей eigen в nalgebra нету потому что их невозможно реализовать на расте.
Ок, получается имплементировать эту часть на языке не надо т.к. она встроена в язык. В джава или C# я такой штуки не знаю (но может есть).
Для чисел есть
Вы почему-то продолжаете делать вид что не понимаете разницу между контейнерами, функциями и ренжами.
Никто не запрещает в С++ делать именованные маркеры. А так да, подходы разные, и это уже другая тема. В расте с трейтами аналогичную проблему всё же как-то решают.
zip_transformпринимает сколько угодно ренжей, жду для начала вариадиков в хаскеле.Это недоработка реализации. Бесконечный размер на уровне типов приравнен к неизвестному размеру. Ваш пример с zip кстати как раз неизвестный размер тоже не покрыл.
Если игнорировать нюансы со ссылками то можно повторить ваш искуственный пример как-то так
Так делать не надо потому что это не реализует нужных концептов для итераторов/ренжей.
Хотя я пока писал понял что смысла в таком Unbounded нету совсем. У нас либо рандом аксесс и тогда мы знаем границы, либо не знаем границ и достаём по-одному. Получается бестолковый пример обсуждаем :/
сложность thaw O(n), т.е. оно делает копию. Вообще продолажая тему про IORef я не понял как там атомарно поменять что-то размером больше инта.
Если есть гарантия что владение переменной однопоточное, то в чём проблема?
Посыл нашего обсуждения что гарантировать должен компилятор, а не человек.
Поэтому раст тут получается впереди, о чём изначально и говорилось по ссылке. Борроу чекер в паре с send/sync даёт больше выразлительности.
В чем неконструктивность если я просто констатирую факты?
А так да, будем ждать ¯_(ツ)_/¯
А как такое работает? ptr это что? Обычно массив это внтуренний примитив и ссылку на место где лежит элемент взять так просто нельзя. Или язык должен предоставлять специальный примитив для этого, который поидее и будет содержать ссылку на сам массив. Иначе как гц узнает связь между (ptr+i) и аллокацией c началом ptr?
Получается Vector это вью для последовательной аллокации? Тогда его всё равно нельзя использовать как параметр для ренжа с O(1) доступом, потому что за iota нету никакой аллокации. Зачем вы мне его предлагали?
Не вижу как сюда передать объект типа
Range, или какой вы там создали?В тот момент когда надо писать такие явные преобразования код перестаёт быть женерик.
По наличию перегрузки
size()Т.е. у меня контейнер создаётся и умирает вместе с runST? Или создаётся мутабельный вью?
Я хочу взять например вектор, мутировать его в одном потоке, потом мувнуть его в другой поток и продолжить мутировать там.
А как мне писать код который одновременно и читает что то из тред-сейф объекта расшареного и на основе этого модифицирует тред-локальный стейт?