学生の備忘録なブログ

日々のことを忘れないためのブログです。一日一成果物も目標。技術系はQiitaにあげるように変更しました。

初めて"git push -f origin master"した。

gitへのForceとかいう不吉なことをした。

rustのコマンドを書き始めたので、gitへfirst commitしようと思った。

エラー

gitのリモートのmasterブランチが先端にないので、ローカルのほうがブランチの先にあることになり、マージできないということらしい。よくわからない。

hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

解決策

普通はこれをすればいいらしい。

git pull origin master
git push origin master

しかし

なんかよくわからないがmergeを拒否された。

git pull origin master                                     
From https://github.com/psato/tree-cd
 * branch            master     -> FETCH_HEAD
fatal: refusing to merge unrelated histories

今回の解決策

gitにforceした。

git push -f origin master

感想

今回は最初のコミットだったので、壊れる内容もなかったからforceした。 しかし、重要なプロジェクトで起きたらどうしようか。。。

参考文献

git pushがreject(拒否)されたときの対処法 - Qiita

『すべての知識を20字でまとめる。紙一枚独学法』の感想メモ

20字でまとめると

20字で教えられるようにインプットする方法(21字)

紙のフォーマット画像

[evernote:22a7eefaf81a1302138301b1aea7f604 アップロード中] [evernote:8c8e2b8fb78342e29db9d22de25dcd9b アップロード中] f:id:forhighlow:20200707224742j:plain f:id:forhighlow:20200707224745j:plain f:id:forhighlow:20200707224736j:plain [evernote:2b5e5593676702e682881854aeade9ee アップロード中]

f:id:forhighlow:20200707224726p:plain

学んだことを忘れないために重要なのは

  1. 目的の明確化
  2. 思考整理
  3. 端的な要約

メモ

  • 勉強する前に目的を紙に書いて、チラミしながら読む
  • 人に説明できることが理解の達成条件
  • 3つの疑問を自らに問いかけ、それを満たせるとき理解したと胸をはる
  • What,Why,How
  • 教養は自信の拠り所になる
  • 消費型学習ではなく、投資型学習へ
  • アウトプットできるとは教えられるということ
  • Howは抽象的ではなく具体的な動作で書く

やり方

  • 1回読んだら10分で16個程度キーワードを紙に抜き出す
  • キーワード同士を赤ペンで関係を書き込み、重要なものを整理する
  • 目的を達成するために、内容を3つの問(why,what,how)に落とし込む
  • 20字で要約する
  • 赤ペンで修正する

他者貢献

  • 働く=傍を楽にする
  • 「あなたはなぜ仕事をしているのか」
  • 「あなたが最近仕事で困っていることは」
  • 「あなたが最近熱心に学んでいることは」
  • 他者貢献の考えが普段からあれば、この問への回答に他者が出てくるはず。
  • 他者を楽にするという考え方で、コントリビューション学習法を作ってみると仕事がうまくいく

[evernote:22a7eefaf81a1302138301b1aea7f604 アップロード中] [evernote:8c8e2b8fb78342e29db9d22de25dcd9b アップロード中]

[evernote:2b5e5593676702e682881854aeade9ee アップロード中]

[evernote:642fc7a8d10ebf0f2b70d0e14435b23a アップロード中]

bit全探索

abc173

bit全探索とは

True Falseの2値で表せるような事象の組み合わせを探索したいときに、便利な探索方法

pythonでは

1<< HOGE

23 を表したいとき、 1bitを3つ左シフトさせること 探索で使いたいのでrange(1<<HOGE)で使われる

2(100) == 10(8)

1か0かチェックするには

01というintで管理しているので、2で割ったあまりが1か見る。

productライブラリ

from itertools import product

for a in product([True, False], repeat=H):
    for b in product([True, False], repeat=W):

問題

C - H and V

回答

H, W, K = map(int, input().split())
c = [input() for _ in range(H)]
result = 0

for rows in range(1 << H):
    for cols in range(1 << W):
        black = 0
        # bitが1になっているか2重ループで探索
        # 赤なら黒ではないからcontinue
        # それ意外ならblackカウンタインクリメント
        for i in range(H):
            if (rows >> i) % 2 == 1:
                continue
            for j in range(W):
                if (cols >> j) % 2 == 1:
                    continue
                if c[i][j] == "#":
                    black += 1
        if black == K: # ループのなかで条件に合う場合をカウントする
            result += 1

print(result)

ソフトウェアシステム論 (exaを読む 実践編)

要旨

ソフトウェアシステム論 (exaを読む 環境構築編)の続き

メモ

講義を忘れないためにとりあえずメモ

Result<T,E>型

Result<,>ってなに * _はなんでもいいときに使う?

Result<T,E>はいつ使う * エラー処理のための戻り値につかう。 * Rustは例外がない。 * Result<>かpanic!を使う。 * 回復可能なResult<> * 終了させるpanic!

参考 Resultで回復可能なエラー

?演算子(?後置演算子)

  • エラー委譲の省略形の書き方 実行時、エラーを想定して予めmatchで条件分岐などを書きたくない場合に用いる。 失敗すると、単に関数の実行から抜ける。

PathBuf

cloneをなぜするのか

他の言語のdeepコピーに相当する。 同じオブジェクトに別の名前を束縛するのではなく、新たにコピーを作る。

今回exaでcloneをする理由は所有権かライフタイムの問題からだと思われる。 参考

exaデバッグ実行

main.rs

11行目

configure_logger();
  • logを取るメソッド

13行目

let args: Vec<OsString> = args_os().skip(1).collect();
  • args:OsStringを持つ配列
  • args_os().skip(1)がイテレータを返す
  • collect()がイテレータを配列にまとめる args_os().skip(1).collect():コマンド実行の引数をコマンドそれ自体をスキップしてそれ以降の引数を配列'args'として得る。

14行目

match Exa::from_args(args.iter(), &mut stdout()) {
  • main.rs2行目にuse exa::Exaとあり、外部ライブラリファイルexa.rsのExaメソッドをインポートしている
  • match式でfrom_argsメソッドに対し引数args.iter(),stdout()を渡す
  • args.iter()は配列argsからイテレータを作る
  • stdout()は標準出力へのハンドラを作る

from_args()

exa.rs 86行目

    pub fn from_args<I>(args: I, writer: &'w mut W) -> Result<Exa<'args, 'w, W>, Misfire>
    where I: Iterator<Item=&'args OsString> {
        Options::parse(args, &LiveVars).map(move |(options, mut args)| {
            debug!("Dir action from arguments: {:#?}", options.dir_action);
            debug!("Filter from arguments: {:#?}", options.filter);
            debug!("View from arguments: {:#?}", options.view.mode);

            // List the current directory by default, like ls.
            // This has to be done here, otherwise git_options won’t see it.
            if args.is_empty() {
                args = vec![ OsStr::new(".") ];
            }

            let git = git_options(&options, &args);
            let ignore = ignore_cache(&options);
            Exa { options, writer, args, git, ignore } 
        })
    }

これは途中でmap()の中に入るので注意

  • parse()イテレータを解析してOptions構造体とfree filenameの配列を作成する
  • LiveVarsThe “real” environment variables type.,just calling "var_os"環境変数?よくわからない。
  • moveするのはRustの変数のライフタイムが遅延評価のmapのクロージャの中でwriterを使うから?
    • ためしにmoveをなくしてコンパイルしてみたところ、"help: クロージャwriter (および他の参照変数) の所有権を強制的に取得するには、move キーワードを使用します。"とエラーがでた。
  • 戻り値は構造体Exa

exa.rs 93行目

         if args.is_empty() {
                args = vec![ OsStr::new(".") ];
            }

15行目

Ok(mut exa) 
  • match式が問題なく実行された場合の処理が書かれている

16行目

match exa.run(){

exa.run()

  • 実際にファイルパスを取得する

exa.rs 115行目 run()

        for file_path in &self.args {
            match File::from_args(PathBuf::from(file_path), None, None) {
                Err(e) => {
                    exit_status = 2;
                    writeln!(stderr(), "{:?}: {}", file_path, e)?;
                }
                Ok(f) => {
                    if f.points_to_directory() && !self.options.dir_action.treat_dirs_as_files() {
                        match f.to_dir() {
                            Ok(d) => dirs.push(d),
                            Err(e) => writeln!(stderr(), "{:?}: {}", file_path, e)?,
                        }
                    } else {
                        files.push(f);
                    }
                }
            }
        }

  • exa.run()が成功すればexit
  • 失敗したらエラーを吐いて終わり

  • File::from_args()の戻り値 File { path, parent_dir, metadata, ext, name, is_all_all }

  • from_args()で親ディレクトリやファイル名を変数pathから得る
  • Rustの&strとStirngの関係がPathとPathBufの関係と対応しているらしい。

An owned, mutable path (akin to String). This type provides methods like push and set_extension that mutate the path in place. It also implements Deref to Path, meaning that all methods on Path slices are available on PathBuf values as well. More details about the overall approach can be found in the module documentation.

#![allow(unused)]
fn main() {
use std::path::PathBuf;

let path = PathBuf::from(r"C:\windows\system32.dll");
println!("{:?}",path)
}
>>> "C:\\windows\\system32.dll"
  • &strは文字列スライスで参照のみ
  • Stringは文字列のベクタ
  • Pathのドキュメントを見るとpush,popはなかった。PathBufの方にあった。
  • Pathを追加したり、削ったりという変更を加えるときはPathBufに入れるようだ。

filename()

file.rs 105行目

/// A file’s name is derived from its string. This needs to handle directories
    /// such as `/` or `..`, which have no `file_name` component. So instead, just
    /// use the last component as the name.
    pub fn filename(path: &Path) -> String {
        if let Some(back) = path.components().next_back() {
            back.as_os_str().to_string_lossy().to_string()
        }
        else {
            // use the path as fallback
            error!("Path {:?} has no last component", path);
            path.display().to_string()
        }
    }
  • pathを正規化して後ろから(右から)ファイル名を返すメソッド
  • components()配列じゃないものをイテレータにする
  • next_bask()イテレータの後ろから要素を得る
  • as_os_str() PashをOsStr形式に変換しファイル名に切り分ける
  • to_string_lossy無効なUnicodeが入っていたら、U+FFFD REPLACEMENT CHARACTER (�)に変換する 戻り値はCow型(A clone-on-write smart pointer.スマートポインタってなに?Rustのポインタ型)
  • to_string()String型に変換する

pathをクローンするのは、色々他にも作業があるから。

file.rs 35行目 * なぜpathをクローンするの?

ファイル名が抽出されていても、ファイルの絶対位置を調べたり (コンパイルされたファイルの検索など)、元のパスを使ったり (シンボリックリンクに続く) する操作があるため、パスを保持しておく必要があります。

read_dir()は何をして何を返すのか

dirs.rs 34行目

    pub fn read_dir(path: PathBuf) -> IOResult<Dir> {
        info!("Reading directory {:?}", &path);

        let contents = fs::read_dir(&path)?
            .map(|result| result.map(|entry| entry.path()))
            .collect::<Result<_, _>>()?;
        println!("{:?}", contents); 
        Ok(Dir { contents, path })
    }
  • read_dir()は何を返しているの? read_dir()の戻り値は以下のような感じで変化する read_dir()->Result<ReadDir> read_dir()?->ReadDirイテレータ

ReadDirResult<DirEntry>を要素に持つイテレータ

  • 2重mapはなにをしているの? 1回目map イテレータReadDirの各要素Result<DirEntry>に対して 2回目map Resul<DirEntry>の要素DirEntryに対してpath() entry.path()はDirEntryをpath型に変換する処理

  • 例 read_dir()が指定されたディレクトリの要素をもつイテレータを返すコード

#![allow(unused)]
use std::fs;

fn main() -> std::io::Result<()> {
    for entry in fs::read_dir(".")? {
        let dir = entry?;
        println!("{:?}", dir);
        println!("{:?}", dir.path());
    }
    Ok(())
}
DirEntry("./.bash_logout")
"./.bash_logout"

Playgrougndで実行する%5D%0Ause%20std%3A%3Afs%3B%0A%0Afn%20main()%20-%3E%20std%3A%3Aio%3A%3AResult%3C()%3E%20%7B%0A%20%20%20%20for%20entry%20in%20fs%3A%3Aread_dir(%22.%22)%3F%20%7B%0A%20%20%20%20%20%20%20%20let%20dir%20%3D%20entry%3F%3B%0A%20%20%20%20%20%20%20%20println!(%22%7B%3A%3F%7D%22%2C%20dir.path())%3B%0A%20%20%20%20%7D%0A%20%20%20%20Ok(())%0A%7D&edition=2018)

  • contests変数に束縛するときの処理が分かりづらい。
    • DirEntry公式ドキュメントがわかりやすかった。read_dir()はReadDir型を返すらしいが、DirEntryの例文がよりわかりやすかった。2重mapがないため。

run()の戻り値

exa.rs 144行目

        self.print_dirs(dirs, no_files, is_only_dir, exit_status)

17行目

                Ok(exit_status) => exit(exit_status),
  • exa.run()が成功したのでexitする
  • exa.run()の戻り値はfilename()

参考文献

PathBuf関係

Rustのファイルシステムコールのコーディング例

map move関係

c言語でls

初めてemacsの単語トグル`cntl+T`を使った。

5年目で初めて。 状況は実践Rustを読んで触っていて、"[count]"とするべき所を"[count]"としてしまっているのに気づいて、VScodeEmacsキーバインドにしていたのでもしやと思って使ってみたら使えた。

でもこれはいらない。二度とやることもないと思うので記念に書き残す。

てかEmacsじゃなくてVScode使ってるじゃん。

cntl+Tってかなり使いやすいキーバインドなのにそれをこれに当てはめてるのどうなの自分。

というかVScode使ってるのにEmacsキーバインドを使ってるのは何なの?

WordCount

実際に作ってみて

最近CLItoolを読んだり写経したりするにつれて(といってもgrep,wc,lsだけ)、RustのCLIのやってることは大なり小なり違ってもライブラリや引数の扱い方など基本的な所は一緒だなあと思います。

  • wcは引数を読み込み、引数の指定するファイルを読み込みます。それをバッファにいれてパースして、カウントして、表示する。
  • lsは引数を読み込み、引数の指定するディレクトリを読み込み、要素をバッファにいれて、それを表示する。
  • grepは引数を読み込み、引数の指定するファイルを読み込み、別の引数の文字列を正規表現で絞り込み、表示する。

procsを読んで見ようと思ってgithubを開いたがよくわからなかった。というか大きすぎない?topの代替にしては。そんなにすることある?と思った。 正直大きすぎるとデバッガを使ってmain()から順序よく読んでいかないことには自分のおつむでは理解できない。

実践Rust入門良き

最近技術評論社twitterが流れてきて、PDF,EPUB版の実践Rust入門が第2版となり誤植が修正されたと知り、翌日ほくほくとダウンロードして実際治っているのを確認しました。

wcの作り方、そしてそれを公開させる前にファイルを分割してよりライブラリらしくする工程とかも書いてあって実践的でやる気が出る作りで良いです。

コミュニティの良さ

Rustのslackではバグ報告が盛んでその度に著者が直々に答えていて活発なコミュニティっていいなーと感じました。

言語それ自体のコミュニティには参加したことがなくってPyConJPというカンファレンス大会のslackには参加したことがありました。

でも、実際Pythonの何かが活発に議論されているという感じではなかった。

ブラウザを作りたい

なんとなく、思っていたことだがブラウザを作ってみたい。

qiita.com

Firefoxを作ってるMozillaがRustで作っているようだ。

正直Rustで構築する最終的な目標にしている。

結構大きいものなので、どうやって作ればいいかよくわからないが、

実践Rust入門の第2章電卓を作る。で字句解析、構文解析、AST木の作成などを読んで、HTMLをパースして表示するのもこんな感じなのかなと思っている。