2011-11-01 (Tue) [長年日記]
_ QE-PL201-K購入
Panasonic USB対応モバイル電源パック リチウムイオン5400 ブラック QE-PL201-K
RubyConf Argentina / Uruguayに向けて、Xperia arcの充電用に購入。
ロゴはPanasonicだけど、モバイルブースターとあんまり変わらないような気がする。中身は同じなのかな、これ。 1.5A出力だけあって、充電が早い気がする。またコードが増えて邪魔くさいけど、無接点充電に対応しているらしい。 対応機器がないから使ったことないけど、今度空港のANAラウンジで試してみよう。
あと、Amazonのプライム会員のお試しで注文したら、翌日の朝に着いた。島根なのに。 便利だけど無料期間は1か月らしいので、登録解除を忘れないようにしよう。
2011-11-08 (Tue) [長年日記]
_ RubyConf Argentina発表
RubyConf Argentinaで発表したよ!、と書く予定だったが、出発2日前に次女が熱傷で入院してしまい、行くことができなくなった。 代りに私の資料でyhara先生が発表してくれた。yhara先生、ありがとうございました。
一応資料を公開しておく。
本番ではノートが表示できなかったそうなので、かなりyhara節になっていたものと推測される。どんな内容だったんだろうなあ。動画とか公開されないの?
2011-11-11 (Fri) [長年日記]
_ MIMEメッセージから添付ファイルを抽出する
Apple Mailから送られて来るMIMEメッセージをなぜかWanderlust(というかSEMI)が上手く処理してくれないので、 Rubyで添付ファイルを抽出することにした。 最近はmailというgemパッケージを使うのがいいのかな?
#!/home/shugo/local/bin/ruby-trunk
require "mail"
mail = Mail.read(ARGV[0])
mail.attachments.each do |att|
if File.exist?(att.filename)
STDOUT.print("Overwrite #{att.filename}? (y/n): ")
STDOUT.flush
unless /^y/i.match(STDIN.gets)
next
end
end
File.binwrite(att.filename, att.decoded)
puts("extracted #{att.filename}")
end
File.binwriteを使っているので、Ruby 1.9.3でないと動かない。
_ 次女の熱傷の経過
入院から8日が経過して、脚の方はかなり良くなっているが、腕の方があまりよくないらしい。 主治医の先生の話では、あと二週間で治らなければ手術になるとのこと。こんなに元気なのに。 他の場所から皮膚を移植することになるのでますます跡が広がるようだ…。
色々調べると湿潤療法という治療方法があるらしく、松江では市立病院の岡先生が熱傷の湿潤療法をされているらしい。 明日主治医の先生に湿潤療法について聞いてみようかなあ。
何か有用な情報があったら教えてください。
2011-11-12 (Sat) [長年日記]
_ 関数プログミングの楽しみ
湿潤治療の本を買うために今井書店に行ったら関数プログラミングの楽しみが置いてあったので、つい購入してしまった。 Richard S. Birdの還暦を記念して、色々な著者が関数プログミングの楽しみについて綴っている。 Introduction to Functional Programming using Haskell (IFPH)の続編という位置付けらしいが、IFPHを持ってなくても一応読める。
以下は、サポートサイトを参考に第1章の最大回避ヒープの練習問題を解いたもの(ほとんど写経)。
import qualified Data.Tree as T
data (Ord a) => Tree a = Null | Fork Int a (Tree a) (Tree a)
drawTree :: (Ord a, Show a) => Tree a -> String
drawTree = T.drawTree . conv
where
conv Null = T.Node "Null" []
conv (Fork n x a b) = T.Node (show x) (map conv [a, b])
instance (Ord a, Show a) => Show (Tree a) where
show = drawTree
isEmpty :: Ord a => Tree a -> Bool
isEmpty Null = True
isEmpty (Fork n x a b) = False
minElem :: Ord a => Tree a -> a
minElem (Fork n x a b) = x
deleteMin :: Ord a => Tree a -> Tree a
deleteMin (Fork n x a b) = merge a b
insert :: Ord a => a -> Tree a -> Tree a
insert x a = merge (Fork 1 x Null Null) a
merge :: Ord a => Tree a -> Tree a -> Tree a
merge a Null = a
merge Null b = b
merge a b
| minElem a <= minElem b = join a b
| otherwise = join b a
join :: Ord a => Tree a -> Tree a -> Tree a
join (Fork n x a b) c = Fork (n + size c) x aa (merge bb cc)
where (aa, bb, cc) = orderBySize a b c
orderBySize :: Ord a => Tree a -> Tree a -> Tree a -> (Tree a, Tree a, Tree a)
orderBySize a b c
| size a == biggest = (a, b, c)
| size b == biggest = (b, a, c)
| size c == biggest = (c, a, b)
where biggest = size a `max` size b `max` size c
size :: Ord a => Tree a -> Int
size Null = 0
size (Fork n x a b) = n
exercise121 = foldr insert Null [1..7]
exercise122 = foldl (flip insert) Null [1, 7, 2, 6, 3, 5, 4]
exercise123 = deleteMin $ foldl (flip insert) Null [1..7]
main = do putStrLn("1.2.1:")
print exercise121
putStrLn("1.2.2:")
print exercise122
putStrLn("1.2.3:")
print exercise123
本当は頭の中で解くことを意図してる気もするけど…。
Rubyだと何でも配列やハッシュで済ませてしまうので、便利ではあるんだけど、あまりこういう楽しみは味わえない。
同じ著者のPurely Functional Data Structuresが欲しいと思いつつ、洋書高いしなあと躊躇していたのだが、意外と『関数プログラミングの楽しみ』の方が高かった。 でもその価値はあると思う。
2011-11-14 (Mon) [長年日記]
_ 次女の治療方針
次女の治療方針について主治医の先生の話を聞いた。 その話では、まだ手術が必要と決まったわけではなく、2週間後までに治らないようであれば、という話とのことで、急に手術と言われても困るだろうから事前に少しずつ説明をしているということだった。 2度の熱傷でも深い方で、話を聞いた印象としては手術が必要な可能性は五分五分くらいという感じ。
湿潤治療についても聞いてみたが、「今やっていることだ。乾燥させてかさぶたを作るわけでなく、適度なうるおいを保つようにしている。完全に閉鎖すると感染の畏れがある。」というだいたい想定どおりの回答。たぶん何回か同じ質問を受けているのだろう。
包帯交換の時の処置方法を観察していると、
- 患部を水で洗う
- 網状のガーゼ(?)で患部を覆う
- ワセリンを塗る
- ガーゼで患部を覆う
- 包帯を巻く
という手順のようだ。湿潤治療のサイトや本で紹介されている感じとは異なるが、消毒を使ってないのと、クリーム系の軟膏でなくワセリンを使っていることから、それほど大きな違いはないように感じた。何より、処置中に娘が痛がっていないし、処置が終わった後も痛がる様子が見られないのは安心材料だと思う。 また手術についても、100%リスクがないとはいえないので手術しないで済めばそれにこしたことはない、という率直な話を聞くことができた。 主治医の先生自身も生後10か月くらいの時に熱傷を受けて今も左腕にその痕が残っていて、患者の立場で考えてもらっているように思う。
とりあえず、しばらくこのまま様子を見ることにしたい。
2011-11-25 (Fri) [長年日記]
_ RailsによるアジャイルWebアプリケーション開発第4版
やっと自分の手元に届いた。内容はもうPDFで見てるので、感想としては「(物理的に)薄くなったなー」ということに尽きる。 第3版と比べると、よく広告とかで見るダイエット前・ダイエット後という感じ。
その分1000円ほどお求めやすくなっていますので、ぜひお買い求めください。Amazonで予約できます。
たぶん、早いところでは11月中に書店にも並ぶのではないかと。
2011-11-29 (Tue) [長年日記]
_ RubyとHaskellによる簡単なCSVファイルの集計
簡単なCSVファイルの集計をHaskellでやろうと思ったら結構大変だったのでメモ。 IO返す関数をはじめて書いた気がする。
問題
以下のような形式の複数のCSVファイルをコマンドライン引数で受け取り、Applicant Nameごとに得点を集計して、合計得点でソートした結果を出力する。
Applicant Name,Project Title,Productivity and performance,Originality and creativity,Feasibility,Jadges point,Comment Shugo Maeda,Introducing list comprehensions into Ruby,5,1,7,3,面白いけど必要ないと思います。 ...
Ruby版 (30行)
Haskellで書こうと思ったけど手が出なかったので、とりあえずRubyで書いた。 色々やり方はあると思うけど、なるべく副作用を使わないやり方で。 flat_map便利。
class Assessment < Struct.new(:applicant, :title, :productivity, :originality, :feasibility, :judges_point)
def +(other)
self.class.new(self.applicant, self.title,
self.productivity + other.productivity,
self.originality + other.originality,
self.feasibility + other.feasibility,
self.judges_point + other.judges_point)
end
def total
productivity + originality + feasibility + judges_point
end
def to_s
[*to_a, total].join(",")
end
end
assessments = ARGV.flat_map { |path|
File.read(path).lines.reject { |line|
/^Applicant Name/.match(line)
}.map { |line|
fields = *line.split(/,/)
Assessment.new(*fields[0, 2], *fields[2, 4].map(&:to_i))
}
}.group_by { |a| a.applicant }.flat_map { |k, as|
as.inject(&:+)
}
puts "Applicant Name,Project Title,Productivity,Originality,Feasibility,Judges Point,Total"
puts assessments.sort_by { |i| -i.total }
Haskell版 (96行)
Ruby版を参考に悩みながら書いたのが以下。
import List
import Data.Ord
import IO
import System.Environment
import Text.ParserCombinators.Parsec
data Assessment = Assessment {
applicant:: String,
title :: String,
productivity :: Int,
originality :: Int,
feasibility :: Int,
judgesPoint :: Int
}
instance Show Assessment where
show a = case a of
(Assessment applicant title
productivity originality feasibility judgesPoint)
-> applicant ++ "," ++ title ++ ","
++ show productivity ++ "," ++ show originality ++ ","
++ show feasibility ++ "," ++ show judgesPoint ++ ","
++ show (totalPoint a)
totalPoint :: Assessment -> Int
totalPoint (Assessment applicant title
productivity originality feasibility judgesPoint)
= productivity + originality + feasibility + judgesPoint
aplus :: Assessment -> Assessment -> Assessment
(Assessment a1 t1 p1 o1 f1 j1) `aplus` (Assessment a2 t2 p2 o2 f2 j2)
= Assessment a1 t1 (p1 + p2) (o1 + o2) (f1 + f2) (j1 + j2)
text :: Parser String
text = many $ noneOf ","
point :: Parser Int
point = do s <- char '-'
return 0
<|> do s <- many digit
return $ read s
record :: Parser Assessment
record = do a <- text
char ','
t <- text
char ','
p <- point
char ','
o <- point
char ','
f <- point
char ','
j <- point
return $ Assessment a t p o f j
parseLine :: String -> [Assessment]
parseLine line
= case (parse record "" line) of
Left err -> []
Right a -> [a]
linesToAssessments :: [String] -> [Assessment]
linesToAssessments = concatMap parseLine
rejectHeaders :: [String] -> [String]
rejectHeaders = filter $ (not) . isPrefixOf "Applicant Name"
sortByApplicant :: [Assessment] -> [Assessment]
sortByApplicant = sortBy $ comparing applicant
groupByApplicant :: [Assessment] -> [[Assessment]]
groupByApplicant = groupBy $ \x y -> applicant x == applicant y
sumAssessments :: [[Assessment]] -> [Assessment]
sumAssessments = map $ foldl1 aplus
sortByTotalPoint :: [Assessment] -> [Assessment]
sortByTotalPoint = sortBy $ comparing (negate . totalPoint)
assessmentSummary :: [String] -> [Assessment]
assessmentSummary = sortByTotalPoint . sumAssessments
. groupByApplicant . sortByApplicant
. linesToAssessments . rejectHeaders
readLines :: FilePath -> IO [String]
readLines path = do h <- openFile path ReadMode
cs <- hGetContents h
return $ lines cs
main = do paths <- getArgs
liness <- sequence (map readLines paths)
let lines = concat liness
let summary = assessmentSummary lines
putStrLn "Applicant Name,Project Title,Productivity,Originality,Feasibility,Judges Point,Total"
sequence_ (map print summary)
色々ハマったけど、以下のことを学んだ。
- Parsecで/[^,]*/相当のことはmany (noneOf ",")と書ける。
- sequenceでIOのリストからアクションの実行結果のリストを得られる。結果が要らない場合はsequence_でOK。
- sortByはRubyのsort_byではなくsort {|x,y|...}相当。Data.Ord.comparingを使うとsort_byっぽく書ける。
残った疑問。
- comparingの==版はないのか? equalingみたいな。
- Rubyのsort_byみたいにSchwartzian Transformをやってくれる関数はないのだろうか。Haskellだと比較関数が速いからいらない?
- getArgsからlinesを得るまでの流れをもっとスマートに書けないだろうか。
- ファイルのクローズはどのタイミングでやればいいの?
- というか、そもそもHaskellでこういうコードを普通はどう書くの?
_ ujihisa [ liness <- sequence (map readLines paths) ..]
_ ujihisa [ sequence_ (map print summary) は mapM_ print summ..]
_ akr [CSV などの表をいじり回すコマンドを以前から作っていたりするのですが、 それを使うとこんなですかねぇ。 % ta..]
_ shugo [> ujihisaさん なるほど、fmapとかmapMを使うとすっきりしますね。たしかにたくさんモジュールをimp..]
_ ikegami__ [比較以外の部分を僕なりに書いてみました。質問は Twitter でいつでも聞いてください。 https://gist..]
_ ikegami__ [「Equaling」は (==) : Eq a => a -> a -> Bool のことかなあ、と考えました。co..]
_ shugo [ありがとうございます。 僕のHaskell力ではまだ読めませんが、すっきりしたコードですね。 Showはたぶんin..]
2011-11-30 (Wed) [長年日記]
_ コンピュータアーキテクチャのエッセンス
以下の文章は翔泳社の「君のために選んだ1冊 ソフトウェア開発の名著」という企画のために書いたものだけど、ブログに公開してよいとのことだったので、たぶんWeb日記でもよいだろうと思って公開しておく。 今気付いたけど、これソフトウェア開発の本じゃないね。
コンピュータアーキテクチャのエッセンス (IT Architects Archiveシリーズ)
僕がはじめてコンピュータに触れたのは小学生の頃で、ファミコンが欲しいと言っていたら親父がHB-55というソニーのMSXマシンを買ってきたのがきっかけだった。ゲームをやりたい一心で、雑誌に付いていたBASICのプログラムを意味もわからずに打ち込んだものだ。その後、PC-9801を親父が買ったりもしたが、ゲーム機兼ワープロとしてしか使わず、プログラミングを再びはじめたのは大学に入って東芝のBREZZAというPCを買ってからだった。といっても、大学で計算機科学を勉強していたわけではなく、当時は理学部の数学科で、計算機センターのNeXTというかっこいいコンピュータを使ってMathematicaをいじっていたりはしたものの、授業でプログラミングをする機会はまったくなかった。せめてそのときに数学をもっとちゃんとやっていたら今ごろ役に立っていたかもしれないが、もともと物理学科を志望していたのに入試の点数が足りなくてあまり興味のなかった数学科に入ってしまったものだから、途中でついていけなくなって文学部哲学科に転部して、プログラミングに関係のあるようなことは大学では結局何一つ学ぶことがなかった。
というわけで、専ら趣味でRubyなどをいじっていたのだが、当時大変な不況で文学部哲学科の学生によい就職先などあるはずもなく(本当は就職活動もろくにしていなかったので、探せばあったのかもしれないが)、何となくプログラミングを仕事にすることになってしまった。
長々と説明してきたが、言いたかったのは、要は、僕は計算機科学の専門教育を受けずにプログラマになってしまったということである。このことはその後の僕の人生に大きく影を落としている…というのはちょっと大げさだが、計算機科学の常識を知らないために、しなくてもよい苦労をしたのは事実である。
最近では僕のようにちゃんとした勉強もせずに何となくプログラマになってしまう人も結構多いようで、「専門教育なんて受けなくてもプログラムはちゃんと書けるよ」というような声も聞く。たしかに書けることは書ける。でも本当に「ちゃんと」書けているだろうか。特に、Rubyのような高級言語によって独学でプログラミングを勉強すると、低レベルな(というのはもちろんハードウェア寄りのという意味だが)知識が不足しがちなように思われる。例えば、Rubyのメーリングリストでは、「浮動小数点数の演算結果が期待と違うがRubyのバグではないか」といった質問が跡を絶たない。
「コンピュータアーキテクチャのエッセンス」は、そんな計算機科学の専門教育を受けていないプログラマに薦めたい一冊である。本書は、元々大学のコンピュータシステム論の教科書として執筆された書籍だが、ハードウェア設計者を目指す学生向けではなく、プログラマ向けに、コンピュータアーキテクチャの基本概念を説明するために書かれている。そのためか、本書の「推薦の辞」にもあるように専門家からは色々と突っ込みどころもあるようだ。本書は、電圧と電流の話からはじまって、論理回路、データやプログラムの表現、プロセッサ、アセンブリ言語、メモリ、入出力、並列化といった概念をわずか400ページほどでまとめている。当然個々の内容は薄くなりがちで、本書だけ読んでもよくわからないところが多いかもしれないが、コンピュータの全体像を掴むためにはこれくらいコンパクトな方がよいのではないだろうか。
本書のテーマの一つは抽象化である。ソフトウェアから見ると、ハードウェアというのは具体的なものに見えるが、実際にはハードウェアもソフトウェア同様に抽象化の階層を成している。そのことは、本書でも繰り返し言及されている。本書の内容の多くはプログラミングに直接役に立つものものではないかもしれないが、それはこの抽象化の階層によって、上位レベルの議論では下位レベルの詳細を気にする必要がないからである。しかし、下位レベルの知識を知った上で、敢えて意識の外に一時的に追い出すのと、そもそも知らないのとでは大きく異なる。ぜひ、本書を手がかりとしてコンピュータアーキテクチャの基本概念を学んだ上で、必要に応じて抽象化の階層を自由に行き来できるようになっていただきたい。僕もあなたに負けないように、これからも勉強して行くつもりである。
後書き
ちゃんと翔泳社の本を選んだし、実は、訳者の一人の鈴木先生は数年前に島大に赴任された方で、笹田さんの知人である。 もちろん、そういった気遣いだけで選んだわけではなく、いい本だと思うので読んでみてください。
あと、浮動小数点数演算の誤差の話に触れたけど、本書ではあまり細かい記述はないので、予備知識なしでこの本だけ読んでも理解できないと思う。 そういうわけで、この本だけ読んで何かの役に立つことはあまりないかもしれないけど、まあそれが教養というものですよね。
_ O-Show [湿潤療法という言葉は『傷はぜったい消毒するな 生態系としての皮膚の科学』という本で知りましたが、 それを読んだ限りで..]
_ shugo [ありがとうございます。 入院先の病院では実施されてない気がしますが、とりあえず相談してみます。]