宮崎市定『アジア史論』が超面白かった
戦後日本を代表する東洋史学者が、西はシリアから東は日本まで含めたアジアを中心に世界史を論じる。文明間の交通を軸に話を進めるのでとにかくダイナミック。
シリアが古代より世界のハブだった、とか、プロテスタントの改革は既にイスラム教が成し遂げていたスキームの横展開だったとか、中世は近代のための準備期間だった、とか。中世に成功しすぎたイスラム世界は、その成功が故に没落も悲惨だった、とか。今のイスラム世界の辛い感じを見てどう思うんだろうな。
僕はウォーラーステインをちゃんと読んでないんだけど、その影響を受けたと思しき人の本を読む感じだと、とても似ているように思う。ということでニーアル・ファーガソン、水野和夫あたりが好きな人はハマるはず。
以下、面白い所を抜書き
p.8
また文化の影響ということが、いつも清水の中にインキを垂らしてこれを染めるようにばかり行われるとは限らない。人類は叡智を持った生物なので一を聞いて十を知り、単にヒントを与えられただけで奥義を悟ることがあり得る。
p.37
所詮、イスラム教とキリスト教との間には近世と中世との相違が横たわっていた。ルーテルの宗教改革こそは、中性的キリスト教をして近世的水準にまで向上させようとする運動に外ならなかった。そしてその説くところはと見れば、進行の根拠を根本経典たる『聖書』に求めようとし、聖徒の軌跡を含む一切の迷信を排斥し、僧侶は単に宗教的知識の宣布者たるべくして進行の媒介者であってはならず、また彼らの結婚生活を承認すべし等と説く。それらの事柄は、いずれもそのの規範を当時のイスラム教に見出すことが出来る。
p.74
『論語』や『孟子』はその主人公の伝記の一部分として歴史的に読むべきものであろう。(中略)現今の時勢にも間に合う所だけ読んで利用しようというのでは意味をなさぬ。それでは鏡に向かって、自分の姿のある角度だけを移すのと変わらない。
p.293
一個の閉ざされたる社会における平和の維持し難きは、一個人の閉ざされたる平和の維持し難きと同断である。これは倫理でもなく、道徳でもなく、ただ歴史が教うる現実なのである。
p.318
一般的に言って好条件は複雑な条件の結合の中から生れる。何とと言っても、手持ちの駒が豊富なでなければ完璧な布陣はできないものだ。そして豊富な持駒は、狭い局地で取り揃えることはできにくい。一番いいのは公益だ。交易ほど経済的で効果的なものはない。
ニューヨークにいる / Visiting New York City
仕事でニューヨークに滞在しています。3/13まで。 ブルックリン、ウィリアムズバーグの北にある、グリーンポイントという街でシェアハウスを借りた。元々ポーランド人街なので、ポーランド系のスーパーとかレストランがある。あと、TØRSTという素晴らしいビアバーがある。
予定としては
Darkside NYCのライブ
1349のライブ
SteffiとDVS1の出るパーティー
Rust-NYC
New York Haskell Users Group
あたりに行きます。
I'm now visiting New York. It's a business trip. Will back to Tokyo Mar 13.
My house for this visit is at Greenpoint, Brooklyn. This is a Polish town. I should have a try some Polish food. Also I found outstanding brew pub called TØRST.
My plans:
Show: Darkside NYC
Show: 1349
Party: Steffi and DVS1
Meetup: Rust-NYC
Meetup: New York Haskell Users Group
ミラン・クンデラ『冗談』
年明けすぐのマニラへの出張で読もうと思って持ってバッグに入れていきました。
行きの飛行機で引き込まれ、マカティの若干黴臭いホテルの部屋でサン・ミゲルを飲みながら読みふけり、帰国してすぐ自分の部屋で読了。
最後のページで全てが完成する。作品としてのあまりの美しさに感動して、しばらく言葉が出なかった。僕が今まで読んだ小説の中でも最高のものの一つでした。
あまりに印象に残る箇所が多かったので、抜き書きをしました。しかし、僕の抜き書きを見てしまうことで、それぞれと正しい形で、つまり作品の中で出会うという、人生で一度しかない機会を奪ってしまうという事は、凄まじい罪悪に感じられます。このインスタグラムの下から抜き書きです。見るのは読了後でお願いできればと…。
p.58
いくつもの顔をもっていたのは私が若かったからで、じぶんが何者で、どういう人間になりたいのかじぶんでもわからないからだった。
p.58
愛というものの心的・身体的な機制は複雑極まるものだから、若い男は人生の一時期、もっぱら自力を集中しなければならない。そのため愛の対象、つまり愛する女性を取り逃がしてしまう(これはちょうど、若いヴァイオリン奏者が演奏中に指使いのことを考えなくてもいいほど達者にならないかぎり、作品の内容に集中できないのと同じことだ)。
p.124
それから彼女は手を上げたのだが、その上げ方と言えば、これまで一度もそんな仕種をしたことがなく、どうやっていいのか分からないのに、ただ別れのしるしに手を振ることだけは知っていて、不器用ながらもそんな動作をしてみようと決心した人のようだった。
p.138
おのれの悲惨を自覚したところで、それで同類達の悲惨との和解が生じるわけではない。めいめいが他人のうちにみずからの卑俗さを見て仲よくするときほど、嫌なことはない。私はそんなべたついた友愛をどう扱っていいのかわからないのだ。
p.216
「王様!あんたには眼は要らないさ!おれが全部話してやる」
p.303
新聞はかさばらず、なんならゴミ箱に捨てることだってできる。同じようにつまらないものでも、ラジオにはそのような情状酌量の余地はない。カフェやレストランにまで私たちを追いかけてくるばかりか、耳に絶え間なく音の栄養をあたえないと、生きている気がしない人々の家を訪問しても変わりないのだ。
p.390
手に持ったカンテラを激しく振りかざしながら海岸をうろつく者がいれば、それは精神が錯乱した人間かもしれない。しかし夜、針路を失った小舟が大波に弄ばれるときなら、その者は救い主になる。
p.474
延期された復讐は奸計に、個人の宗教に、神話に変わり、日に日に当事者自身から離れていく。当事者たちは復讐の神話のなかで不変でも、じっさいには(動く歩道はたえず動いているから)、もはや以前の彼らではなくなっている。
新しいリリースプロセスをデプロイした
今やっているサービス、ちょっと障害が増えてきたので、リリースプロセスを変えました。
ざっくり言うと、今までmaster
を全部デプロイしていたのを、金曜日以外の毎日一回、手動の確認をしてリリースするようにした。実際のドキュメント(Wikiです)を日本語にしてダイジェストで紹介してみようと思います。
ちなみにこのサービスは複数のアプリケーションがあって、今回対象にしたのはそのうちの主要な3つのみです。
ブランチ戦略
develop
を本流として、そこにトピックブランチからプルリクエストを出す。master
は常に本番環境に自動的にリリースされる*1- 急ぐときはHotfixとして
master
に直接プルリクエストを出してもOK*2。
リリース手順
- HipChatで「リリースするよ」ってアナウンスする
develop
からmaster
にプルリクエストを出す- 手作業でテストして、チェックリストを埋める
- 問題があったら課題管理システムに起票
- 凄いやばそうな問題があったら相談する
- プルリクエストをマージして本番環境にリリースする
- HipChatで「終わった」ってアナウンスして終わり
リリースチームについて
- 開発者&非開発者のペアを一週間でローテーション
- リリース体制自体を担当する開発者&非開発者が一人づつ*3
- リリースのない金曜日はプロセスのふりかえりをする
- リリースは開発者ではなく、非開発者が主導
経緯と歴史
複数アプリケーションにまたがるEnd to endテストをやりきれないのと、テスト対象以外の障害やイケてないところを検知できるっていう手作業のメリットを享受したいな、といったあたりが理由です。 もちろん全部自動化したいんですが*4、このタイミングでは手動のリリースプロセスを導入するのがコスト的にもサービスの品質向上という面も良さそうでした。
ちなみにこのプロセスは以前別のプロジェクトでやっていたものをちょっと変えただけ。そのプロジェクトでうまく行った実績があったので、ある程度自信を持って進められた。
2014年12月の前半くらいに他の仕事をしつつプランニングと制度についてふんわりと考え始めました。先述のプロジェクトでやっていたことをざっと文書化してそれを元に相談しつつ、12月半ばくらいから周知を開始。フィードバックがあった部分や不足していた部分を詰め、自動化とChatOpsの仕組みなどを調査・整備、年明けにやわらかい状態でスタート。そこから一週間で一気に制度としくみを詰めた感じです。 まだ詰め切れてない部分はあるものの、走りながら治せる程度にまとまりました。
やってみて思いますが、サービスの事をよく知ることができる、改善点が見つかる、など、手動のテストにも特有のメリットがありますね。今更ではありますが。実は全体のEnd to endテストもあるので*5、今後はそれをこのプロセスに組み込んで機械と手作業それぞれの良さを活かせる仕組みにしたいなーと思ってます。
2014年
後20時間ちょいしかない。表面的に振り返ってみようと思います。
仕事
今年は、大規模なアライアンスプロジェクトの開発リーダーを中心に、人事、採用、開発、体制の整備などに加えてBiz Dev的な活動にも参加するようになった。気がつけば自分でコード書いてない、って日もだんだん出てきた。大人力がコア・コンピタンスになりつつあるのはプログラマーとしては悩ましい事態だけど、今の会社では必要なことをなんでもやるつもりでいるので、まあ良し。
オープンソース
ライブラリ
fujimura/hi · GitHub
Haskellのプロジェクトを生成するやつ。cabal init
だと、ちょっと足りないので作った。今日時点で119star。海外のブログで言及されることも何度かあった。ちょっと飽きてきた。そろそろ1.0.0が出せそう。
hspec/hspec-wai · GitHub
WAI(HaskellのRack)のアプリケーションをHspecでテストできるようにした。元々サンプルアプリだったのをライブラリ化した。というかHspecの作者Simonさんがライブラリ化してくれた、が正しいかも。残念ながら僕は個人でも仕事でも使ってないけど、Zaloraでは使われてるらしい。
fujimura/git-gsub · GitHub
git-grep
とsed
を組み合わせリポジトリ内の文字列置換するのをGem化した。今やこれなしでは生きられぬ。
fujimura/git-freq · GitHub
Gitでどのファイルが頻繁に変更されてるか出すCLI。使うより作るほうが楽しかった。
主なPull request
マージされたのはここらへん。Cabalにコントリビュートできたのは結構うれしい。全体に雑で手間をかけちゃってるので反省している。gulp-purescriptとか完全に自分でも忘れていた。
- Ask source directory in cabal init by fujimura · Pull Request #1989 · haskell/cabal · GitHub
- Add conversion function which cares about bounds by fujimura · Pull Request #16 · basvandijk/scientific · GitHub
- Extract result handling from execParser by fujimura · Pull Request #94 · pcapriotti/optparse-applicative · GitHub
- Support output directry also for `psc` by fujimura · Pull Request #3 · purescript-contrib/gulp-purescript · GitHub
- Create output file by gulp, not `psc` command by fujimura · Pull Request #4 · purescript-contrib/gulp-purescript · GitHub
ここらへんは放置中。JSONとBSONの規格を調べたりして楽しかった。
- https://github.com/mongodb-haskell/mongodb/pull/8
- Allow aeson >= 0.7 by fujimura · Pull Request #5 · nh2/aesonbson · GitHub
今年の一曲
Leo Anibaldi - Elements - Italian House - ACV 1991 - YouTube
このミックスの1曲目。マニラの空港で飛行機を待っている時に初めて聞いた。ディープハウスと旅は合う。合いすぎる。このミックスはその後も何度も聞いた。
Bodytonic Podcast - Murat Tepeli by Bodytonicmusic - Hear the world’s sounds
来年は「いい一年だったね!」って言って年を越せるといいな。
Haskellでコマンドラインアプリケーションを作る時の基本的な情報とTips
Haskellでコマンドラインアプリケーション(以下CLI)を作る時の基本的な情報とTipsをまとめてみました。 Haskellは雰囲気で読める、しかしCLIはあまり作ったことが無い、って人が想定読者です。
この記事はHaskell Advent Calendar 2014の16日目のエントリです。
とりあえず何のサンプルコードも無く話を進めるのも雰囲気が伝わらないかなと思って、Gitリポジトリにあるファイルの中身を標準出力に出力するプログラムをls-more
という名前で作ってみました。
module Main where import Control.Monad import Data.Monoid import qualified Data.Version import Options.Applicative import Paths_ls_more (version) import System.IO (Handle, hGetLine, hIsEOF) import System.Process (runInteractiveProcess) data CommandLineOption = CommandLineOption { showVersion :: Bool -- バージョンを出力 , show3Lines :: Bool -- 3行だけ出力 } commandLineOption :: Parser CommandLineOption commandLineOption = CommandLineOption <$> switch ( long "verion" <> short 'v' <> help "Show version" ) <*> switch ( long "show-3-lines" <> short '3' <> help "Show 3 lines only" ) main :: IO () main = do -- コマンドラインオプションパーサーを実行してオプションを取得 opts <- execParser (info commandLineOption mempty) -- バージョンを出すか、実行するかで分岐 if showVersion opts -- バージョンを出す then putStrLn $ Data.Version.showVersion version else do -- `runInteractiveProcess`で実行した外部プロセスの標準出力を受け取る (_,out,_,_) <- runInteractiveProcess "git" ["ls-files"] Nothing Nothing -- 本処理へ go opts out where go :: CommandLineOption -> Handle -> IO () go opts handle = do -- ファイル末尾か判定 eof <- hIsEOF handle if eof then return () else do -- 一行読む path <- hGetLine handle --- ファイルの中身を読む content <- readFile path -- ファイルパスを出力 putStrLn path if show3Lines opts then -- 3行だけ出力 forM_ (take 3 (lines content)) putStrLn else -- すべて出力 putStrLn content -- 次へ go opts handle
いかがでしょうか。冒頭にこのサンプルコードを置く意味がどの程度あったのかという問いを放置しつつ、箇条書きでCLIを作る際に必要な情報をまとめていこうと思います。
ファイルの読み書き
Prelude
にreadFile
、writeFile
など基本的な関数があります。ByteString
、Text
向けにも同じインターフェイスの関数が用意されています。
- http://hackage.haskell.org/package/base/docs/Prelude.html
- http://hackage.haskell.org/package/bytestring/docs/Data-ByteString.html
- http://hackage.haskell.org/package/bytestring/docs/Data-ByteString-Lazy.html
- http://hackage.haskell.org/package/text/docs/Data-Text-IO.html
- http://hackage.haskell.org/package/text/docs/Data-Text-Lazy-IO.html
ディレクトリ操作
System.Directory
を使います。
ファイルパス
System.FilePath
を使います。
ドキュメントはSystem.FilePath.Posix
とSystem.FilePath.Windows
に分かれていますがインターフェイスは同じです。
- http://hackage.haskell.org/package/filepath/docs/System-FilePath-Posix.html
- http://hackage.haskell.org/package/filepath/docs/System-FilePath-Windows.html
外部プロセスの呼び出し
System.Process
を使います。readProcess
、readProcessWithExitCode
を使うことが多いような気がします。
結構前の話ですがsystem
が1.2.0.0で非推奨になってしまいました。よく使う関数だったので衝撃です。今後はcallCommand
を使えば良いみたいです。
文字列操作
真面目にHaskellのプログラムを書いていると、ユニコードの文字を出力する必要がある、遅い、などの事情で素のString
ではなくByteString
とText
を使うことになると思います。「ファイルの読み書き」にも書きましたが、この2つのライブラリははPreludeと同じインターフェイスの関数を多く装備していて、それを使うとByteString
/Text
の文字列もリスト操作感覚でいじることができます。
終わり方
exitSucess
/ exitFailure
が System.Exit
にあります。
標準入出力
getChar
、getLine
、getContents
など基本的なものはPrelude
にあります。さっきのサンプルプログラムにあるようにHandle
を指定するなどの場合はSystem.IO
にあるh
で始まるものを使います。
これもByteString
/Text
に同様の関数があります。
- http://hackage.haskell.org/package/base/docs/Prelude.html
- http://hackage.haskell.org/package/bytestring/docs/Data-ByteString.html
- http://hackage.haskell.org/package/bytestring/docs/Data-ByteString-Lazy.html
- http://hackage.haskell.org/package/text/docs/Data-Text-IO.html
- http://hackage.haskell.org/package/text/docs/Data-Text-Lazy-IO.html
今回は省略を省きますが、conduit
、pipes
、io-streams
等のストリーム処理ライブラリを使うのも良いと思います。
- http://hackage.haskell.org/package/conduit
- http://hackage.haskell.org/package/pipes
- http://hackage.haskell.org/package/io-streams
コマンドラインオプションは?
沢山ライブラリがあります。optparse-applicative
がおすすめです。APIの変更が若干激しい、ドキュメントが読みづらい等欠点はありますが使いやすいライブラリです。
- https://www.haskell.org/haskellwiki/Command_line_option_parsers
- https://github.com/pcapriotti/optparse-applicative
同梱したファイルを使いたい
.cabal
ファイルのdata-files
プロパティで同梱するファイルを指定できます。
このようなパッケージ固有の情報はPaths_pkgname
というモジュールから読めます。同梱ファイルのパスはgetDataFileName
で取得できます。
バージョンを出したい
サンプルコードにある通り、
import Paths_pkgname import Data.Verison (showVersion)
して、 showVersion Paths_pkgname.version
で取得できます。
設計
個人的には下記のような構造に落ち着きました。各工程をテストできるのが良いです。 実際はもうちょっとグチャグチャになります。
-- コマンドラインオプションを生成 parseArgs :: [String] -> CommandLineOption -- コマンドラインオプションからオプションを生成。 -- 環境変数などはここで読んで、オプションを完成させる buildOption :: CommandLineOption -> IO Option -- オプションから処理を実行。 run :: Option -> IO () -- 各部品をつなげる。 main = (parseArgs <$> getArgs) >>= buildOption >>= run
おわりに
HaskellでCLI作るの楽しいです。相性良い気がします。是非お試しを!
追記
バージョン情報が無かった。各ライブラリは2014/12/16時点で最新のものを使っています。
$ ghc --version The Glorious Glasgow Haskell Compilation System, version 7.8.3 $ cabal --version cabal-install version 1.20.0.3 using version 1.20.0.2 of the Cabal library
Tools for trade Late 2014
OS and Application
- MacBook Pro 15inch
- Mac OS X
- Terminal.app
- MacVim.app
- Divvy.app
- Karabiner.app
- LICECap.app
- Writer Pro
- Spotlight as a launcher
CLI
Zsh
- Colorful prompt
- Path and Git branch on the right
- Cabal sandbox status
- Lots of one character aliases
Vim
- vimrc is about 250 kloc
- ctrlp, syntastic, gitgutter, vim-align
- Just omni complete
- Wrap parens
- Emacs keybind in insert mode
- Warnings for whitespace etc.
- Search with /
Git
$ g
forgit
$ s
forgit status --branch --short
$ d
forgit diff
- Commit is always verbose to write good commit comment
$ git fixup
to amend staged changes to previous commit- Heavy user of
git-grep
with these options
Custom defined Git commands
$ git tb
to create topic branch named by last commit$ git gsub
for substitution. I can't write code without this now
Repository management
$ r (repo url)
to clone a repository$ r (repo name)
to move to the cloned repository$ r \TAB
to auto complete repositories$ r \ENTER
to intaractive selection of repository