2008年04月29日
「C#プログラミングレッスン」 C#3.0文法編
Gushwell's C# Programing Page --「窓際プログラマーの独り言」別館で、メールマガジン『C#プログラミングレッスン』のバックナンバー「C#3.0文法編」をダウンロードできるようにしました。
C#3.0で追加された、var変数、オブジェクト初期化子、匿名クラス、拡張メソッド、ラムダ式などの説明をしています。
現在は、LINQ to Objects について連載中です。
C#3.0で追加された、var変数、オブジェクト初期化子、匿名クラス、拡張メソッド、ラムダ式などの説明をしています。
現在は、LINQ to Objects について連載中です。
2008年04月27日
C#プログラミングレッスン・LINQ to Objects
メルマガの連載を休んでいる間に、LINQ to Objectsの記事を書き溜めておこうと思ったのですが、Haskellに夢中になっていて、書き溜めることができませんでした。orz
でも予定通り、今週メルマガの発行を再開しようと思います。
ご期待ください。
連載を休んでいる間も読者数が50人近くも増えており、嬉しいかぎりです。
でも予定通り、今週メルマガの発行を再開しようと思います。
ご期待ください。
連載を休んでいる間も読者数が50人近くも増えており、嬉しいかぎりです。
2008年04月26日
[Haskell] 型チェックは意外と厳しい
getAverage :: (Fractional a) [a] -> a
getAverage xs = div (sum xs) (length xs)
という関数を書いてみた。
最初の行では、aという型がFractionalクラスに属していることを示している。
Fractionalクラスは、小数点を扱える数値型。
でもなぜかコンパイルエラーになった。なんか型が一致しないようだ。
なぜ?
sum xs / (length xs)
って書いてもだめ。
調べてみると、この場合割り算の分子は、Fractionalである必要があるので、
fromIntegral で型変換をする必要がある。
getAverage xs = sum xs / fromIntegral (length xs)
C#のキャストのようなものかな。
Haskellの型チェックって見た目以上に厳しいようだ。
2008年04月23日
[Haskell] foldl関数の動き
Haskellのmaximum関数は,
という定義らしい。
ここで出てきた foldl1についても調べてみる。
foldl1の定義は、
だ。
重要なのは、
の部分。
という関数呼び出しのコードだと、
の値を新たな z ととし、xs を新たな第3引数のリストとし、再帰的にfoldlを呼びだすというものだ。
こうすることで、f の結果を保持しながら、リストを順に処理できることになる。
具体的に見てみよう。たぶん以下のように推移するんだと思う。
僕にはとても思いつきません。
maximum, minimum :: (Ord a) => [a] -> a
maximum [] = error "Prelude.maximum: empty list"
maximum xs = foldl1 max xs
という定義らしい。
ここで出てきた foldl1についても調べてみる。
foldl1の定義は、
foldl1 :: (a -> a -> a) -> [a] -> a
foldl1 f (x:xs) = foldl f x xs
foldl1 _ [] = error "Prelude.foldl1: empty list"
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
だ。
重要なのは、
foldl f z (x:xs) = foldl f (f z x) xs
の部分。
foldl func z (x:xs)
という関数呼び出しのコードだと、
func z x
の値を新たな z ととし、xs を新たな第3引数のリストとし、再帰的にfoldlを呼びだすというものだ。
こうすることで、f の結果を保持しながら、リストを順に処理できることになる。
具体的に見てみよう。たぶん以下のように推移するんだと思う。
maximum [1,5,3,4]
-> foldl1 max [1,5,3,4]
-> foldl max 0 [1,5,3,4]
-> foldl max (max 0 1) [5,3,4]
-> foldl max 1 [5,3,4]
-> foldl max (max 1 5) [3,4]
-> foldl max 5 [3,4]
-> foldl max (max 5 4) [4]
-> foldl max 5 [4]
-> foldl max (max 5 4) []
-> foldl max 5 []
-> 5
僕にはとても思いつきません。
2008年04月22日
[Haskell] 指定した長さより長い文字列を取り出す
標準入力から指定した長さよりも長い行だけを
標準出力へ複写するプログラムを書け。
このコードでのポイントは filter関数かな。
関数(ここではラムダ式)で与えた条件に一致するものだけを返す関数。
この場合は、文字列のリストから、長さが n 以上の文字列だけを
抜き出すというもの。
map と filterがあれば、随分といろんなことが出来そう。
C#のLINQではSelectとWhereに対応しているような感じですね。
main の do 記法は、いつもとちょっと変えて、{ } を使ってC#風に
書いてみた。
僕には、この方がしっくりきますね。
{ }を使わなければ、
標準出力へ複写するプログラムを書け。
main = do {
cs <- getContents;
args <- getArgs;
putStrLn $ unlines $ selectlines (read $ head args) $ lines cs
}
selectlines :: Int -> [String] -> [String]
selectlines n list = filter (\s -> (length s) >= n) list
このコードでのポイントは filter関数かな。
関数(ここではラムダ式)で与えた条件に一致するものだけを返す関数。
この場合は、文字列のリストから、長さが n 以上の文字列だけを
抜き出すというもの。
map と filterがあれば、随分といろんなことが出来そう。
C#のLINQではSelectとWhereに対応しているような感じですね。
main の do 記法は、いつもとちょっと変えて、{ } を使ってC#風に
書いてみた。
僕には、この方がしっくりきますね。
{ }を使わなければ、
main = do cs <- getContents
args <- getArgs
putStrLn $ unlines $ selectlines (read $ head args) $ lines cs
2008年04月21日
[Haskell] 月の日数を求める
指定した月の日数を求める関数を作れ。
ただし、うるう年は考慮しなくてもよい。
やりたいことは実に単純なんだけど、リストのn番目を求めるのってどうやるんだろうか?
調べたら !! 演算子があるということがわかった。
なるほど、それならば、
でOKかな。
自分で、!! 演算子と同じことをやる関数を作るとするとどうやるのかも考えてみた。
とこんな感じか。
随分とHaskellの再帰処理にも慣れてきたようだ。
ところで、今気がついたんだけど、Haskellで例外処理って
どう書くのかな?
これこは、明日以降の課題ですね。
ただし、うるう年は考慮しなくてもよい。
やりたいことは実に単純なんだけど、リストのn番目を求めるのってどうやるんだろうか?
調べたら !! 演算子があるということがわかった。
なるほど、それならば、
daysOfMonth :: Int -> Int
daysOfMonth n = days !! (n-1)
days :: [Int]
days = [31, 28, 31, 30, 31, 30, 31,31, 30, 31, 30, 31]
でOKかな。
自分で、!! 演算子と同じことをやる関数を作るとするとどうやるのかも考えてみた。
valueAt :: Int -> [Int] -> Int
valueAt n (x:xs)
| n == 0 = x
| otherwise = valueAt (n-1) xs
とこんな感じか。
随分とHaskellの再帰処理にも慣れてきたようだ。
ところで、今気がついたんだけど、Haskellで例外処理って
どう書くのかな?
これこは、明日以降の課題ですね。
2008年04月20日
[Haskell] maximumを使わずに最大値を求める
標準関数 max, maximum を使わずに、最大値を求める関数を書け。
最初に書いたコードはこれ。
ガードを使って書いてみた。
2回同じ maxnum xs が出てどうなんだろう?って思ったが、動くことには動いた。でも、ものすごく遅い。
次に書いたのがこちら。
これならば、速度的には問題ないようだ。
でも、意外と手こずった。
先頭の要素を2つ取り出すのに、2段階に関数を定義しなければならないのが厄介だが、これしかやり方が思いつかない。
foldl系の関数を使えばもっと簡単になるが、foldl系の関数も中身は同じようなことをやっているので、本質的には変わらない。
最初に書いたコードはこれ。
maxnum :: [Integer] -> Integer
maxnum [a] = a
maxnum (x:xs)
| x > maxnum xs = x
| otherwise = maxnum xs
ガードを使って書いてみた。
2回同じ maxnum xs が出てどうなんだろう?って思ったが、動くことには動いた。でも、ものすごく遅い。
次に書いたのがこちら。
maxnum :: [Integer] -> Integer
maxnum (x:xs) = maxnum_ x xs
maxnum_ :: Integer -> [Integer] -> Integer
maxnum_ n [] = n
maxnum_ n (x:xs) = maxnum_ (maxn n x) xs
maxn :: Integer -> Integer -> Integer
maxn a b = if a > b then a else b
これならば、速度的には問題ないようだ。
でも、意外と手こずった。
先頭の要素を2つ取り出すのに、2段階に関数を定義しなければならないのが厄介だが、これしかやり方が思いつかない。
foldl系の関数を使えばもっと簡単になるが、foldl系の関数も中身は同じようなことをやっているので、本質的には変わらない。