「念書」の歌詞が好き

B’z が好きで子どもの頃からよく聴いている。

その流れで B’z のメンバーのソロ楽曲も聴くことがあるんだけど、最近「念書」をあらためて聴く機会があり、良さを再確認した。

僕はこの曲の歌詞が好きだ。

今から自分がやることを未来において 絶対後悔いたしません 永遠に誓いますって 心に彫ってしまえばいい

ここが特に気に入っている。

僕は「自分の行動が未来に及ぼす影響を真剣に考える」かつ「行動を起こしたのなら最後までやりきり、どのような結果であれ真摯に受け入れる」というふたつの意味で解釈している (歌詞の前段からの流れをくむと、後者の意味合いの方が強そうだ)。我ながら陳腐な理解だと思うけど、「やっていくぞ」という気持ちになる。

Node.js の REPL に関する tips

REPL で複数行の入力を行う方法

Node.js の REPL で複数行の入力を行うには .editor とタイプすればよい。.editor とタイプしてから Ctrl-d をタイプするまでの範囲をインタプリタが解釈する。

$ node
Welcome to Node.js v12.18.0.
Type ".help" for more information.
> .editor
// Entering editor mode (^D to finish, ^C to cancel)
const foo = 'bar'
foo

(^d をタイプして REPL を終了する)

'bar'

REPL で直前に評価した値を再利用する

Node.js の REPL で直前の値を参照したい場合は _ 変数を使う。次に使用例を示す。

$ node
Welcome to Node.js v14.2.0.
Type ".help" for more information.
> [1, 2, 3]
[ 1, 2, 3 ]
> _[0]
1

なお、直前のエラーは _error 変数に入れられる。

「ふつうの Linux プログラミング 第2版」再入門 - 自作 cat コマンド (タブと改行を変換するバージョン)

引き続き「ふつうの Linux プログラミング 第2版」を読んでいく。6章の練習問題に次のようなものがある。 タブ文字 ('\t') を 「\t」という2文字、改行を「'$' + 改行」の2文字として置き換えながら出力する cat コマンドを書きなさい。 次のようなコードを書いてみた。 // P.132 の練習問題 #include <stdio.h>#include <stdlib.h> #define BUFFER_SIZE 2048 static void do_cat(FILE *f); int main(int argc, char *argv[]) { if (argc == 1) { do_cat(stdin); } else { for (int i = 1; i < argc; i++) { FILE *f; f = fopen(argv[i], "r"); if (!f) { perror(argv[i]); exit(1); } do_cat(f); fclose(f); } } exit(0); } static void do_cat(FILE *f) { int c; while ((c = fgetc(f)) ! [Read More]

「ふつうの Linux プログラミング 第2版」再入門 - 自作 cat コマンド

何日か前の「決意表明」の後、あらためて「ふつうの Linux プログラミング 第2版」を読み直すことにした。C 言語に対するコンプレックスを払拭するのだ。 過去にも書いたことがあるけど「ふつうの Linux プログラミング」は大変な名著である。僕は第1版も第2版も購入している (そして、どちらも途中で脱落した…)。今回は練習問題をすべてこなして、最後まで読み切ろうと思う。 最初の練習問題は「cat コマンドの再実装」だ。write(2) と read(2) が紹介された章の問題なので、僕のコードも無駄にシステムコールを使っている。 全体のコードは次の通りだ。 // 本章で作った cat コマンドを改造して、コマンドライン引数でファイル名が渡されなかったら標準入力を読むようにしなさい。 #include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h> static void do_cat(int fd, const char *s); static void die(const char *s); int main(int argc, char *argv[]) { if (argc == 1) { do_cat(STDIN_FILENO, "STDIN"); } else { for (int i = 1; i < argc; i++) { int fd; fd = open(argv[i], O_RDONLY); do_cat(fd, argv[i]); } } exit(0); } #define BUFFER_SIZE 2048 static void do_cat(int fd, const char *path) { unsigned char buf[BUFFER_SIZE]; if (fd < 0) die(path); for (;;) { int n = read(fd, buf, sizeof buf); if (n < 0) die(path); if (n == 0) break; if (write(STDOUT_FILENO, buf, n) < 0) die(path); } if (close(fd) < 0) die(path); } static void die(const char *s) { perror(s); exit(1); } 長いので関数ごとに見ていこう。 [Read More]

【読書メモ】NO HARD WORK!

NO HARD WORK!」を読んだ。日本語版には「無駄ゼロで結果を出すぼくらの働き方」というサブタイトルがついている。BasecampJason FriedDHH が書いた本である。

僕は彼らの書く本が好きで、数年前まではよく読んでいた。しかし「NO HARD WORK!」は二年も前の本である。僕の「追っかけ」熱も冷めてしまったものだ…。

本書の感想を端的に言うと「いつもの Jason と DHH だな…」だ。率直なところ、これまでの Basecamp の本を読んでいれば、目新しい情報や主張は多くないと思う。

その中で少しだけ、かつての Basecamp と「主張が変わったなあ」と思うところを紹介しよう。Basecamp の昔の本である「小さなチーム、大きな仕事」には「けんかを売れ」と言う節があった。これは業界のトップブランドに対して「違いを打ち出して顧客を奪え」という主張であった。一方で、本書の「ハッピーな不戦主義者」では、「競合を意識してもしょうがない」というようなことを言っている。Basecamp も変わったものだ。僕は本書の主張の方が好みだ。

他に面白かったのは「Basecamp では、ユーザー数で課金しない」という話だ。「失う勇気」という章で書かれている。「ユーザー数で課金すると、大企業がクライアントになったときに大金を手にしてしまう。そのため、その企業の意向を無視できなくなってしまう」とのことである。この考え方はすごい。売上を (ある程度) あきらめることで、自由を手にしているわけだ。こういうポリシーで会社を運営できるのは強い。

「NO HARD WORK!」は楽しく読めたものの、やはり昔ほど Basecamp の本に入れ込めなくなってしまったように思う。ソフトウェア技術者として経験を積む中で、ある程度の諦観を持ったからかもしれない。ここで紹介されている素晴らしいノウハウを自社に持ち込むためには、他のメンバーにも同じ理解をしてもらう必要がある。これは容易ではない。たとえば「リアルタイムチャットは害悪である」という主張が本書にある。僕だけがこの主張に同意してもうまくいかない。他のメンバーにも同じように理解してもらえない限り「返事の遅い嫌なやつ」になってしまうだろう。しかし、Basecamp の主張は癖が強いので、僕の友だちの中にも「受け入れられない」と言う人もいる。なかなか実世界に Basecamp の考えをインストールするのは難しい。

現実的には、本書のエッセンスを汲んだ上で、役立つところだけを少しずつ組織に導入していくしかないのだろう (もしくは転職する)。

NO HARD WORK!

C 言語に対する畏敬の念、または C 言語コンプレックス

職業プログラマーを 15 年以上しているけれど、仕事で C 言語を書いたことがなく、C 言語に対して苦手意識を持っている。C 言語は高専および大学で習ったし、それらの教育機関で与えられた課題には C 言語で回答したものもあった。しかし、仕事ではスクリプト言語や JVM 言語 (Java や Kotlin) ばかり触れてきており、ついぞ C 言語を書かずにここまで来てしまった。

これまで、職業プログラマとしてはバックエンドのプログラムを書く他に、ミドルウェアの設定をすることも多かった。この記事の執筆時点で広く使われているミドルウェアの多くは C 言語もしくは C++ で書かれており、同僚の中にはミドルウェアの実装を深堀りして拡張したり、場合によっては開発者にパッチを投げてバグを改修する人もいた。僕は C 言語に対する苦手意識から、ミドルウェアの不具合を見つけても、ワークアラウンドを考えたり実装したりする程度で済ませてきた。こうして C 言語に対するコンプレックスをこじらせてきたのだ。

このコンプレックスを払拭したいと思う。

今後、いくつか C 言語の入門書を読みながら、しばらくブログに学習内容をメモ書きしていこうと思う。

このブログ記事はその決意表明である。

HTTP リクエストの実験用モックサービス

前回に続いて「達人プログラマー 熟達に向けたあなたの旅(第2版)」を読んでいて学んだことを書こうと思う。

今回は Reqres というサービスについてである。書籍の中で HTTP リクエストを実行するサンプルで叩かれていたのがこのサービスだ。ここでは色々な HTTP リクエストに対してダミーのデータを返してくれる。

例えば次のようにリクエストできる:

$ curl -s -X GET https://reqres.in/api/users | jq '.data[].email'
"george.bluth@reqres.in"
"janet.weaver@reqres.in"
"emma.wong@reqres.in"
"eve.holt@reqres.in"
"charles.morris@reqres.in"
"tracey.ramos@reqres.in"

また、同じエンドポイントに対するリクエストであっても、例えば POST: /api/register は渡すデータによって 200 だけでなく 400 が返ったりする。単にモックとして振る舞う HTTP サーバーがほしいときには便利だと思う。ダミーデータつきの httpbin だと考えればよさそう。

達人プログラマー 熟達に向けたあなたの旅(第2版

ビッグ・オー記法で log の底を無視する理由

達人プログラマー 熟達に向けたあなたの旅(第2版)」を読んでいたら、中の「練習問題」に次のようなものがあった。

(少し原文と変えてある) ビッグ・オー記法において対数の底は無視してよいと述べました。その理由を説明できるでしょうか?

ビッグ・オー記法では係数を無視して良いことは知っているし、最も次数の大きい項のみを考え、その他は無視して良いとも知っていた。でも、log の場合はどうだろう…。僕はこの練習問題にうまく答えられなかった。

書籍の中で、練習問題の答えとして紹介されていたのは次のような内容だ。

対数の底 ab に変換する式は次の通りである。

$$ \log_b(x) = \frac{\log_a(x)}{\log_a(b)} $$

このとき:

$$ {\log_a(b)} $$

…は定数であるため、無視してもよい。したがって、対数の底はビッグ・オー記法において無視して良い、とのことであった。

なるほど。

達人プログラマー 熟達に向けたあなたの旅(第2版

ファイル内からランダムに一行を取り出す

あるファイルの中からランダムに一行を取り出したいとしましょう。この目的のために便利なのは shuf です。shuf は多くの Linux 環境にインストールされているものですが、macOS では coreutils をインストールすることで (e.g., brew install coreutils) shuf 同等の機能を持つ gshuf をインストールできます。この記事では gshuf を使います。

次の内容の a.txt というファイルがあるとします。

$ cat a.txt
あい
うえ
お

このファイルの各行をランダムにシャッフルするために gshuf を使えます。

$ gshuf a.txt 
うえ
お
あい

(実行するたびに結果は変わります)

gshuf でファイルの各行をランダムに並び替えられるので、| head -n 1 を後ろに置くだけでランダムな一行を取り出せます。

$ gshuf a.txt | head -n 1
お

Git で複数のローカルブランチを一度に削除する方法

Git のローカルブランチが複数あるとします。たとえば次のような状態です。

$ git branch
  FOOBAR-4714/hotfix-dummy
  FOOBAR-4714/dummy-custom-metrics
  FOOBAR-4714/patch-dummy
  FOOBAR-4714/feature-dummy
* master

ここで、 FOOBAR-4714/* を全て削除したいとしましょう。もっとも単純な方法は git branch -D FOOBAR-4714/... と何度もコマンドを実行することです。この例のように対象となるブランチが 4 つ程度であれば、それでもよいでしょう。しかし、これがさらに増えると面倒な作業になります。

残念なことに、ワイルドカードによるブランチの指定は git branch --list ... などには使えるものの、git brranch -D ... には使えません。したがって、ワイルドカードを使ってブランチを一括削除するためには、git branch --list ...git branch -D ... を組み合わせることになります。

上記の例では、次のようにすることで、FOOBAR-4714/* を全て削除できます。

$ git branch --list 'FOO-BAR-4714/*' | xargs -n 1 git branch -D 

xargs -n 1 により、パイプから渡された結果を一行ずつ git branch -D に渡すことができます。