Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Rust более низкоуровневый и гибкий
// VarRefs() - это функция, определенная для ссылки на запрос (*Query) и возвращает массив ссылок ([]*VarRef)
func (q *Query) VarRefs() []*VarRef {
// если массив q.refs еще не вычислялся
if q.refs == nil {
// присваеваем пустой массив
q.refs = []*VarRef{}
// для каждого statement s из массива q.statements
for _, s := range q.statements {
// добавляем сссылки из s.VarRefs() в массив q.refs
q.refs = append(q.refs, s.VarRefs()...)
}
}
return q.refs
}
Go was born out of frustration with existing languages and environments for systems programming
Rust сугубо для системного программирования, в то время как Go хм для программистов.
Более того с последним релизом Rust перешел на OS threads, против собственных легковесных green threads по умолчанию, что делает серверное программирование затруднительней.
я перешёл на Rust, оставив позади Boo, Dart, Haskell
С другой стороны есть Haskell, этакий язык-крепость (по принципу «раз оно компилируется, значит работает»), хоть и не могущий похвастаться скоростью.
Нужны тесты производительности
оценки востребованности
возможности поддержки кода (и стоимости его поддержки)
Проще повторить все лучшее что уже есть или было.
Нужна востребованность, комьюнити, которое будет их развивать и т.д.
Тут не поспоришь. Проще вообще ничего нового не придумывать.
Те, кому была важна безопасность уже давно пересели на Java.
— стабильности проверенной годами
— обилии КАЧЕСТВЕННЫХ библиотек, вылизываемых годами
— обилии большого числа дешевых и качественных программистов
— стабильности проверенной годами
— обилии КАЧЕСТВЕННЫХ библиотек, вылизываемых годами
— обилии большого числа дешевых и качественных программистов
Rust даже 1 год назад очень сильно отличался от сегодняшнего; Rust 2 года назад — это совершенно другой язык.Не уверен, что это отличие в лучшую сторону.
D не взлетел. Go не взлетел. Не взлетит и Rust. Ближайшие 5 лет так точно.
Те, кому была важна безопасность уже давно пересели на Java
Попытаюсь пройтись по основным моментам, которые могут занести Вас в ступор при начальном изучении:
7) Куча багов в компиляторе, постоянные креши с просьбой отправить багрепорт.
но что напрягает, так это, например, то, что &'static str не конвертится само в &str. И че, мне теперь писать две функции чтоли?
fn print_string_slice(s: &str) { println!("{}", s); }
fn main() {
let s: &'static str = "abcd";
print_string_slice(s); // abcd
}
&'static str вполне себе конвертируется автоматом в &str.Map<K, V> в Java не переводят как «отображение» (хотя это и есть непосредственный перевод, в том числе и по смыслу) — обычно так и говорят, «мап» или «мапа», реже — «словарь» или «ассоциативный массив» (что очень длинно и неудобно, поэтому так говорят редко). Если не придерживаться общепринятой терминологии, то люди просто перестанут друг друга понимать.Map<K, V> в Java не переводят как «отображение»Потому что переводят как раз-таки как «ассоциативный массив» :) Я бы сказал, это устоявшийся перевод на русский, длинный и неудобный, но… «Отображение» — это скорее из мира математики.Map в этом случае в английском подразумевает именно отображение, потому что ассоциативный массив по сути и есть математическое отображение, которое в английском обозначается, в частности, словом «map» (или «mapping»).Это означает, что перевод «map» как «отображение» в контексте структур данных будет неверным, потому что это не устоявшийся термин.
input.map(|x| x^2) По-русски это звучит как «каждому элементу x из входной последовательности сопоставляется x^2». Отсюда, собственно, и термин "сопоставление". Он не ассоциируется с математикой и лучше отражает смысл происходящего.1) Документации очень мало, существующая почти вся нерабочая (устарела).
2) Постоянные изменения в компиляторе/библиотеке. Ни дня без breaking change.
3) Не только постоянные изменения, но и неконсистентное состояние: одну часть изменили, другую еще нет.
4) Ни одного рабочего примера в интернете (видимо, из за (2)).
5) Каждая строка кода — битва с компилятором насмерть. Пытались писать особо изощренную шаблонную магию в С++? Тут этот ад во всем коде.
6) Ошибки компилятора повергают в недоумение даже программистов под gcc с его жуткими сообщениями.
prog.cpp: In instantiation of ‘void fill_array(std::array<T, N>&, F&&) [with T = std::vector<std::basic_string<wchar_t> >; unsigned int N = 10u; F = main()::<lambda()>]’: prog.cpp:18:61: required from here prog.cpp:10:9: error: no match for ‘operator=’ in ‘v = main()::<lambda()>()’
prog.cpp:10:9: note: candidates are:
In file included from /usr/include/c++/4.7/vector:70:0,
from prog.cpp:4:
/usr/include/c++/4.7/bits/vector.tcc:161:5: note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const std::vector<_Tp, _Alloc>&) [with _Tp = std::basic_string<wchar_t>; _Alloc = std::allocator<std::basic_string<wchar_t> >]
/usr/include/c++/4.7/bits/vector.tcc:161:5: note: no known conversion for argument 1 from ‘std::vector<std::basic_string<char> >’ to ‘const std::vector<std::basic_string<wchar_t> >&’
In file included from /usr/include/c++/4.7/vector:65:0,
from prog.cpp:4:
/usr/include/c++/4.7/bits/stl_vector.h:427:7: note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(std::vector<_Tp, _Alloc>&&) [with _Tp = std::basic_string<wchar_t>; _Alloc = std::allocator<std::basic_string<wchar_t> >; std::vector<_Tp, _Alloc> = std::vector<std::basic_string<wchar_t> >]
/usr/include/c++/4.7/bits/stl_vector.h:427:7: note: no known conversion for argument 1 from ‘std::vector<std::basic_string<char> >’ to ‘std::vector<std::basic_string<wchar_t> >&&’
/usr/include/c++/4.7/bits/stl_vector.h:449:7: note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(std::initializer_list<_Tp>) [with _Tp = std::basic_string<wchar_t>; _Alloc = std::allocator<std::basic_string<wchar_t> >; std::vector<_Tp, _Alloc> = std::vector<std::basic_string<wchar_t> >]
/usr/include/c++/4.7/bits/stl_vector.h:449:7: note: no known conversion for argument 1 from ‘std::vector<std::basic_string<char> >’ to ‘std::initializer_list<std::basic_string<wchar_t> >’dangling.rs:3:12: 3:14 error: `i` does not live long enough
dangling.rs:3 return &i;
^~
dangling.rs:1:23: 4:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 1:22...
dangling.rs:1 fn dangling() -> &int {
dangling.rs:2 let i = 1234;
dangling.rs:3 return &i;
dangling.rs:4 }
dangling.rs:1:23: 4:2 note: ...but borrowed value is only valid for the block at 1:22
dangling.rs:1 fn dangling() -> &int {
dangling.rs:2 let i = 1234;
dangling.rs:3 return &i;
dangling.rs:4 }
error: aborting due to previous errorкто владеет определённой сущностью (owner), кто лишь временно одалживает её (mutable borrow), а кто просто пришёл посмотреть (immutable borrow)Теперь буду знать, какими обидными словами ругать должников и любителей поглазеть.
Указатели есть только в незащищённом коде (unsafe {}). Вместо них в безопасном коде есть ссылки, которые гарантированно указывают на существующие объекты.
while (curItem.next !=nullptr). А тут вроде как nullptr нету. И как с этим жить? Выносить все алгоритмы обхода структур данных в unsafe? Пилить отдельное поле под указание конца цепочки? А зачем тогда rust?int* ptr = new int;
int& ref = *ptr;
// blabla * 100 lines
delete ptr;
// blabla
ref = 1; // Ооps
int* ptr = nullptr;
// bla bla * 100 lines
int& ref = *ptr;
ref = 1; // Oops
предотвращает почти все падения
int *x = 123;
int &y = *x;
y = 1; // memory access violation
let mut array = Vec::new();
array.push(1);
let ptr = array.get(0); // возвращает ссылку на первый элемент
array.push(2); // небезопасно, ибо память под вектор может измениться
переменные живут до конца своей области видимости
Maybe классная штука, но не бесплатная.
println!("{}, {}",
std::mem::size_of::<Option<&int>>(),
std::mem::size_of::<int>())
Ну и опять же, no offense, но просто все эти вещи должны быть раскрыты в основной статье, а не глубоко в каментах.
Option — бесплатная штука. Компилятор оптимизирует использование памяти так, что, в частности, Option<&int> будет занимать ровно столько же памяти, сколько и &int. Это возможно за счёт отсутствия null-указателей. Более того, в планах схожая оптимизация для большего количества типов, помимо указателей.pub struct Vec<T> {
len: uint,
cap: uint,
data: *mut T
}
Vec имеют семантику типов-значений, т.е. ведут себя точно так же, как типы-значения вроде int (за исключением автоматического копирования и вызова деструкторов; это различие также себя проявляет в системе типов Rust за счёт трейтов Copy, Clone и Drop), даже несмотря на то, что внутри у них динамически выделенная память. Такие структуры очень легко описывать в терминах владения данными и уникальных указателей. Однако, это не всегда удобно/возможно: например, с помощью уникальных указателей можно описать древовидные структуры данных, а вот двусвязный список, например, сделать уже нельзя. В таком случае используются другие типы умных указателей, например, Rc, который означает указатель с подсчётом ссылок, или Gc, который будет означать указатель со сборкой мусора. В C++ есть аналогичные типы, например, shared_ptr или unique_ptr, но в C++ ничего не мешает вам получить обычный сырой C-указатель на их внутренности и сохранить его после того, как указатель «умрёт». В Rust этого сделать нельзя в принципе.
Зачем нам нужен Rust?