• person rss_feed

    nerdfella’s feed

    Blog

    • chevron_right

      Ржавый стыд

      nerdfella · Wednesday, 22 April, 2020 - 18:33 · 3 minutes

    Друзьяшечки, я учу Rust, и пока пишу на нём такую дичь, что аж стыдно и противно.

    Shame

    Сейчас кодить не могу, но могу сделать обзор своего же кода. Программка состоит из двух файлов как в 12 главе Rust Book'а. main.rs только запускает функцию run из lib.rs. А вот сам lib.rs:

    1> extern crate yaml_rust;
    2> 
    3> use yaml_rust::{YamlLoader, YamlEmitter};
    4> use yaml_rust::yaml::Yaml;
    5> use std::fs::File;
    6> use std::io::prelude::*;
    7> use std::collections::HashMap;
    8> use std::error::Error;
    9> 
    10> pub struct Config {
    11>     pub layout: String,
    12>     pub corpus: String,
    13> }
    14> 
    15> impl Config {
    16>     pub fn new(args: &[String]) -> Result<Config, &'static str> {
    17>     if args.len() > 1 {
    18>             return Err("Too many arguments.");
    19>     }
    20>     
    21>     let layout = String::from("layout.yaml");
    22>     let corpus = String::from("corpus.yaml");
    23> 
    24>     Ok(Config {layout, corpus})
    25>     }
    26> }
    27> 
    28> struct Layout(HashMap<String, HashMap<String, String>>);
    29> 
    30> impl Layout {
    31>     fn from_yaml(yaml: &Yaml) -> Layout {
    32>     let mut layout: HashMap<String, HashMap<String, String>> = HashMap::new();
    33>     for (lang, keys) in yaml.as_hash().unwrap() {
    34>         let mut hash: HashMap<String, String> = HashMap::new();
    35>         for (key, chord) in keys.as_hash().unwrap() {
    36>         hash.insert(key.as_str().unwrap().to_string(),
    37>                 chord.as_str().unwrap().to_string());
    38>         }
    39>         layout.insert(lang.as_str().unwrap().to_string(), hash);
    40>     }
    41>     Layout(layout)
    42>     }
    43> 
    44>     fn score(layout: Layout, corpus: Corpus) -> Result<f64, Box<dyn Error>> {
    45>     let mut summ = 0.0;
    46>     summ = summ + 1.0;
    47>     Ok(summ)
    48>     }
    49> }
    50> 
    51> struct Corpus(HashMap<String, HashMap<String, f64>>);
    52> 
    53> impl Corpus {
    54>     fn from_yaml(yaml: &Yaml) -> Corpus {
    55>     let mut corpus: HashMap<String, HashMap<String, f64>> = HashMap::new();
    56>     for (lang, pairs) in yaml.as_hash().unwrap() {
    57>         let mut hash: HashMap<String, f64> = HashMap::new();
    58>         for (pair, weight) in pairs.as_hash().unwrap() {
    59>         hash.insert(pair.as_str().unwrap().to_string(),
    60>                 weight.as_f64().unwrap());
    61>         }
    62>         corpus.insert(lang.as_str().unwrap().to_string(), hash);
    63>     }
    64>     Corpus(corpus)
    65>     }
    66> }
    67> 
    68> pub fn run(config: Config) -> Result<(), Box<dyn Error>>  {
    69>     let mut file = File::open(config.layout).expect("Unable to open file");
    70>     let mut contents = String::new();
    71>     file.read_to_string(&mut contents)
    72>         .expect("Unable to read file");
    73> 
    74>     let layout_yaml = &YamlLoader::load_from_str(&contents).unwrap()[0];
    75>     let layout = Layout::from_yaml(layout_yaml);
    76>     Ok(())
    77> }
    78> 
    

    Начну с начальца.

    1> extern crate yaml_rust;
    

    Я не знаю что делает эта строка. То ли надо Rust Book перечитывать, то ли я ещё не дошёл до объяснения этой конструкции. Я пока прочитал только первые 12 глав.

    3> use yaml_rust::{YamlLoader, YamlEmitter};
    

    Надо, конечно, убрать YamlEmitter, я им пока не пользуюсь.

    3> use yaml_rust::{YamlLoader, YamlEmitter};
    4> use yaml_rust::yaml::Yaml;
    5> use std::fs::File;
    6> use std::io::prelude::*;
    7> use std::collections::HashMap;
    8> use std::error::Error;
    

    В каком порядке принято это всё писать? Зачем нужны пространства std::io и std::fs, в чём разница?

    10> pub struct Config {
    11>     pub layout: String,
    12>     pub corpus: String,
    13> }
    

    Надо повторить разницу между String и &str. Ко всем остальным употреблениям String это тоже относится.

    28> struct Layout(HashMap<String, HashMap<String, String>>);
    

    Хотел определить новый тип для хранения раскладки. На stackoverflow ещё был вариант с trait'ами. Не понимаю как это работает и как этим пользоваться. Идём дальше.

    31>     fn from_yaml(yaml: &Yaml) -> Layout {
    32>     let mut layout: HashMap<String, HashMap<String, String>> = HashMap::new();
    33>     for (lang, keys) in yaml.as_hash().unwrap() {
    34>         let mut hash: HashMap<String, String> = HashMap::new();
    35>         for (key, chord) in keys.as_hash().unwrap() {
    36>         hash.insert(key.as_str().unwrap().to_string(),
    37>                 chord.as_str().unwrap().to_string());
    38>         }
    39>         layout.insert(lang.as_str().unwrap().to_string(), hash);
    40>     }
    41>     Layout(layout)
    42>     }
    

    Это что за жесть? Почему так многословно? И это при том, что я использовал unwrap(), а не полноценный pattern matching. И я в HashMap преобразую даже не файл, а уже переменную типа Yaml. Ниже ещё несколько строчек с чтением файла, тоже уродливых.

    И да, в похожей функции для Corpus'а я использую f64, потому что Yaml выдаёт только f64. Мне такая высокая точность не нужна, но как преобразовать в f32 я не знаю.

    Если у вас есть какие-то комментарии или ответы на мои вопросы, то я с удовольствием вас послушаю.

    • wifi_tethering open_in_new

      This post is public

      nl.movim.eu