기초문법

요약

hello world

fn main() {
    let s = "hello world";
    println!("{}", s); // println! macro   标准输出macro 可以完成编译器格式检查, 更加安全
}

타입지정

fn Foo(input1: i32, input2: u32) -> i32 {
  ...
}

use

use std::prelude::*; // std rust에서 제공하는 standard 유틸

Format

fn main() {
    println!("{}", 1); // default
    println!("{:o}", 9); // 八进制
    println!("{:x}", 255); // 十六进制 小写
    println!("{:X}", 255); // 十六进制 大写
    println!("{:p}", &0); // pointer
    println!("{:b}", 15); // 二进制
    println!("{:e}", 10000f32); // 科学计数 小写
    println!("{:E}", 10000f32); // 科学计数 大写
    println!("{:?}", "test"); // debug
    println!("{:#?}", ("test1", "test2")); // 带换行和缩进的debug
    println!("{a} {b} {b}", a = "x", b = "y"); // 命名参数
}

변수선언

let num: i32 = 100;
let num = 100i32;

let x = 5;
x = 10; // error

let mut x = 5;
x = 10;

let x:i32;
x = 1;

let (mut a, mut b) = (1,2);
let Point {x: ref a, y: ref b} = p;

static GLOBAL:i32 = 0;

기본 데이터 유형

let empty: () = (); // unit type
let boolean: bool = true;
let t1: char = 'x';
// u8 ~ u128
let i1: i8 = -128; // -128~127
let i2: u8 = 255; // 0~255
// f32, f64
let f1: f32 = 123.0;
let f2 = 123.0f32;

복합 데이 유형

// tuple
let a = (1i32, false);
let b = (a, (1i32, 2i32));
let a = (0,);
let b: i32 = (0); // 표현식, tuple 아님

// struct
struct Point {
  x: i32,
  y: i32,
}
let p = Point {x: 0, y: 0};
println!("point is at {} {}",p.x, p.y);

// struct: 생략 가능
let x = 10;
let y = 20;
let p = Point {x, y};

// struct: px, py alias로 바인딩 가능
let p = Point { x: 0, y: 1 };
let Point { x: px, y: py } = p;

// struct: destruct도 가능
let Point {x, y} = p;

// struct: 语法糖, default 지정 가능
struct Point3d {
  x: i32,
  y: i32,
  z: i32,
}
fn default() -> Point3d {
  Point3d { x: 0, y: 0, z: 0 }
}
let origin = Point3d { x: 4, ..default() };

// tuple struct
struct T(i32);
let v1 = T(1);
let v2 = T{0: 1};

// enum
enum Number {
    Int(i32),
    Float(f32),
}
// Number::Int로 enum구성원에 접근
fn read_num(num: &Number) {
    match num {
        &Number::Int(value) => println!("integer {}", value),
        &Number::Float(value) => println!("float {}", value),
    }
}
fn main() {
    let n: Number = Number::Int(10);
    read_num(&n);
}
// index
enum Animal {
    dog = 1, // 선언하지 않으면 0
    cat = 200,
    tiger,
}

let x = Animal::tiger as isize;
println!("{}", x) // 201

Expression

let x = 100;
let y = 10;
let t = true;
let f = false;

println!("{}", x + y);
println!("{}", x - y);
println!("{}", x * y);
println!("{}", x / y);
println!("{}", x % y);
println!("{}", x == y);
println!("{}", x != y);
println!("{}", x < y);
println!("{}", x > y);
println!("{}", x >= y);
println!("{}", x <= y);
println!("{}", t && f);
println!("{}", t || f);
println!("{}", !t);

let mut y1 = 40;
let mut y2 = 40;
let mut y3 = 40;
let mut y4 = 40;
let mut y5 = 40;
y1 += 10;
y2 -= 10;
y3 *= 10;
y4 /= 10;
y5 %= 10;
println!("{}", y1);
println!("{}", y2);
println!("{}", y3);
println!("{}", y4);
println!("{}", y5);
let x: () = {
    println!("hello x");
};
x;
let y: i32 = {
    println!("hello y");
    30
};
println!("{}", y);

if else

fn func(n: i32) -> bool {
    if n < 0 {
        println!("{} is negative", n);
    } else if n > 0 {
        println!("{} is positive", n);
    } else {
        println!("{} is zero", n);
    }
    return n > 0;
}
let x = func(-3);
println!("{}", x)

loop

let mut count = 0u32;

loop {
    count += 1;
    if count == 3 {
        println!("three");
        continue;
    }

    println!("{}", count);
    if count >= 5 {
        println!("OK");
        break;
    }
}

while

let mut count = 0u32;

while count < 101 {
    if count % 15 == 0 {
        println!("fizzbuzz");
    } else if count % 3 == 0 {
        println!("fizz");
    } else if count % 5 == 0 {
        println!("buzz");
    } else {
        println!("{}", count);
    }
    count += 1;
}

for

let array = &[1, 2, 3, 4, 5];
for i in array {
    println!("is {}", i);
}

함수

// 일반
fn add(t: (i32, i32)) -> i32 {
    t.0 + t.1
}
fn add2((a, b): (i32, i32)) -> i32 {
    a + b
}
println!("{}", add((1, 2)));
println!("{}", add2((3, 4)))

// return이 없는 경우 unit ()
fn empty(a: i32) -> () {
    a+a;
}

// 함수에 값을 할당해서 사용(타입이 동일할 때에만 할당 가능)
// let mut f = add as fn((i32, i32)) -> i32;
let mut f: fn((i32, i32)) -> i32 = add;
f = add2;

println!("{}", f((1, 3)))

// main함수 args
fn main() {
    for arg in std::env::args() {
        println!("{}", arg);
    }
    std::process::exit(0);
}
// ./004 test1 opt2
// ./004
// test1
// opt2

// const 함수 컴파일 단계에서 실행하는 함수라서 제한이 많음,
// 제한이 있을수 있으니 조심해서 사용
const fn add(a: i32, b: i32) -> i32 {
    a + b
}

let total: i32 = add(1, 2);
let total2: i32 = add(3, 4);
println!("{}", total);
println!("{}", total2);

// 재귀 함수
// 函数调用自身,称为递归。如果尾调用自身,就称为尾递归。
// rust1.19 버전까지 trail call 최적화가 되지 않음.
fn fib(index: u32) -> u64 {
    if index == 1 || index == 2 { 1 } else { fib(index - 1) + fib(index - 2) }
}

let f8 = fib(8);
println!("{}", f8)

trait

// method
trait Shape {
    fn area(&self) -> f64;
}
struct Circle {
    radius: f64,
}

impl Shape for Circle {
    fn area(&self) -> f64 {
        std::f64::consts::PI * self.radius * self.radius
    }
}

let c = Circle { radius: 2f64 };
println!("{}", c.area());

// static method
struct T(i32);
impl T {
    fn func(this: &Self) {
        println!("{}", this.0)
    }
}

let x = T(42);
T::func(&x);

// extend method
trait Double {
    fn double(&self) -> Self;
}
impl Double for i32 {
    fn double(&self) -> i32 {
        *self * 2
    }
}

let x: i32 = (10).double();
println!("{}", x)

// fully qualified syntax(universal function call syntax)
trait Cook {
    fn start(&self);
}
trait Wash {
    fn start(&self);
}
struct Chef;
impl Cook for Chef {
    fn start(&self) {
        println!("Cook::start");
    }
}
impl Wash for Chef {
    fn start(&self) {
        println!("Wash::start");
    }
}

let me = Chef;
<Cook>::start(&me);
<Chef as Wash>::start(&me);

// alias
pub trait Service {
    type Request;
    type Response;
    type Error;
    type Future: Future<Item=Self::Response, Error=Self::Error>;
    fn call(&self, req: Self::Request) -> Self::Future;
}

trait HttpService = Service<Request = http::Request, Response = http::Response, Error = http::Error>;

array

let v = [1,2,3];
// 크기 반드시 지정, 가변 크기는 std Vec/LinkedList 사용
let xs: [i32; 5] = [1, 2, 3, 4, 5];
println!("{:?}", xs)

// 기본값 으로 fill처리
let xs: [i32; 5] = [0; 5];
println!("{:?}", xs)

// 2depth
let v: [[i32;2];3 ] = [[0,0],[0,0],[0,0]]

// range
let r = 1..10;
for i in r {
    println!("{}", i);
}

string

let greeting: &str = "Hello";
let substr: &str = &greeting[2..];
println!("{}", greeting);
println!("{}", substr);

let mut s = String::from("Hello");
s.push(' ');
s.push_str("World");
println!("{}", s)

match

enum Direction {
    East,
    West,
    South,
    North,
}

fn print(x: Direction) {
    match x {
        Direction::East => {
            println!("East");
        }
        Direction::West => {
            println!("West");
        }
        Direction::South => {
            println!("South");
        }
        Direction::North => {
            println!("North");
        }
    }
}

fn print2(y: Direction) {
    match y {
        Direction::East => {
            println!("East");
        }
        _ => {
            println!("Other");
        }
    }
}

fn print3(x: Direction) {
    match x {
        Direction::East => 10
        Direction::West => 20
        Direction::South => 30
        Direction::North => 40
    }
}

let x = Direction::East;
let y = Direction::West;
print(x);
print2(y);
print3(x);

_

struct P(i32, i32, i32);
fn calc(P(x, _, y): P) -> i32 {
    x * x + y * y
}
let t = P(1, 2, 3);
println!("{}", calc(t));