1. ホーム
  2. Web プログラミング
  3. 関連情報

ラストオペレーターを語る

2022-01-17 17:56:26

単項演算子

単項演算子はその名の通り、ラスト要素に特化して操作する演算子で、以下のような構成になっています。

  • : 負の値をとる。特に数値型に対して。std::ops::Negを実装しています。
  • * : デリファレンス。std::ops::Deref または std::ops::DerefMut を実装します.
  • ! : 逆。例えば、!falseはtrueと等価である。面白いことに、この演算子を数値型に使うと、すべてのビットを反転させるのです! std::ops::Notが実装されています。
  • & &mut : それぞれ所有者、読取専用権、読取書込権にリース、借用します。

二項演算子

算術演算子

  • + : 追加です。std::ops::Addを実装しています。
  • - : 引き算をする。std::ops::Subを実装しています。
  • * : 乗算を行う。std::ops::Mulを実装しています。
  • : ディバイド。std::ops::Divを実装しています。
  • % : 余りを取る。std::ops::Remを実装しています。

ビット演算子

  • & : 操作を行います。std::ops::BitAndを実装しています.
  • |{code または操作。std::ops::BitOrを実装しています.
  • - ^ : Iso or. std::ops::BitXor を実装しています。
  • << : 左シフト演算子。std::ops::Shl を実装しています。
  • >> : 右シフト演算子。std::ops::Shrを実装しています。

不活性なブーリアン演算子

論理演算子には、次の3つがあります。

&&
||
and
!
. The first two of these are called inert boolean operators, so named because other C-like logic short-circuiting problems can occur in Rust. They work exactly the same as in C. But the difference is that in Rust this operator can only be used on bool types.
The comparison operator
The 

The comparison operators are actually syntactic sugar for certain traits, but there are only two traits implemented by the comparison operators: the std::cmp::PartialEq and std::cmp::PartialOrd .

where == and ! = implemented by PartialEq, the < , > , {{code > >=

<= はPartialOrdで実装されています。

標準ライブラリでは std::cmp このmodの下に4つのtraitがあり、直感的にOrdとEqの方が良いのでは?と思うかもしれませんが、Rustのこの4つのtraitの扱いは非常に明快です。という浮動小数点数における特殊な値があるからです。 NaN これは未定義の浮動小数点数を表します。Rustでは 0.0f32 / 0.0f32 を使ってその値を求めますが、それはすべて決定された値ですが、未定義な数を表しているので、次に NaN ! = NaN その結果はどうなるのでしょうか?標準ライブラリは、次のように教えてくれる。 true . しかし、この書き方では Eq の定義にある total equal (各数値は同じ)。したがって、次のようになります。 PartialEq が定義され、NaN の場合は特別に参照される。

一般的なケースでは、Rust のコンパイラは PartialOrd PartialEq をデフォルトの比較シンボルとして使用します。 trait .

型変換演算子

これはword asなので演算子には見えません。他の言語での表示変換に似ている。

fn avg(vals: &[f64]) -> f64 {
    let sum: f64 = sum(vals);
    let num: f64 = len(vals) as f64;
    sum / num
}

演算子のオーバーロード

Rustは演算子のオーバーロードをサポートしています。より詳細な部分については、次のセクションで説明します。以下はその例です。

use std::ops::{Add, Sub};

\#[derive(Copy, Clone)
struct A(i32);

impl Add for A {
    type Output = A;
    fn add(self, rhs: A) -> A {
        A(self.0 - rhs.0)
    }
}

impl Sub for A {
    type Output = A;
    fn sub(self, rhs: A) -> A{
        A(self.0 + rhs.0)
    }
}

fn main() {
    let a1 = A(10i32);
    let a2 = A(5i32);
    let a3 = a1 + a2;
    println!("{}", (a3).0);
    let a4 = a1 - a2;
    println!("{}", (a4).0);
}

    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `yourpath\hello_world\target\debug\hello_world.exe`
5
15

書式付き文字列

RustはPythonのformatと同様のアプローチをとっており、5つのマクロと2つのtraitをコアセットとして持っています。
format! フォーマット format_arg! ,

print!
, println!
, write!
 and 
Debug
,
Display
.
was already used in hello_world 
print!
or 
println!
These two macros, but the core one is 
format!
The first two macros are just a way to change the
format!
to console.
Let's start by analyzing a
format!
application of
fn main() {
    let s = format!("Today is {0} year {1} month {2} day, {week:?} , temperature {3:>0width$} ~ {4:>0width$} degrees Celsius. ",
        2016, 11, 24, 3, -6, week = "Thursday", width = 2);

    print!("{}", s);
}

As you can see, the
format!
macro can be called with any type of parameter, and the position and key-value parameters can be mixed. Note that the key-value value can only appear after the position value and does not occupy position.
fn main() {
    let s = format!("Today is {0} year {1} month {2} day, {week:?} , temperature {3:>0width$} ~ {4:>0width$} degrees Celsius. ",
        2016, 11, 24, week = "Thursday", 3, -6, width = 2);

    print!("{}", s);
}

This will report an error.
  Compiling hello_world v0.1.0 (yourpath/hello_world)

/{br error: expected ident, positional arguments cannot follow named arguments {
 --> main.rs:3:42
  |{br {
3 | 2016, 11, 24, week = "Thursday", 3, -6, width = 3);
  | ^
error: aborting due to previous error error: Could not compile `hello_world`. Note also that the argument type must implement the std::fmt For example, most of the native types implement the Display and Debug macros, and the integer type additionally implements the Binary and so on. can be accessed via {:type} that takes the call to these parameters. For example. format!(":b", 2); // call the `Binary` trait format!(":? ", "hello"); // call `Debug` Call Display by default if type is empty. The colon : is followed by more parameters, such as the {3:>0wth$} and {4:>0wth$} . First > is a semantics that indicates that the generated string is aligned to the right, so the above code yields 003 and -06 These are the two values. As opposed to the left-aligned < and centered ^ . Next 0 is a special padding syntax that indicates that the empty digits are filled with zeros, and wth& indicates the length of the formatted string. It can be an exact length value, or it can be a number starting with $ as a string ending in $ The preceding part can be written as a key or a position. Note also that between wth and type there is a region called precision, and their representation usually starts with . They usually start with . .4 indicates 4 decimal places of precision. The worst part is that it is still possible to reference the parameter in this position, just like wth above, with .N$ to represent a position parameter, except that it cannot refer to a key-value type. For example fn main() { // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)} println!("Hello {0} is {1:.5}", "x", 0.01); // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)} println!("Hello {1} is {2:.0$}", 5, "x", 0.01); // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)} println!("Hello {0} is {2:.1$}", "x", 5, 0.01); } will output. Hello x is 0.01000
/{br Hello x is 0.01000
Hello x is 0.01000
There is another special use of this bit, which is . *, which does not denote a value, but two values. The first value indicates the exact number of bits, and the second value marker indicates the value itself. For example fn main() { // Hello {next arg ("x")} is {second of next two args (0.01) with precision // specified in first of next two args (5)} println!("Hello {} is {:. *}", "x", 5, 0.01); // Hello {next arg ("x")} is {arg 2 (0.01) with precision // specified in its predecessor (5)} println!("Hello {} is {2:. *}", "x", 5, 0.01); // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified // in arg "prec" (5)} println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01); } This example will output. Hello x is 0.01000
/{br Hello x is 0.01000
Hello x is 0.01000
You can see more in the standard library documentation format! for more information. This is the end of this article on Rust operators. For more information about Rust operators, please search the previous articles of Codedevlib or continue to browse the following articles.

fn main() {
    let s = format!("Today is {0} year {1} month {2} day, {week:?} , temperature {3:>0width$} ~ {4:>0width$} degrees Celsius. ",
        2016, 11, 24, 3, -6, week = "Thursday", width = 2);

    print!("{}", s);
}


fn main() {
    let s = format!("Today is {0} year {1} month {2} day, {week:?} , temperature {3:>0width$} ~ {4:>0width$} degrees Celsius. ",
        2016, 11, 24, week = "Thursday", 3, -6, width = 2);

    print!("{}", s);
}

Call Display by default if type is empty.

Hello x is 0.01000

/{br Hello x is 0.01000
Hello x is 0.01000
You can see more in the standard library documentation
format!
 for more information.