LINUX.ORG.RU

Rust 1.34

 ,


2

11
  • cargo теперь умеет в сторонние репозитории

  • оператор ? теперь может использоваться в доктестах

  • стабилизированы трейты TryFrom и TryInto

  • стабилизированы типы AtomicU8AtomicU64 и AtomicI8AtomicI64 в дополнение к имевшимся ранее Atomic{Bool,Ptr,USize,ISize}

  • стабилизированы типы NonZeroI8NonZeroI128 и NonZeroISize в дополнение к имевшимся ранее беззнаковым аналогам

https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html

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

Не, я про название переменных. Не читаемая каша. Если вдруг через год тебе покажут этот код, скажут что в нем есть ошибка и надо фиксить, а ты по по какой-то причине выпал из области этого продукта, то вникать будешь долго. Я бы вынес некоторые части в отдельные переменные что бы легче читалось. Да и нормальные названия бы дал всему этому, а не однобуквенные.

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

Вот в рамках C++98 и С++03 я когда-то (хотя это вообще был именно сишный код) использовал макрос

В рамках C++98/03 можно использовать вот такой простой вариант:

#include <vector>
#include <iostream>

template< class V, int Dim >
class matrix_accessor {
	V & v_;
public :
	matrix_accessor(V & v) : v_(v) {}

	typename V::value_type & operator()(int row, int col) const {
		return v_[row * Dim + col];
	}
};

int main() {
	std::vector<double> T(100*50, 0.0);
	matrix_accessor<std::vector<double>, 100> pT(T);

	std::cout << pT(10, 25) << std::endl;

	pT(10, 25) = 0.3;

	std::cout << pT(10, 25) << std::endl;
}

А если немного упороться, то можно без особых проблем получить вообще околоматематическую запись вида pT[i][j]

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

Да и нормальные названия бы дал всему этому, а не однобуквенные.

В вычислительном коде чем ближе названия переменных к обозначениям в исходных формулах, тем лучше. А в математике, так уж повелось, не принято использовать обозначения в 15-20 символов длиной.

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

Забыл добавить, что в отличии от макросов, в подобном коде очень легко для отладочных целей включить run-time проверку корректности индексов. При отладке запутанных случаев бывает весьма полезно.

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

Если вдруг через год тебе покажут этот код, скажут что в нем есть ошибка и надо фиксить, а ты по по какой-то причине выпал из области этого продукта,

Там комментарии есть (которые нужно подправить, указав там pT вместо T в случае с С++) о том, что что обозначает, поэтому даже через 5 лет всё будет понятно. Как ещё назвать температуру в таком простом примере, если не одной буквой?

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

И не относись к этому примеру слишком серьёзно. Я указал откуда его первоначально взял и просто для сравнения производительности быстро переписал алгоритм на C++, лишь бы он работал тот же результат.

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

если немного упороться, то можно без особых проблем получить вообще околоматематическую запись вида pT[i][j]

Ага, как здесь например?

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

Угу, работа когда-то с таким софтом...

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

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

Ага, как здесь например?

Если ничего не путаю, то вот так:

#include <vector>
#include <iostream>

template< class T >
class row_accessor {
	T * row_;
public :
	row_accessor(T * row) : row_(row) {}

	T & operator[](int col) const { return row_[col]; }
};

template< class V, int Dim >
class matrix_accessor {
	V & v_;
public :
	matrix_accessor(V & v) : v_(v) {}

	row_accessor<typename V::value_type> operator[](int row) const {
		return &v_[row * Dim];
	}
};

int main() {
	std::vector<double> T(100*50, 0.0);
	matrix_accessor<std::vector<double>, 100> pT(T);

	std::cout << pT[10][25] << std::endl;

	pT[10][25] = 0.3;

	std::cout << pT[10][25] << std::endl;
}

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

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

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

Показанные выше трюки с marix_accessor и row_accessor мы проделывали еще году в 1994-ом, до того, как C++98 вообще появился. И если бы в C++ шаблонов не было, то я бы давным-давно с этим языком распрощался. Да и сейчас из-за этих же шаблонов особо податься некуда. Разве что в D :)

Посмотрим, завезут ли когда-нибудь в Rust скалярные аргументы для генериков.

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

Отличный вопрос. И очень в точку. Они это делают потому что могут и это очень легко, совсем не нужно ограничиваться dev пакетами дистрибутива, как принято для С/С++

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

потому, что

1. нет прода;
2. естественно не используется, это же просто пример реализации алгоритма.

Но в качестве домашнего задания можешь, если тебе нечем заняться, покрыть его тестами (зачем не знаю, так как покрывать там нечего).

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

Они это делают потому что могут и это очень легко, совсем не нужно ограничиваться dev пакетами дистрибутива, как принято для С/С++

Неверно. Ты перепутал убогую методичку и реальность. Использование либ в С++ куда быстрее и проще. Потому что а) уже всё есть, б) есть ho. Пока раст-ламерки пишут код в блокноте и ищут методы - пользователи нормальных языков получают всё и сразу.

По поводу «почему» - я уже отвечал. Ламерки не могут написать код, не могут выполнить поставленную задачу. Потому что их недоязычок - говно, как и сами адепты - птушники лсные. Ведь они так же не могут ничего, т.к. в основном это школота/студентота самого низшего класса. Т.е. всякие неудачники, которые не состоялись в реальном мире и перешли в маргинальный, где конкуренции меньше.

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

ho

Что же это такое? Придумали название, фиг нагуглишь

Если это какой-то инструмент управления зависимостями, как тот же conan, то мимо. В С++ много таких островков, но нету такого места где библиотеки публикуются в первую очередь

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

Ах, ну и да - как я мог забыть. Ещё нужно не обосраться с методичкой, а то https://github.com/rust-ndarray/ndarray/search?q=unsafe&unscoped_q=unsafe https://github.com/rayon-rs/rayon/search?q=unsafe&unscoped_q=unsafe

И это только капля в море - там миллиард говнолиб в зависимостях этой херни. А где-то снизу там биндинги к С/С++-рантайму.

NishiragiShintaro ()
Ответ на: комментарий от vertexua

Что же это такое? Придумали название, фиг нагуглишь

headers-only

Если это какой-то инструмент управления зависимостями, как тот же conan, то мимо. В С++ много таких островков, но нету такого места где библиотеки публикуются в первую очередь

Мимо это твоя методичка. Я могу использовать хоть conan, хоть что угодно и твои убогие потуги в сторону «какие-то библиотеки не могут» - пойдут куда подальше, т.к. я начну сравнивать кол-во и качество библиотек для С/С++ и раста. И ты поплывёшь так быстро как только можешь.

NishiragiShintaro ()
Ответ на: комментарий от eao197

Забыл добавить, что в отличии от макросов, в подобном коде очень легко для отладочных целей включить run-time проверку корректности индексов.

#include <stdio.h>
#include <stdlib.h>

int
main()
{
    enum { N = 100, M = 50 };
    double *v = calloc(N * M, sizeof(double));
    if (!v) {
        fprintf(stderr, "Out of memory.\n");
        abort();
    }
#define v_at(I_, J_) *({ \
        if ((I_) > N || (J_) > M) { \
            fprintf(stderr, "ko-ko-ko-ko-ko!\n"); \
            abort(); \
        } \
        &v[(I_) * M + (J_)]; \
    })

    v_at(1, 1) = 5;
    printf("%g\n", v_at(1, 1));
}
anonymous ()
Ответ на: комментарий от VarfolomeyKote4ka
fn main() {
    let arr = [1, 2, 3, 4, 5, 6];
    const INDEX: usize = 1024;

    println!("{:?}!", arr[INDEX]);
}

Вот кстати так отваливается ошибкой компиляции. Видно let не такой уже и иммутабельный для компилятора, раз у него все же есть адрес в мутабельной памяти и какой-то ковбойский код может через unsafe все поменять. А вот const - иммутабельный на этапе компиляции, вот этой штуке он доверяет

На этапе компиляции

error: index out of bounds: the len is 6 but the index is 1024

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

Вот кстати так отваливается ошибкой компиляции. Видно let не такой уже и иммутабельный для компилятора, раз у него все же есть адрес в мутабельной памяти и какой-то ковбойский код может через unsafe все поменять. А вот const - иммутабельный на этапе компиляции, вот этой штуке он доверяет

Полная и тотальная чушь. Никому компилятору ненужно знать о какой-то там мутабельности. Это говорит лишь о том, что компилятор раста говно и раст говно, т.к. не отслеживает значения и их изменение в переменных.

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

Причём я могу понять С/С++ - там типа unsafe и в любой момент можно поменять значение(пусть даже снизу), но для раста такое не прокатывает.

NishiragiShintaro ()
Ответ на: комментарий от anonymous
ta1.c: In function 'main':
ta1.c:13:23: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
 #define v_at(I_, J_) *({ \
                       ^
ta1.c:21:5: note: in expansion of macro 'v_at'
     v_at(1, 1) = 5;
     ^~~~
ta1.c:13:23: warning: ISO C forbids braced-groups within expressions [-Wpedantic]
 #define v_at(I_, J_) *({ \
                       ^
ta1.c:22:20: note: in expansion of macro 'v_at'
     printf("%g\n", v_at(1, 1));
                    ^~~~

ISO C? Не не слышали.

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

а какие настройки проекта в rust всё-таки были для сборки с O2 и fast-math?

у меня такие настройки Cargo.toml

[dependencies]
ndarray = "0.12.1"

[profile.release]
opt-level = 3
debug = false
rpath = false
lto = false
debug-assertions = false
codegen-units = 16
panic = 'unwind'
incremental = false
overflow-checks = false


и всё ужасно в плане скорости выполнения.

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

Он ничего не ломает, если знать где его можно использовать - здесь можно.

А в раст его просто нет, судя по багтреккеру. С такой скоростью выполнения вычислений лучше взять Lazarus (fpc) - скорость будет такой же и никаких проблем с прикручиванием интерфейса.

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

Он ничего не ломает, если знать где его можно использовать - здесь можно.

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

Тут разве что ручками вызывать нужные интерсинки, что уныло.

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

Уныло - это наблюдаемая скорость выполнения вычислений.

Без fast-math - та же, что и в С/С++. То, что Rust не даёт стрелять себе в ногу - это уже другая история.

Я боюсь представить как у вас будет гореть, когда вы узнаете, что в rust нельзя сортировать float.

В режиме debug я вообще вывода не дождался.

В дебаге включен overflow-checks. Так и задумано.

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

Только fast-math очень часто используемая опция при вычислениях.

Гореть сильнее от того, что производительность кода как у fpc и при этом нет gui вряд ли сильнее возможно.

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

В режиме debug я вообще вывода не дождался.

В дебаге включен overflow-checks. Так и задумано.

Здесь пациент врёт. Вся производительность раста - это целиком и полностью заслуга оптимизаций в llvm. Без этих оптимизаций это мусорная поделка ничего не может - она может начать копировать весь массив по 20раз в каждой итерации цикла.

NishiragiShintaro ()
Ответ на: комментарий от RazrFalcon

Конечно, и не только не для меня.

Но, как минимум, одной нишей у него меньше. А учитывая кто его разработчик, то его основная ниша уже заведомо предрешена и за её пределы ему долго ещё не выйти.

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

Например, там, где нет уверенности, что промежуточные результаты не окажутся бесконечными величинами (и когда нужно обрабатывать NaN); там где очень важны точность связанная с порядком операций (ffast-math включает ассоциативность операций), правилами округления и вообще строгое соответствие IEEE754.

grem ★★★★★ ()