Понимаю, что это, возможно, первый код автора на Rust, но всё-таки хочется указать на некоторые недочёты.
Непонятен выбор библиотек. Почему generic-matrix вместо ndarray или nalgebra? Почему именно reed-solomon? Так вышло, что я знаком с автором reed-solomon, и он говорит, что эта библиотека была в своё время его упражнением в Rust и не предназначена для серьёзного использования.
Опять-таки, можно написать короче и заодно не расписывать все варианты:
pub fn flip_module(&mut self) {
if let Self::Data(data) = self {
*data = !*data;
}
}
pub fn set_square(&mut self, size: usize, cordinate: (usize, usize), matrix_module: &mut Matrix<Module>) {
let start_width: usize = cordinate.1;
let start_height: usize = cordinate.0;
for i in 0..size {
for j in 0..size {
let new_module = matrix_module.index_mut((i, j));
self.set_module((i + start_height, j + start_width), *new_module);
}
}
}
pub fn set_module(&mut self, cordinate: (usize, usize), new_module: Module) {
let mut _module: &mut Module = self.get_mut_module(cordinate);
_module.set_module(new_module);
}
К этим функциям у меня хватает вопросов:
Зачем отдельным параметром передается size, если, насколько я понимаю, можно вынуть размер из matrix_module?
Зачем matrix_module передаётся по мутабельной ссылке, если он не меняется?
Зачем используется index_mut вместо оператора индексации?
Почему в set_module выносится отдельная переменная _module, да ещё и с прочерком в начале? В Rust так принято именовать неиспользуемые переменные, поскольку по умолчанию на них не срабатывает предупреждение о мёртвом коде.
(и, кстати, почему cordinate с одной o?)
И да, библиотеки рулят. С какой-нибудь nalgebra весь метод можно было бы свести к
И да, функция зачем-то принимает на вход Vec<u8>, вынуждая вызывающую сторону безусловно выделять память, в то время как просто слайса (&[u8]) было бы достаточно (собственно, это именно то, что принимает на вход Encoder::encode).
В функции move_horizontaly есть число 6. Мне, как человеку со стороны, вообще непонятно, откуда оно взялось.
В функции move_vertical есть вот такой странный фрагмент:
Зачем тут else if? Условия self.upward и !self.upward взаимно исключают друг друга.
В любом случае, не смотря на недочёты, видно, что автор программировать всё же умеет — что правда впечатляет с учётом его возраста. Правда, у меня сложилось впечатление, что хоть это и первая программа на Rust, но не первый опыт программирования у автора в принципе. Судя по косвенным признакам (аннотации типов, геттеры, сеттеры, ненужные return), я бы сделал ставку на Java. Я угадал?
И да, хотелось бы увидеть опубликованный код, желательно на платформе, где можно предложить исправления. Кода в статье не хватает для того, чтобы собрать программу целиком.
При этом код на Rust — очень часто вообще нечитабелен из-за переизбытка Rc/Box и времён жизни
Очень странное заявление. Rc — это потоконебезопасный счётчик ссылок. У него есть свои области применения, но всё же он обладает меньшей универсальностью, чем Arc — атомарный счётчик ссылок. Arc используется в реальных программах куда чаще.
Ну а Box — это аналог std::unique_ptr, который используется примерно тогда же, когда unique_ptr используется в C++. И что-то мне подсказывает, что про код на C++ вы не скажете "переизбыток уникальных указателей".
То есть вы предлагает руками вызывать функции для экранирования подставляемых параметров? Извините, но это ненадёжно: рано или поздно пользователь библиотеки забудет это сделать и подвергнется опасности SQL injection.
Дело в том, что на С пишут "достаточно специфические люди". Которые примерно знают во что превратится их код на ассемблере (не до строчки, но примерено представляют).
Ага, а потом очень обижаются, когда их столетний говнокод перестаёт работать из-за того, что новая версия компилятора начинает абузить UB в их коде.
Когда ты пишешь на С++, ты никогда не знаешь во что выльется твой код. Что стоит за вызовом той или иной функции — сколько там будет динамических выделений/освобождений памяти, сколько создастся/схлопнется уровней стека и т.п
Надо же, совсем как в C!
(и сам не раз с этим сталкивался когда ++-й код не проходит по быстродействию, а написанное на чистом С проходит ...)
Это очень странная ситуация, потому что (почти) всё, что можно написать на C, можно написать и на C++. И, к слову, C++ не заставляет использовать динамическую аллокацию памяти.
У меня вопрос по коду. Насколько я могу видеть, вы полагаетесь на то, что имена переменных уникальны и не учитываете, что имена аргументов вложенных лямбд могут затенять имена аргументов обрамляющих функций.
И этой действительно проблема. Скажем, если в окружение добавить факт, что имя "y" имеет тип "int", то для такого выражения:
(\x.x)(y)
ваш алгоритм корректно выводит тип выражения, как int, но для чуть более сложного
Что такое сознание, "трудная проблема сознания", "китайская комната", "философский зомби"
Кстати, философский зомби — понятие абсолютно бесполезное. Именно потому, что по определению такой объект неотличим от человека.
А насчёт китайской комнаты — их современным аналогом можно считать языковые модели (в том числе нашумевшую ChatGPT). И детектировать искусственность их вывода вполне возможно на практике.
Как человек, который эти самые ЕГЭ сдавал — то, что учёба в 11 классе выхолащивается в подготовку к ЕГЭ. Натаскивая этим самым на наработку навыка, который после сдачи ЕГЭ становится бесполезным, ведь сдаётся ЕГЭ только один раз.
Как-то однажды знаменитый учитель Кх Ан вышел на прогулку с учеником Антоном. Надеясь разговорить учителя, Антон спросил: "Учитель, слыхал я, что объекты — очень хорошая штука — правда ли это?" Кх Ан посмотрел на ученика с жалостью в глазах и ответил: "Глупый ученик! Объекты — всего лишь замыкания для бедных."
Пристыженный Антон простился с учителем и вернулся в свою комнату, горя желанием как можно скорее изучить замыкания. Он внимательно прочитал все статьи из серии "Lambda: The Ultimate", и родственные им статьи, и написал небольшой интерпретатор Scheme с объектно-ориентированной системой, основанной на замыканиях. Он многому научился, и с нетерпением ждал случая сообщить учителю о своих успехах.
Во время следующей прогулки с Кх Аном, Антон, пытаясь произвести хорошее впечатление, сказал: "Учитель, я прилежно изучил этот вопрос, и понимаю теперь, что объекты — воистину замыкания для бедных." Кх Ан в ответ ударил Антона палкой и воскликнул: "Когда же ты чему-то научишься? Замыкания — это объекты для бедных!" В эту секунду Антон обрел просветление.
Всё ядро операционной системы, например, построено на разыменовании указателей, сконструированных из целых чисел, и других подобных вещах, являющихся несомненным UB.
Если вы про Linux, то он по факту и не на C написан.
Если операция свёртки энергичная (как в набившем оскомину примере суммы списка через свёртку), то левая свёртка эффективнее, потому что не плодит thunk-и.
Понимаю, что это, возможно, первый код автора на Rust, но всё-таки хочется указать на некоторые недочёты.
Непонятен выбор библиотек. Почему
generic-matrixвместо ndarray или nalgebra? Почему именноreed-solomon? Так вышло, что я знаком с авторомreed-solomon, и он говорит, что эта библиотека была в своё время его упражнением в Rust и не предназначена для серьёзного использования.Теперь непосредственно по коду.
Этот метод просто не нужен и целиком заменяется на оператор присваивания по месту.
Можно написать короче:
Опять-таки, можно написать короче и заодно не расписывать все варианты:
К этим функциям у меня хватает вопросов:
size, если, насколько я понимаю, можно вынуть размер изmatrix_module?matrix_moduleпередаётся по мутабельной ссылке, если он не меняется?index_mutвместо оператора индексации?set_moduleвыносится отдельная переменная_module, да ещё и с прочерком в начале? В Rust так принято именовать неиспользуемые переменные, поскольку по умолчанию на них не срабатывает предупреждение о мёртвом коде.(и, кстати, почему
cordinateс однойo?)И да, библиотеки рулят. С какой-нибудь
nalgebraвесь метод можно было бы свести кДалее, функцию
create_reed_solomon_encoderможно без ущерба для кода заменить наEncoder::new. Это даже короче.Разнесено на три строчки то, что можно уместить в одну:
И да, функция зачем-то принимает на вход
Vec<u8>, вынуждая вызывающую сторону безусловно выделять память, в то время как просто слайса (&[u8]) было бы достаточно (собственно, это именно то, что принимает на входEncoder::encode).В функции
move_horizontalyесть число 6. Мне, как человеку со стороны, вообще непонятно, откуда оно взялось.В функции
move_verticalесть вот такой странный фрагмент:Зачем тут
else if? Условияself.upwardи!self.upwardвзаимно исключают друг друга.В любом случае, не смотря на недочёты, видно, что автор программировать всё же умеет — что правда впечатляет с учётом его возраста. Правда, у меня сложилось впечатление, что хоть это и первая программа на Rust, но не первый опыт программирования у автора в принципе. Судя по косвенным признакам (аннотации типов, геттеры, сеттеры, ненужные
return), я бы сделал ставку на Java. Я угадал?И да, хотелось бы увидеть опубликованный код, желательно на платформе, где можно предложить исправления. Кода в статье не хватает для того, чтобы собрать программу целиком.
А как эта задача решается, кстати?
Очень странное заявление. Rc — это потоконебезопасный счётчик ссылок. У него есть свои области применения, но всё же он обладает меньшей универсальностью, чем Arc — атомарный счётчик ссылок. Arc используется в реальных программах куда чаще.
Ну а Box — это аналог std::unique_ptr, который используется примерно тогда же, когда unique_ptr используется в C++. И что-то мне подсказывает, что про код на C++ вы не скажете "переизбыток уникальных указателей".
Столько громких заявлений — и ни одного аргумента, кроме ятаксказал
А ничего, что даже сама Microsoft отказалась от поддержки всех этих версий?
То есть вы предлагает руками вызывать функции для экранирования подставляемых параметров? Извините, но это ненадёжно: рано или поздно пользователь библиотеки забудет это сделать и подвергнется опасности SQL injection.
Ну и тот факт, что экранируются только кавычки, как-то не внушает доверия.
… Или можно просто вызвать
arr.reverse()и не думать об индексах вообще /sХотелось бы больше деталей. Или там NDA?
Ну, вообще-то изменит: не нужно следить за соответствием тегов и типа, в который кастуется общий указатель.
Ага, а потом очень обижаются, когда их столетний
говнокод перестаёт работать из-за того, что новая версия компилятора начинает абузить UB в их коде.И да, они почти наверняка не знают.
Надо же, совсем как в C!
Это очень странная ситуация, потому что (почти) всё, что можно написать на C, можно написать и на C++. И, к слову, C++ не заставляет использовать динамическую аллокацию памяти.
Удивительно!
У меня вопрос по коду. Насколько я могу видеть, вы полагаетесь на то, что имена переменных уникальны и не учитываете, что имена аргументов вложенных лямбд могут затенять имена аргументов обрамляющих функций.
И этой действительно проблема. Скажем, если в окружение добавить факт, что имя
"y"имеет тип"int", то для такого выражения:ваш алгоритм корректно выводит тип выражения, как
int, но для чуть более сложноговыводит неправильный
Variable(TypeVariable(1)).Кстати, философский зомби — понятие абсолютно бесполезное. Именно потому, что по определению такой объект неотличим от человека.
А насчёт китайской комнаты — их современным аналогом можно считать языковые модели (в том числе нашумевшую ChatGPT). И детектировать искусственность их вывода вполне возможно на практике.
*Кто же пишет тесты
Как человек, который эти самые ЕГЭ сдавал — то, что учёба в 11 классе выхолащивается в подготовку к ЕГЭ. Натаскивая этим самым на наработку навыка, который после сдачи ЕГЭ становится бесполезным, ведь сдаётся ЕГЭ только один раз.
Всячески поддерживаю. Вот только конкретно по биологии не советую, она так себе.
На C с нестандартными расширениями от GCC
Если вы про Linux, то он по факту и не на C написан.
Если операция свёртки энергичная (как в набившем оскомину примере суммы списка через свёртку), то левая свёртка эффективнее, потому что не плодит thunk-и.