学生の備忘録なブログ

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

イノセンスを失ったと感じるとき

日本語は明治維新以降の知識人達の頑張りなどによって、漢文の知識などを応用して相当する単語を組み合わせたりして、外国語を翻訳して取り込むことが上手な言語です。

本来は日本にはなかった概念も昔からあったかのようになじませて来ました。

しかし、言葉の意味というのはその言葉から形を変えた時点である程度失われます。

ですからその言葉の意味を絶対に過不足なく伝えたいと思ったら、その言葉の言語でその言葉を使う。つまり翻訳せず伝えるほかないと思います。

しかし、それでは実世界では意味がないので、音を当てはめてカタカナ語にしたり、相当する意味を当てはめて新しい熟語を作ったりします。

長々と前置きしましたが、今回私はイノセンスという概念を表す言葉とそれでしか表せない自分の心象を説明したいと思います。

引退したアイドルが復活した姿を観たとき

私はメディアを通して有名人を見たり、久しぶりに知人にあったりしたとき、この感覚を覚えることがあります。

その感覚とは「この人はイノセンスを失ったな」という感覚です。

イノセンスは日本語では純潔と訳されます。しかし、これでは私の伝えたい意味とは少し違った意味が加わってしまいます。

具体的には、貞操を失ったという意味だと感じてしまう人もいると危惧します。

しかし私が感じるのはそうではなく、「イノセンスを失って普通の人になったな」と感じるということです。

この場合のイノセンスを純潔と置き換えてしまうと、単純にアイドルという意味と結びついて下品な意味になってしまいます。

innocence: 無罪、潔白、純潔、純真、無邪気、天真爛漫(らんまん)、単純、無知、無害、無毒

chastity: 肉体的な貞節

アイドルなどは特に感じます。女性も男性も区別なく、イノセンスが失われてしまった様を見て悲しく感じることがあります。

なぜなら、それらをもう一度取り戻したひとを自分は見たことがないからです。

もちろん、それにより以前にも増した人気が出てくることもあるでしょう。

しかし、それまでのイノセントな存在感は失われたので何も表面的には変わらなく見えるのに、別人のように感じてしまい冷めてしまうということが起きるのです。

これは私がいわゆるタレントに対して幼児性を愛するタイプの消費行動をするために、タレントが方向転換をして幼児性を捨てて、洗練された表現あるいは大人としての自立を表すメッセージ性を表したような場合に感じるのではないかと自己分析していました。

(いわゆるロリコンなんじゃないかと自己分析していました。*1

しかし、自分はまずロリコンではないですし、特にイノセンスを失ったと感じる対象の人が自立したり、幼児性を脱したりした場合でなくとも感じるので、どうやらそうではないのだと思い直しました。

結局わからないので、この「イノセンスを失ったな」という感覚を他の人が感じることはないのかと思い、ブログに書き綴りました。

自分に対する自信をまだ一度も失っていない

今の考えでは以下のようなときにイノセンスを失ったと感じるのではないかと思っています。

その人が自分に対する自信をまだ一度も失っていない状態を崩されて、それを受け入れたとき。

なにかカリスマと呼ばれる人はある種の教祖と同じく、自分の世界とその世界を動かす法則について絶対の自信を持っているものです。

あるいはアイドルという人たちは、物心ついた頃から自分が一番魅力的で一番注目されていたいと思っています。

しかし、アイドルが集まれば優劣が生まれて、その自信を揺るがされてしまいます。

それに対して抵抗し、あるいは自分が近い将来、絶対に一番になれるという自信を持ってなんとか頑張るという人がいます。

一方で自分の限界に見切りをつけ、現状の中である程度満足の行く成果を出そうと努力の目標を変える人もいます。

この後者の人のように、心からの自信を失ってそれを受け入れてしまったときに「ああ、この人はイノセンスを失ったのだな」と感じるのではないでしょうか。

おわりに

ポエムを久しぶりに書きました。私自身、アイドルにコミットはしたことないですが、人並みにかわいい女性とかは好きでメディアを通して見たりするのですが、その時感じる感覚が長年あったので、整理するために書きました。

  • 芸人、アイドル、諸々のタレント、芸術家等、ハレとケにおけるハレに分類されるような非日常に生きる人々に対してよくイノセンスの有無を感じます。
  • 人は世界を直接は見れません。脳がつくる心象を見ています。自分が他者に与える心象を最大限に美化させるのは、その人が自身の魅力を信じていることが重要です。
  • カリスマ教祖が信者に信じ込ませるとき、一番信じ込ませることができるのは教祖本人がそれを信じ込んでいる場合だそうです。
  • アイドルやタレントも心の底から自分の魅力を信じているとき、ポテンシャルが最大限に発揮されるのではないでしょうか。

*1:ロリコンとは少なくとも婚姻可能な男女には使われるべき言葉ではないが、ここでは通俗的な意味で使う。

treeコマンドをRustで書いた

勉強のためにtreeコマンドをRustで書いたよ

github.com

treeコマンドの要旨

treeコマンドはlsコマンドの再帰的な表示を木構造で表したものです。

これはこれまで意識したことはなかったのですが、コードを読んで確かに再帰的な処理で事足りるなと思いました。

prefix

prefixに対して空白などを追加していくことでディレクトリを右にずらしていくことにより、再帰的な深さを表すことができます。

Rustでコマンド自作 Treeコマンド編

作業メモ

  • よくわからない。
  • コマンドラインのパーサを使わない予定だったが、正直面倒なので使ったほうがいいのかもしれない。

    • 参考にしているtree-rsはclapを使っている。でもstructoptはclapをラップしている。
    • deriveマクロにも対応していてチュートリアルが押しているので、初心者むけなんだろうと考えずに使うことにする。
  • データを扱うので、構造体にする

    • structoptで引数を構造体optにした。
  • debugマクロを入れることで構造体のprintをできるようにした。

  • どうやって表示するか

prefix + |---- + filename

ここで、fileがディレクトリだった場合、再帰的にもう一度移動してディレクトリを出力する。

  • 必要な関数

    • Treeクラス
      • init関数
        • 最終的にどれくらいのディレクトリ、ファイルがあったかを表示させるため
        • dirCount変数
        • fileCount変数
      • レジスター関数
        • initで初期化した変数をインクリメントする
      • サマリー関数
        • initで定義した変数を最終的に表示する
      • ウォーク関数
        • listdir関数でdirectoriryのエントリーを取得してfilepathesリストに入れる。
        • filepathesをソートする
        • len(filepathes)でindexを取得する
        • indexごとにディレクトリの前に入れる表示させかた、再起のさせかたを変更
        • absolute関数
          • absolute = os.path.join(directory, filepaths[index])
          • directory+ディレクトリエントリ
          • 変数absolute、その時その時の処理をするためのpathを持つ変数
  • ウォーク関数の詳細

if index == len(filepaths) - 1:
    print(prefix + "└── " + filepaths[index])
        if os.path.isdir(absolute):
                self.walk(absolute, prefix + "    ")
        else:
            print(prefix + "├── " + filepaths[index])
            if os.path.isdir(absolute):
                self.walk(absolute, prefix + "│   ")
  1. もし最後ならprefix(初期値"") "└── "

    1. かつabsoluteがディレクトリなら再起でwalk(absolute,prefixに空白を足す)
    2. それ以外なら"├── "
      1. もしabsoluteがディレクトリならwalk(absolute,prefixに"│ "を足す)
  2. filter_map()

  3. prefixをString::from("")で作成する

    • hello.push('w');で後々伸ばせる。
  4. フルパスではなく、ファイル名を表示する

    • let filename = path.file_name().unwrap().to_str().unwrap();

ToDoスタック

  • [x] 構造体optを作る
  • [x] optからpathを表示する
  • [x] pathの前にprefix(階層を表す記号)をどうやって挿入するか調べる。
  • [x] 再起させずに、まずはファイル名の前にprefixと記号を入れてみる。
  • [x] 必要な関数の概要を理解する
    • [x] pythonのコードを読んで必要な関数の概要を理解する
    • [x] rustのコードを読んで必要な関数の概要を理解する
  • [x] vec<>にpathを入れる
    • [x] resultをunwrapする
  • [x] prefixをString::from("")で作成する
  • [x] paths配列の中身をフルパスではなく、ディレクトリorファイル名のみにする。
    • [x] 一番うしろを切り取る方法を調べる。

重要だけど今じゃないToDoスタック

  • [ ] オプションをパースして取得する
  • [ ] .からtreeを始める(treeの根)

参考文献

https://rust-cli.github.io/book/tutorial/cli-args.html https://github.com/kddeisz/tree/blob/master/tree.py https://doc.rust-lang.org/std/path/struct.Path.html https://github.com/sighol/tree-rs https://github.com/alexanderwe/rs-tree

初めて"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キーバインドを使ってるのは何なの?