知らんけど。

主にプログラミングについて書きます

特定の文字列をサジェストした上で全ての文字列を受け付ける LooseAutocomplete

type LooseAutocomplete<T extends string> = T | Omit<string, T>;

自分が勉強する姿を子供に見せています

勉強する時間がない!

エンジニアの勉強には多くの時間が必要ですね。コードを書く時間、書籍を読む時間などなど。しかし、その時間を捻出するのは難しいものです。時間の捻出の難しさは人それぞれですが、私には家庭があり子供の遊びに付き合う必要があるなどして、家にいたとしても勉強を進めにくいです。

子供のために自分の勉強を我慢する。でもそれは本当に子供のためになるでしょうか?

子供の目の前で勉強をしていたらある変化が・・・

ウチの子は現在7歳の「かまってちゃん」です。1 人で遊ぶことがほとんど出来ない。常に一緒に遊んでやらなければなりませんし、見ていなければなりません。

そんな子ですが、本当にくだらない事で呼ばれた際には、「パパ勉強してるから」と言って断るようにしました。その際は、本を読むなどして実際に勉強しています。

(もちろん限度はありますが)それを続けていたら、子供に変化が現れました。

「私家庭学習するから、パパ勉強してて良いよ。」「家庭学習こんなにやったよ!」

進んで勉強をするようになっていたのです。

やはり、子は親の背中を見て育つのだなぁと思いました。そして、子供のためにも、自分(親)が勉強している姿を見せる必要があると考えるようになりました。

普段意識してやっていること

子供に自発的に勉強してもらうことについて、我が家では上手くいっていると思うので、何を意識しているのかを紹介します。

子供と遊ぶ際に「勉強する」という選択肢を出す

子供と遊ぶタイミングで「勉強する」という選択肢を出します。 子供には「好きなことをしていて良い」と言います。 その際、決して勉強しなさいとは言いません。(もちろん、宿題がある場合などは「しなさい」と言います。遊ぶタイミングで「しなさい」とは言いません。)

勉強がしたいと伝える

「パパは勉強がしたい」と伝えています。 強引にやっているつもりはありません。

本を読むところを見せる

常に本を持って、子供が一人遊びを始めたら本を読んでいます。 子供も真似をして、本を読むようになりました。

注意点

子供と遊ぶ時間を利用して勉強させてもらえる時間は非常に短いです。長くて30分くらいです。 集中もしにくいです。まぁ、仕方がありませんね。

おわりに

きっと、勉強の質をあげるには、勉強をする行為自体の鍛錬が必要なのではないかと思っています。小さい頃からの日常的な行為は、当然ながら洗練されていくでしょう。 子供に勉強を日常的な行為として身に付かせるためにも、今後も自分の勉強する姿を見せていこうと思っています。

僕のコーヒーの楽しみ方

みなさんはいつもどのようにコーヒーを楽しんでいますか? 僕は10年ほど前から、コーヒー豆を挽いてハンドドリップで淹れるのが日課になっています。 僕のコーヒーの楽しみ方を書かせていただきたいと思います。

ハンドドリップして水筒で持ち歩く

仕事の最中でも、外出先でも、いつでも美味しいコーヒーが飲みたいですよね。 なので僕は、朝にペーパードリップ3〜4杯分のコーヒーを淹れて水筒で持って出かけます。 3〜4杯分を一気に淹れると美味しく淹れやすいと思いますし、水筒に淹れておけば酸化しにくく美味しいままです。 ぬるくなってしまいますが、美味しいコーヒーはぬるくなっても美味しいと、僕は思っています。 (個人の感想です)

ペーパードリップは良いですよね。 色々試しましたが最も手軽で美味しいです。

僕が使用しているドリッパーは👇のフラワードリッパーです。

cafec-jp.com

エスプレッソやカフェラテを手軽に楽しむ

エスプレッソ、美味しいですよね。 お砂糖をたっぷりいれて、くいっっと。 時間がなかったり、お腹がいっぱいでコーヒー1杯飲みきれない・・・けどコーヒーが飲みたい!という時に最適ですね。

エスプレッソを淹れて、ミルクを注いでカフェラテにするのも良いです。 僕は牛乳が大好きなんですが、カフェラテはもっと好きです。

家でエスプレッソを楽しみたいと思うと、なんだかんだで手間がかかってしまいます。 手軽に飲みたい!

そこで、うちでは Nespresso を使ってエスプレッソを手軽に楽しんでいます。

www.nespresso.com

Nespresso を買うまでは、カプセルを使うタイプのコーヒーメーカーは美味しさもイマイチな印象がありましたし、1杯にかかるコストも自分でドリップするよりかかると思いますし、あまり良いイメージはありませんでした。

Nespresso は、コストはやはり割高とは思いますが、美味しいです。 なんと言っても美味しいエスプレッソやカフェラテを、気軽に楽しめるところが良いです!

手間をかけた美味しいコーヒーも良いですが、自宅で気軽にコーヒーを楽しみたいときはこれですね!

もっと手軽にコーヒー豆を楽しむ

次女が生まれる際に、妻と長女がお世話になるのでそのお礼と、僕も入り浸りになるので、ということで義実家に👇のコーヒーメーカーをプレゼントしました。

www.amazon.co.jp

このコーヒーメーカーは、「マツコの知らない世界」のコーヒーメーカーの特集で、もっともイチオシのコーヒーメーカーとして紹介されていました。

豆を挽くところから自動で、ハンドドリップが苦手な方でも美味しいドリップコーヒーを楽しめます。

水を少なめにし、濃いめの設定でドリップしたものは、氷を足してアイスコーヒーとしても楽しめます。

まとめ

以上、駄文ですが僕のコーヒーの楽しみ方を紹介させていただきました。 お読みいただきありがとうございました。

Next.js メモ

本当にただのメモ

気づきとか意外なこととかをメモしていきます。

コンポーネント内で空白スペースをうまくいれるには

以下のように改行があったとしてもスペースなしになる。 Helloの後ろや <strong> の前にスペースを入れたくても prettier などで補正されてしまったりする。

return (
  <div>
    Hello
    <strong>Hori-chan.</strong>
  </div>
);

f:id:hori_chan:20211127144016p:plain
実行結果

スペースを入れたい場合は以下のようにする。

return (
<div>
  Hello{" "}
  <strong>Hori-chan.</strong>
</div>
);

f:id:hori_chan:20211127144418p:plain
実行結果

Static Generation か Server Side Rendering かはページごとに選べる

getStaticProps

  • dev 起動時には request ごとにしか動かない
  • build 時にはビルド時にしか動かない(何言ってる)
  • getStaticKeys のフォールバックキーでより便利になる(なんのこっちゃ)
  • Page でしか使用できない(単なるコンポーネントは無理)

Mac でのキーボード設定など

Mac でのキーボード設定

Mistel Barocco M770 の設定

  • ディップスイッチ1 のみ ON
  • マクロ等なし

システム環境設定

  • システム環境設定
    • キーボード
      • キーボード
        • キーのリピート → 最速
        • リピート入力認識までの時間 → 最短
        • 修飾キー
          • USB-HID Keyboard (Barocco のこと)
            • Ctrl と Command を入れ替える
          • 内蔵キーボード(JIS配列)
            • Caps Lock → Command (一番左下のキー)
            • Ctrl → Caps Lock
            • Command → Ctrl
      • ユーザ辞書
        • 英字入力中にスペルを自動変換 → OFF
        • 文頭大文字 → OFF
        • スペースバー2回でピリオド → OFF
      • 入力ソース
        • 入力モード → ひらがな・英字のみ
        • Caps Lock の動作 → オンの時「英字」を入力
        • タイプミスを修正 → OFF
        • Windows風のキー操作 → ON
        • "¥" キーで入力する文字 → \ (バックスラッシュ)
        • 数字を全角入力 → OFF
      • 音声入力
        • ショートカット → OFF
  • Karabiner-Elements
    • 無効にする・インストールしない

Rust Tips : バイナリプロジェクトにおける責任の分離

以下の記事から引用&和訳したものです。 大事なので、なんども読みたいので、載せました。

doc.rust-lang.org

複数のタスクの責任をmain関数に割り当てるという組織上の問題は、多くのバイナリプロジェクトに共通しています。そのため、Rustコミュニティでは、バイナリプログラムのmainが大きくなり始めたときに、別々の関心事を分割するためのガイドラインとなるプロセスを開発しました。このプロセスは次のようなステップで構成されています。

  • プログラムをmain.rsとlib.rsに分割し、プログラムのロジックをlib.rsに移動します。
  • コマンドライン解析ロジックが小さいうちは、main.rs に残すことができます。
  • コマンドライン解析ロジックが複雑になり始めたら、それを main.rs から抽出して lib.rs に移動します。

この処理の後、main関数に残る責任は以下のように限定されるべきです。

  • コマンドライン解析ロジックを引数の値で呼び出すこと
  • その他の設定を行う
  • lib.rs内のrun関数の呼び出し
  • runがエラーを返した場合のエラー処理

このパターンは、懸念事項を分離するためのものです。main.rsはプログラムの実行を処理し、lib.rsは手元のタスクのすべてのロジックを処理します。main関数を直接テストすることはできませんが、この構造であればプログラムのすべてのロジックをlib.rsの関数に移してテストすることができます。main.rsに残る唯一のコードは、それを読むことでその正しさを検証できるほど小さくなります。

僕のRust チートシート

自分のためのチートシートを作ります。 このチートシートを少しずつ育てていくことにする。

コマンド

command 説明
cargo new hello_world バイナリプロジェクトを作る
cargo new --lib hello_world ライブラリプロジェクトを作る
cargo search hello_world クレートのバージョンについて調べる

調べる

知りたいこと 参考URL
vecの使い方について 公式ドキュメント
arc TRPL

サードパーティクレート

クレート名 説明 参考URL
structopt コマンドライン引数をいい感じに受け取る MS Learn
chrono 日付と時刻のデータを処理する MS Learn
slice_group_by vec内でグループを作る時に使うと便利。group-by は公式に実装される予定がある。 docs.rs
serde 型から Serialize と Deserialize の特性を派生できるようにするベース クレート MS Learn
serde_json Serialize と Deserialize の特性を、選択したファイル仕様形式である JSON に実装するクレート MS Learn
home ユーザーのオペレーティング システムによって異なるHOMEディレクトリを判断する MS Learn
anyhow 有用で適切なエラーをユーザーに表示できる MS Learn

小技

main 関数からは Ok / Err を返せる

fn main() -> Result<(), ()> {
    Ok(())
}

exeにコンパイルした場合、Ok(())をリターンすると実行結果は0となり、Err(())をリターンすると実行結果は1となる。

随所に出てくる不自然な() は、空のタプル。voidのようなものだろうか。

Resultが返る関数においてErrが返ったら即リターンする?構文

参考サイト

use std::error::Error;
use std::fs::File;

fn main() -> Result<(), Box<dyn Error>> {
    let f = File::open("hello.txt")?;

    Ok(())
}

Vec<i32>の合計値を求めようとして苦労した

fn sum(list: &Vec<i32>) -> i32 {
    list.iter().as_slice().iter().sum::<i32>()
}

整数同士で割り算するなら先に as f64 しておく

fn mean(list: &Vec<i32>) -> f64 {
    list.iter().as_slice().iter().sum::<i32>() as f64 / list.len() as f64
}

使用しない戻り値は_に代入する

生真面目にlet result =みたいに書くと警告吐かれて困るので。

// _ なら使わなくても警告吐かれない。
let _ = std::fs::remove_file("memo.txt");

Mac でビルド成果物を実行する

恥ずかしながら僕にはわからなかった。 ビルド成果物があるディレクトリに移動して・・・👇

./hello_world

./ がない場合、コマンドなしの結果になる。 実行ファイルを実行するには ./ が必要。

標準ライブラリで最も一般的なスマートポインタ

  • Box<T> ヒープ上にメモリを確保するスマートポインタ
  • Rc<T> 多重所有を可能にする参照カウント型スマートポインタ
  • Ref<T> RefMut<T> コンパイル時ではなく実行時に借用規則を実施する型であるRefCellを通してアクセスされるスマートポインタ

Rc::clone の使い所

あんまりよくわからないけど、グラフデータなどで複数のノードから一つのノードを参照するような構造を作る際に使える。通常のBox(再帰は可能)などで実現しようとすると所有権の問題でコンパイルできない。それを解決するのにDeepClone しちゃうと性能の問題が発生するし、全く別のインスタンスを参照することになってしまう。

そんな場合に Rc::new で唯一のノードを作成し、それを参照する複数のノードは唯一のノードを引数に Rc::clone することで、同一インスタンスへの参照を持つことができる。

参考👇 doc.rust-lang.org

Interior mutability pattern(インテリアミュータビリティパターン)

std::cell::RefCell の使い所。 Mock オブジェクトを使って試験したい場合の例がわかりやすい。

doc.rust-lang.org

Rc と RefCell の合わせ技

もうなんだかわからん。

doc.rust-lang.org

MPSC

multiple producer, single consumer の略。

doc.rust-lang.org

連番のVecを作る

fn main() {
    let min = 8;
    let max = 13;
    let vec: Vec<u8> = (min..max).collect();
    println!("{:?}", vec); // [8, 9, 10, 11, 12]
}

スレッド間で値を安全に共有するためのAtomic Reference Counting, Arc.

引用:

doc.rust-lang.org

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = counter.lock().unwrap();

            *num += 1;
        });
        handles.push(handle);
    }

    for handle in handles {
        handle.join().unwrap();
    }

    println!("Result: {}", *counter.lock().unwrap());
}

等価比較する

/// derive で PartialEq を指定すると、プロパティ全てを等価比較する挙動となる。
#[derive(PartialEq, Debug)]
struct A {
    x: u8,
    y: u8,
}

/// 独自の実装が必要であれば derive で PartialEq を指定せず impl で fn eq を実装する。
#[derive(Debug)]
struct B {
    id: u8,
    foo: u8,
}

impl PartialEq for B {
    /// id が同じならば等価とみなす
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

fn main() {
    let a1 = A { x: 1, y: 2 };
    let a2 = A { x: 1, y: 2 };
    let a3 = A { x: 3, y: 3 };
    assert_eq!(a1, a2);
    assert_ne!(a1, a3);

    let b1 = B { id: 1, foo: 1 };
    let b2 = B { id: 1, foo: 2 };
    let b3 = B { id: 3, foo: 1 };
    assert_eq!(b1, b2);
    assert_ne!(b1, b3);
}

詳しくは👉 Eq in std::cmp - Rust

impl 内の fn の引数で self: Box<Self> になってるのなに

いやぁそろそろわけわからなくなってきましたが、説明にはこうありました。

メソッドの最初のパラメータとして、self、&self、&mut selfではなく、self: Boxとなっていることに注意してください。この構文は、その型を持つBoxに対してメソッドが呼び出されたときのみ有効であることを意味します。この構文は、Boxの所有権を取得し、古い状態を無効にして、Postの状態値が新しい状態に変換できるようにします。

Box に格納している場合のみ呼び出し可能な関数を定義する際に使うのだろうか。 とても使い所が難しい気がする。

参考👇

Implementing an Object-Oriented Design Pattern - The Rust Programming Language

パターンがマッチし続ける限りwhileループを実行することができる while let

if letと似た構造のwhile let条件付きループは、パターンがマッチし続ける限りwhileループを実行することができます。リスト18-2の例は、ベクターをスタックとして使用し、ベクター内の値をプッシュされたのと逆の順序で表示するwhile letループを示しています。

    let mut stack = Vec::new();

    stack.push(1);
    stack.push(2);
    stack.push(3);

    while let Some(top) = stack.pop() {
        println!("{}", top);
    }

引用元👇

All the Places Patterns Can Be Used - The Rust Programming Language

イテレータの中身をindexとともに取得したい時は enumerate() を使う

    let v = vec!['a', 'b', 'c'];

    for (index, value) in v.iter().enumerate() {
        println!("{} is at index {}", value, index);
    }

参考👇

All the Places Patterns Can Be Used - The Rust Programming Language

Vec<u32>.iter().map(|n| *n++) のように n は dereference が必要?

iter_into() を使うと dereference は不要?

collect() を変数に格納せずに型指定する

assert_eq!(
    vec![1, 2, 3].iter().map(|n| *n * 2).collect::<Vec<u8>>(),
    &[2, 4, 6]
);

お手軽にコピーしたいときは

#[derive(Copy, Clone)]

テストで println! を標準出力する

以下でテストを実行することで標準出力されるようになる。

cargo test -- --nocapture

Rust の Vec をインデックス付きでループする方法

引用元:Rust の Vec をインデックス付きでループする方法 参考にさせて頂きます。ありがとうございます。

let a = ['a', 'b', 'c'];

for (i, val) in a.iter().enumerate() {
    println!("{}: {}", i, val);
}

👇 (0_i32..) のような書き方もできるのか〜びっくり。

let a = ['a', 'b', 'c'];

for (i, val) in (0_i32..).zip(a.iter()) {
    println!("{}: {}", i, val);
}

勉強になります。

JS でいうところの array.some

some ではなく any でした。

let a = ['a', 'b', 'c'];

let result = a.any(|item| item == 'a');

Rust の補完が効かない問題

以下と rust-analyzer があれば良さそう。

 rustup component add rust-src
 rustup component add rust-analysis
 rustup component add rls