сказочник а-ля Рел может присоединиться к команде редокса и чой-нть мало-мальски полезное накропать но пока Рел тута доказывает могучность ржаки, происходит сишизация редокса, пч для написания ржачных кодов тупо нет ресурсов
То есть, камнем преткновения оказались не недостатки языка, парадигма и даже не два процента потерь во вложенных циклах, а невозможность переписать весь существующий сишный софт? А в чём тогда твой посыл? Система-то более сишной не становится. relibc написана на расте - просто появляется возможность запускать софт на других языках, которые требуют более полной libc, чем есть сейчас. --- Сообщение объединено, 5 фев 2024 --- Кстати, два забавных момента: 1. Наше обсуждение почему-то крутится только вокруг раста, хотя основная канва темы - отказ от си и плюсов в целом, где это возможно, в пользу более простых, удобных и высокоуровневых языков - не обязательно в пользу раста, а, например, в пользу гоу, шарпа или даже джавы. Хейт именно раста, похоже, вызван не особенностями языка, а тем, что среди вышеназванных языков он один имеет шансы действительно заменить си с плюсами в нишах, куда шарпам и джавам пока не добраться. Проще говоря, дело не в языке, а в потенциальном обесценивании знаний и навыков сишных спецов. На горизонте появился конкурент - включаем режим берсерка. 2. Хейтеры приводят выдуманные аргументы, каждый из которых легко опровергается фактами, но почему-то ещё никто в этой теме не говорил про настоящие недостатки и неудобства раста, которые действительно мешают жить. Чтобы жизнь мёдом не казалась, надо исправить это упущение - завтра соберу вам подборочку моментов, от которых #аштрисёт.
полная формула: overhead * 2ⁿ %, n - глубина вложенности цикла ядерные коды бегают в контексте процесса и слегонца могут достигать глубины в 5чку достоинства ржаки таковы, что денег на разработку редокса не дают очень интересно, то бишь нужно прописать полноценный рантайм/либы на сишке иль Ты хочешь утверждать, что на ржаке можно прописать сишные функи полноценно???
...vs двухпроцентный Убивец... так и живем... Странно, ресурсов для написания кодов на Ржавом нет, а мелкомягкие с красноглазиками их тратят на то, чтобы потеснить Цэ в своих ядрах. Видишь ресурсы, я тоже нет, а они есть.
Да и пускай достигают - по бенчмаркам отличий от си нет. У нас есть одна система на расте, на которую не выделяют денег, и миллион систем на си, на которые тоже не выделяют денег. Может, дело не в языке, а коммерческой нецелесообразности создания новых операционок? Или всё-таки в языке? А в чём проблема? Пиши хоть на паскале, лишь бы ABI совпадал.
У раста иде от JetBrains называется RustRover, у кого нет деньги на торогие автомобили можно бесплатно почуствовать себя шишешчкой на ровном месте, что тоже плюс! Запишите в бенчмарк
Сложный против простого. Вот чувак намудрил, что сразу и поймёшь. Вот что нагородил своими лямбдами. Код (C++): // Ray is inbounds so test to see if the ray cell is a wall block if (map.c_str()[nTestX * nMapWidth + nTestY] == '#') { // Ray has hit wall bHitWall = true; // To highlight tile boundaries, cast a ray from each corner // of the tile, to the player. The more coincident this ray // is to the rendering ray, the closer we are to a tile // boundary, which we'll shade to add detail to the walls vector<pair<float, float>> p; // Test each corner of hit tile, storing the distance from // the player, and the calculated dot product of the two rays for (int tx = 0; tx < 2; tx++) for (int ty = 0; ty < 2; ty++) { // Angle of corner to eye float vy = (float)nTestY + ty - fPlayerY; float vx = (float)nTestX + tx - fPlayerX; float d = sqrt(vx*vx + vy*vy); float dot = (fEyeX * vx / d) + (fEyeY * vy / d); p.push_back(make_pair(d, dot)); } // Sort Pairs from closest to farthest sort(p.begin(), p.end(), [](const pair<float, float> &left, const pair<float, float> &right) {return left.first < right.first; }); // First two/three are closest (we will never see all four) float fBound = 0.01; if (acos(p.at(0).second) < fBound) bBoundary = true; if (acos(p.at(1).second) < fBound) bBoundary = true; if (acos(p.at(2).second) < fBound) bBoundary = true; } Поначалу вообще не понял что этот код делает. Но потом переделал в более простой и понятный код. Код (C++): // Ray is inbounds so test to see if the ray cell is a wall block if (map[nTestX * nMapWidth + nTestY] == '#'){ // Ray has hit wall bHitWall = true; // To highlight tile boundaries, cast a ray from each corner // of the tile, to the player. The more coincident this ray // is to the rendering ray, the closer we are to a tile // boundary, which we'll shade to add detail to the walls sSquare corners[4]; // Test each corner of hit tile, storing the distance from // the player, and the calculated dot product of the two rays for (int tx = 0, n = 0; tx < 2; tx++) for (int ty = 0; ty < 2; n++, ty++){ // Angle of corner to eye float vy = (float)nTestY + ty - fPlayerY; float vx = (float)nTestX + tx - fPlayerX; float dist = sqrt(vx*vx + vy*vy); corners[n].dist = dist; corners[n].dot = (fEyeX * vx / dist) + (fEyeY * vy / dist); } // Sort Pairs from closest to farthest // Сортировка пузырьком #define SWAP(a,b){auto tmp1=(a);auto tmp2=(b);(a)=tmp2;(b)=tmp1;} bool swapped = true; for (int j=4; swapped; j--){ swapped = false; for (int i=1; i < j; i++){ if (corners[i-1].dist > corners[i].dist){ SWAP(corners[i].dist, corners[i-1].dist) SWAP(corners[i].dot, corners[i-1].dot) swapped = true; } } } // First two/three are closest (we will never see all four) float fBound = cosf(0.003); if (fBound <= corners[0].dot || fBound <= corners[1].dot || fBound <= corners[2].dot) bBoundary = true; Надо проще делать.
HoShiMin, возможно ты удивишься, но внутри квика для малых массивов как раз используется пузырёк, либо аналогичная простая сортировка. Можно вызвать и qsort, но мне так проще. Хотя этот алгоритм совсем не оптимальный, и я его переделал.
В одном из интервью они сами искренне удивлялись что их сырые поделки кто-то покупает, у них там целая тима говноделов
Уже лет 5 пользуюсь Райдером, куда приятнее, удобнее и (что удивительно) быстрее, чем Визуал Студия. А вы говорите, эти ихние Джавы медленные... в сравнении с гуанокодом на Плюсах и Шарпах, бывает, что и быстрые.
Нет, справедливости ради, у меня 48гб, но это никак не отменяет моего удивления тем, что десктопное приложение на Джавах/Котлинах оказывается мало того, что более быстрым и отзывчивым, но еще и куда более функциональным, чем приложение на Плюсах/Шарпах, которое пилят целая куча индусов со времен, когда динозавры были большими.
Современная джава - давно не тот тормозной монстр, которым была пятнадцать лет назад, во времена 1.4 и 1.5. Сейчас и она, и шарп почти не уступают в производительности плюсам. Единственное, в чём нативные языки пока впереди - в сильно меньших аппетитах к памяти. Впрочем, с появлением .NET Native и AOT-компиляции джавы в Graal и эта проблема уже не так актуальна. --- Ладно, львы, сегодня мы хотели устроить разнос расту: вместо выдуманных проблем посмотрим на проблемы настоящие. Где-то будет субъективно, но я как Тиньков - я так чувствую. В общем, нечего тянуть - вперёд! 1. Сложный синтаксис. Поднимите руки все, кто считает синтаксис раста простым или хотя бы читаемым. Как я и думал - лес рук. Просто возьмём что-то рандомное: Код (Rust): impl<Fut, T, E> Future for FromRequestOptFuture<Fut> where Fut: Future<Output = Result<T, E>>, E: Into<Error>, { type Output = Result<Option<T>, Infallible>; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { let this = self.project(); let res = ready!(this.fut.poll(cx)); match res { Ok(t) => Poll::Ready(Ok(Some(t))), Err(err) => { log::debug!("Error for Option<T> extractor: {}", err.into()); Poll::Ready(Ok(None)) } } } } Никого не смущает, что знаков препинания здесь больше, чем смысла? Да-да-да, ко всему можно привыкнуть, мы всё это уже слышали. Давайте просто посмотрим на джаву: Код (Java): public void sayToFaction(Player player, String text, String faction) { logger.info(player.getName()); logger.info(text); logger.info(faction); String playerName = player.getName(); FactionInfo factionInfo; boolean isAdminSays = false; if (faction == null) { factionInfo = factions.getPlayerFaction(playerName); if (factionInfo == null) { player.sendMessage(ChatColor.DARK_RED + "Вы не состоите во фракции!"); return; } } else { factionInfo = factions.getFaction(faction); if (factionInfo == null) { player.sendMessage(ChatColor.DARK_RED + "Фракции " + ChatColor.GOLD + faction + ChatColor.DARK_RED + " не существует!"); return; } if (!PEXFactionsWrapper.isFactionsManager(player)) { player.sendMessage(ChatColor.DARK_RED + "У вас нет прав на доступ к этой команде!"); return; } isAdminSays = true; } factionInfo.sayToFaction(playerName, text, isAdminSays); } Это просто квинтессенция кода, кратчайший путь от мысли до реализации. Ты просто берёшь и пишешь. Да, в нативных языках без сборщика мусора растовые закорючки - необходимость, но нам от этого не легче. 2. Отсутствие битовых полей. Seriously? В языке, нацеленном на низкий уровень, где буквально ВСЁ описано битмапами, нет их поддержки? К сожалению, да. О них сломано много копий, но сообщество пришло к выводу, что их невозможно сделать универсально. Никто не знает, как должны работать битмапы для разных архитектур, для Little- и BigEndian; описывать ли их как подмножество примитивных типов, как в си, или вводить специальный тип bit; как (и нужно ли) проверять или ограничивать значения, которые пытаемся в них записать - и так далее. В итоге сообщество, используя макросы, стало придумывать свой синтаксис для битовых полей - и таки да, большинство реализаций не стали изобретать велосипед и решили сделать как в си, просто потому что это удобно и привычно. Теперь у нас есть bitfield, proc-btfields, bit, modular-bitfield - тысячи их. 3. Указатели. Как дело доходит до указателей - мы приходим к такому бреду: Код (Rust): struct Root { inner: *const Inner } struct Inner { the_innest: *const TheInnest } struct TheInnest { value: i32 } fn test(root: *const Root) { let value = unsafe { (*(*(*root).inner).the_innest).value }; } Вы правда считаете это нормальным? Что мешало ввести оператор стрелочку? Код (Rust): fn test(root: *const Root) { let value = unsafe { root->inner->the_innest->value }; } 4. Константы в дженериках. Дженерики просто не работают (по крайней мере так, как вы ожидаете). Смотрим пример: Код (Rust): struct Sample<const VALUE: i32>; impl<const VALUE: i32> Sample<VALUE> { const INNER: i32 = VALUE; // Это можно fn sample(&self) { const A: i32 = VALUE; // can't use generic parameters from outer item const B: i32 = Self::INNER; // can't use generic parameters from outer item const C: i32 = Sample::INNER; // А вот так можно todo!(); } } Кто-нибудь может объяснить, почему C объявить можно, а A и B нельзя? А почему Sample доступен, а его синоним Self - нет? Никто не может. А это не обусловлено НИЧЕМ. Хорошо, давайте другой пример: Код (Rust): struct Sample<const VALUE: i32>; fn test() { const A: i32 = 123; const B: i32 = 123; let instance = Sample::<A + B>; // expected trait, found constant `A` let instance = Sample::<{ A + B }>; // А так можно } А чем обусловлено это? У нас что, результат A + B перестал возвращать число или перестал быть константой? Тоже нет. На словах раст Лев Толстой с Тьюринг-полными дженериками, а на деле can't use generic parameters from outer item. 5. Компайлтайм в трейтах. Код (Rust): trait Something { fn func(&self) -> i32; } struct Impl; impl Something for Impl { // functions in traits cannot be declared const const fn func(&self) -> i32 { todo!() } } Из-за этого мы не можем использовать for в const-функциях, потому что внутри for вызывает метод iter() из трейта, а тот не может быть константным. В итоге все ваши планы на компайлтайм идут по бороде. 6. Вечный unstable. 6.1 Аллокаторы. В stable-расте нельзя определять кастомные аллокаторы для произвольных коллекций. Всё, что мы можем - только переопределить глобальный аллокатор. Проблема с ними та же, что с битовыми полями: никто не знает, что и в каком виде мы от них хотим. Проблематику можно почитать здесь. 6.2. Nightly. Помните наши эксперименты с bare-metal? Каждый раз, когда мы выходим за рамки поддерживаемых систем, нам приходится переключаться в nightly-ветку, чтобы пересобрать тулчейн, т.к. stable запрещает это делать. Как бы да, сборка core под неподдерживаемую систему - не совсем безопасно, но зачем добавлять ещё потенциальных проблем, заставляя собирать заведомо нестабильную ветку, которая даже на поддерживаемых архитектурах не предполагает стабильной работы? И очень похоже, что эти части раста никогда не будут стабилизированы. 7. Casts everywhere. Код (Rust): fn sample(val: usize) { ... } fn test() { let val: u8 = 123; sample(val); // mismatched types @ expected `usize`, found `u8` } Да, мы знаем, что раст не приемлет неявных кастов, и это действительно может быть небезопасно в некоторых случаях. Но почему нельзя разрешить их там, где это безопасно, как в примере выше? Знаковые в беззнаковые и обратно - харам, большие в меньшие - харам, но меньшие-то в большие почему нельзя? 8. Строки. Строки в расте хранятся в UTF-8 и не используют нуль-терминаторы. Понятно, что хотели разработчики: для самого раста нуль-терминаторы не нужны, но ВНЕЗАПНО нужны ВСЕМУ, на чём он работает. Неожиданно оказалось, что раст работает не в сферическом вакууме, а на операционках, где все строки предполагают завершающий ноль. Что мешало сделать как в дэльфи или как в C++, когда строка хранит и длину, и терминатор - неясно. Идём дальше - строковые литералы. На линуксе ладно, там и так строки в UTF-8, а как быть на винде, где весь WinAPI работает в UTF-16? Снова получаем костыли, типа макроса w! в windows-rs, который в компайлтайме конвертирует строковый литерал в массив u16. В марте выходит релиз 1.77, в котором наконец стабилизировали литералы для сишных-строк. Ждём ещё десять лет, пока стабилизируют UTF-16 и дадут возможность из коробки с ним работать, как с обычной строкой. 9. Паники (у меня от раста). У нас же память бесконечная, правда? Нам же не нужно беспокоиться о том, что она однажды закончится? Чёрт возьми, раст, ты должен был бороться со злом, а не примкнуть к нему!
Чтобы установить Rust сначала нужно установить vs_buildtools. Он не устанавливается из коробки одним кликом: скачал rustup-init.exe, запустил и все ок Почему 2 действия надо делать вместо одного? Для удобства? --- Сообщение объединено, 6 фев 2024 --- Я не говорю что gcc "идеален", но что мешало создателям Rust 'а сделать все в одном .exe без мутного скачивания? Например в таком виде, но без кривого sourceforge: https://sourceforge.net/projects/gcc-win64/ --- Сообщение объединено, 6 фев 2024 --- Или к примеру: https://www.python.org/downloads/release/python-3121/ Решил внести немного конструктива в твой дискурс, интересен твой ответ, только ответь честно без риторики: --- Сообщение объединено, 6 фев 2024 --- Даже скайнет наверно меньше весит =) --- Сообщение объединено, 6 фев 2024 --- Накодить «чёрную магию в одну строку, которая непонятно почему но работает, это ли не плюс?
И всё это, чтобы использовать майкрософтовский линкер. Всё равно что ради ложки мёда покупать пасеку.