Closed7

実践Rustプログラミング入門でうまく動かなかったとこメモ

esakaesaka

Chap4

Clapのstructopsを利用したサンプルが動作しない
バージョンも正誤表に合わせたbeta.2にしても下記のエラーが出る

コードもgithubから引っ張ってきたけどダメだった
https://github.com/forcia/rustbook/tree/master/ch04/4-1/samplecli-derivemacro

error: cannot find derive macro `Clap` in this scope
 --> src/main.rs:4:10
  |
4 | #[derive(Clap, Debug)]
  |          ^^^^

error: cannot find attribute `clap` in this scope
 --> src/main.rs:5:3
  |
5 | #[clap(
  |   ^^^^

error: cannot find attribute `clap` in this scope
  --> src/main.rs:13:7
   |
13 |     #[clap(short, long)]
   |       ^^^^

error: cannot find attribute `clap` in this scope
  --> src/main.rs:17:7
   |
17 |     #[clap(name = "FILE")]
   |       ^^^^

error[E0599]: no function or associated item named `parse` found for struct `Opts` in the current scope
  --> src/main.rs:22:22
   |
11 | struct Opts {
   | ----------- function or associated item `parse` not found for this
...
22 |     let opts = Opts::parse();
   |                      ^^^^^ function or associated item not found in `Opts`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `parse`, perhaps you need to implement it:
           candidate #1: `Clap`

warning: unused import: `clap::Clap`
 --> src/main.rs:1:5
  |
1 | use clap::Clap;
  |     ^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error: aborting due to 5 previous errors; 1 warning emitted

For more information about this error, try `rustc --explain E0599`.
error: could not compile `samplecli`

To learn more, run the command again with --verbose.
esakaesaka

https://github.com/clap-rs/clap/tree/v3.0.0-beta.2

公式のv3.0.0-beta.2のサンプルでも動かなかった

現時点で最新のv3.0.0-rc.9のサンプルは動作した

https://github.com/clap-rs/clap/tree/v3.0.0-rc.9

Cargo.toml

...
[dependencies]
clap = { version = "3.0.0-rc.9", features = ["derive"] }
use clap::Parser;

/// Simple program to greet a person
#[derive(Parser, Debug)]
#[clap(about, version, author)]
struct Args {
    /// Name of the person to greet
    #[clap(short, long)]
    name: String,

    /// Number of times to greet
    #[clap(short, long, default_value_t = 1)]
    count: u8,
}

fn main() {
    let args = Args::parse();

    for _ in 0..args.count {
        println!("Hello {}!", args.name)
    }
}

分からんけど、3.0.0.beta.2自体がなんかデグレってる?

esakaesaka

一応3.0.0-rc.9 で動く版は下記

use clap::Parser;

#[derive(Parser, Debug)]
#[clap(
    name = "My RPN program",
    version = "1.0.0",
    author = "Your name",
    about = "Super awesome sample RPN calculator"
)]
struct Opts {
    /// Sets the level of verbosity
    #[clap(short, long)]
    verbose: bool,

    /// Formulas written in RPN
    #[clap(name = "FILE")]
    formula_file: Option<String>,
}

fn main() {

    let opts = Opts::parse();

    match opts.formula_file {
        Some(file) => println!("File specified: {}", file),
        None => println!("No file specified."),
    }
    println!("Is verbosity specified?: {}", opts.verbose);
}
esakaesaka

最終的に動く逆ポーランド記法電卓のコードは下記

use clap::Parser;
use std::fs::File;
use std::io::{stdin, BufRead, BufReader};

#[derive(Parser, Debug)]
#[clap(
    name = "My RPN program",
    version = "1.0.0",
    author = "Your name",
    about = "Super awesome sample RPN calculator"
)]
struct Opts {
    /// Sets the level of verbosity
    #[clap(short, long)]
    verbose: bool,

    /// Formulas written in RPN
    #[clap(name = "FILE")]
    formula_file: Option<String>,
}

fn main() {
    let opts = Opts::parse();

    if let Some(path) = opts.formula_file {
        let f = File::open(path).unwrap();
        let reader = BufReader::new(f);
        run(reader, opts.verbose);
    } else {
        // ファイルを指定しない場合, 標準入力
        let stdin = stdin();
        let reader = stdin.lock();
        run(reader, opts.verbose);
    }
}

fn run<R: BufRead>(reader: R, verbose: bool) {
    let calc = RpnCalculator::new(verbose);

    for line in reader.lines() {
        let line = line.unwrap();
        let answer = calc.eval(&line);
        println!("{}", answer);
    }
}

struct RpnCalculator(bool);

impl RpnCalculator {
    pub fn new(verbose: bool) -> Self {
        Self(verbose)
    }

    pub fn eval(&self, formula: &str) -> i32 {
        let mut tokens = formula.split_whitespace().rev().collect::<Vec<_>>();
        self.eval_inner(&mut tokens)
    }

    fn eval_inner(&self, tokens: &mut Vec<&str>) -> i32 {
        let mut stack = Vec::new();

        while let Some(token) = tokens.pop() {
            if let Ok(x) = token.parse::<i32>() {
                stack.push(x)
            } else {
                let y = stack.pop().expect("invalid syntax");
                let x = stack.pop().expect("invalid syntax");
                let res = match token {
                    "+" => x + y,
                    "-" => x - y,
                    "*" => x * y,
                    "/" => x / y,
                    "%" => x % y,
                    _ => panic!("invalid token")
                };
                stack.push(res);
            }

            // verbose指定されている場合
            if self.0 {
                println!("{:?} {:?}", tokens, stack);
            }
        }

        if stack.len() == 1 {
            stack[0]
        } else {
            panic!("invalid syntax")
        }
    }
}
esakaesaka

5章

MyErrorの実装、Displayトレイトの実装しないと、actix_web::ResponseErrorがコンパイルエラー吐くので下記追加が必要

impl fmt::Display for MyError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

(Intellijの静的チェックだとエラー出るけど、buildしたら上なくても普通にいけたわ


5.2 DB

ライブラリ, r2d2とかのバージョンと合わせると、下記のように変更が必要

- rusqlite = { version = "0.23", features=["bundled"] }
+ rusqlite = { version = "0.26", features=["bundled"] }

5.4 DELETEのfn

- conn.execute("DELETE FROM todo WHERE id=?", &[params.id])?;
+ conn.execute("DELETE FROM todo WHERE id=?", &[&params.id])?;

こうしないとコンパイル通らない

esakaesaka

7章: GUI

そのままんだとbuildエラー

とりあえずライブラリのバージョンをあげてみる

[dependencies]
iced = { version = "0.3.0", features = ["async-std"]}
iced_native = "0.4.0"
iced_futures = "0.3.0"
async-std = { version = "1.10.0", features = ["unstable"] }

さらにコードも一部修正

impl Application for GUI {
-    type Executor = executor::Null;
+   type Executor = executor::Default;

...
-    fn update(&mut self, _message: Self::Message) -> Command<Self::Message> {
-        Command::none()
-    }
+    fn update(&mut self, _message: Self::Message, _clipboard: &mut Clipboard) -> Command<Self::Message> {
+        Command::none()
+    }

とりあえずこれで動きはした

image

githubに上がってるやつ通り
https://github.com/forcia/rustbook/blob/master/ch07/7-2/src/main.rs

このスクラップは2022/01/01にクローズされました