https://ortem.xyz website source code
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
4.0 KiB
88 lines
4.0 KiB
12 months ago
|
+++
|
||
|
title = "Расттест 1"
|
||
|
date = "2022-08-18"
|
||
|
|
||
|
[taxonomies]
|
||
|
tags = ["rust"]
|
||
|
+++
|
||
|
|
||
|
### Какой тип имеет переменная `result`?
|
||
|
```rust
|
||
|
fn count_uppercase(s: &str) -> usize {
|
||
|
let result = {
|
||
|
let upper = s.chars().filter(|c| c.is_uppercase()).collect::<String>();
|
||
|
return upper.len();
|
||
|
};
|
||
|
}
|
||
|
```
|
||
|
|
||
|
<details><summary>Ответ</summary>
|
||
|
|
||
|
`result` имеет тип `!` (never type/никогдатый тип).
|
||
|
В `result` записывается результат выполнения блока инструкций в фигурных скобочках.
|
||
|
Блок `{ ... }` всегда возвращает значение, но как быть, если мы натыкаемся на `return`,
|
||
|
прерывающий поток выполнения программы и возвращающий значение из **функции**, а не из блока?
|
||
|
Для этого в раст завезли служебный тип `!`, показывающий, что тип данной переменной никогда не будет присвоен.
|
||
|
|
||
|
Если бы мы переписали функцию следующим образом:
|
||
|
```rust
|
||
|
fn count_uppercase(s: &str) -> usize {
|
||
|
let result = {
|
||
|
let upper = s.chars().filter(|c| c.is_uppercase()).collect::<String>();
|
||
|
upper.len()
|
||
|
};
|
||
|
return result
|
||
|
}
|
||
|
```
|
||
|
то `result` бы имел верный тип `usize`.
|
||
|
|
||
|
[Почитать ещё](https://doc.rust-lang.org/book/ch19-04-advanced-types.html#the-never-type-that-never-returns)
|
||
|
|
||
|
P.S.: обычно в расте принято опускать `return` и писать вместо него возвращаемое значение без `;`.
|
||
|
Это трактуется как возврат значения из текущего блока (в том числе функции)
|
||
|
|
||
|
</details>
|
||
|
<br>
|
||
|
|
||
|
### Ограничен ли дженерик-тип `T` какими-либо трейтами?
|
||
|
```rust
|
||
|
pub fn drop<T>(_x: T) { }
|
||
|
```
|
||
|
|
||
|
<details><summary>Ответ</summary>
|
||
|
|
||
|
Да, по умолчанию любые дженерики имеют ограничение `T: Sized`.
|
||
|
Этот трейт реализован для всех типов, размер которых известен на момент компиляции.
|
||
|
|
||
|
Для отмены ограничения используется следующий синтаксис:
|
||
|
```rust
|
||
|
pub fn drop<T: ?Sized>(_x: T) { }
|
||
|
```
|
||
|
означающий, что функция может принимать безразмерные типы (DST), такие как `dyn Trait`, `[u8]`, `str` и т.д.
|
||
|
|
||
|
</details>
|
||
|
<br>
|
||
|
|
||
|
### Есть ли отличия между следующими кусками кода?
|
||
|
```rust
|
||
|
const GLOBAL_MUTEX: Mutex<i32> = Mutex::new(0);
|
||
|
```
|
||
|
и
|
||
|
```rust
|
||
|
static GLOBAL_MUTEX: Mutex<i32> = Mutex::new(0);
|
||
|
```
|
||
|
|
||
|
<details><summary>Ответ</summary>
|
||
|
|
||
|
`const` клонирует значение константы во все места её использования.
|
||
|
В результате вместо изменения глобального мьютекса мы получаем несколько клонированных мьютексов и часы дебага.
|
||
|
|
||
|
В случае со `static` программа действительно создаёт один глобальный мьютекс, который можно изменять из разных потоков.
|
||
|
|
||
|
Это известная проблема, о которой не сигнализирует `rustc`,
|
||
|
поэтому будет полезно дополнительно использовать `clippy` в вашем проекте. Он не только отловит неверное использование констант,
|
||
|
но привьёт вам чувство прекрасного растового кода.
|
||
|
[Почитать ещё](https://rust-lang.github.io/rust-clippy/master/index.html#/declare_interior_mutable_const)
|
||
|
|
||
|
</details>
|
||
|
<br>
|