Haskell で Python の String#join, Ruby の Array#join に相当するものは何だろう?
Prelude, Data.List を眺めてみるが、どこだろうか ... (@_@;)
自分で実装
とりえあえず、自分で書いてみる。 まず使い方を考えた場合、こんな感じ。
join ", " ["aaa", "bbb", "ccc"]
文字列と文字列のリストに join を適用すると、連結された結果の文字が返されると考え、
join :: String -> [String] -> String join _ [] = [] join sep ss@(x:xs) = x ++ case length ss of {1 -> ""; otherwise -> sep} ++ join sep xs
ワイルドカード(ふつうのHaskellプログラミング, p170)、アズパターン(同, p173)、case 式(同, p177) の練習になったが、なんともぎこちない感じが。 ^^;
少し改良してみた。 case 式を使うのをやめて、リストパターン(同, p172)で。
join :: String -> [String] -> String join sep [] = [] join sep [x] = x join sep (x:xs) = x ++ sep ++ join sep xs
最初、リストパターンについてわかっていなくて、次のように書いていた。
join sep [x] | length x == 1 = x
冗長だ ... (@_@;) これにずっと気がつかず、意味のないガードを。 ^^;
ちなみに、[], (x:xs) はデータコンストラクタによるパターンマッチ。(同上, p173) うーん、ややこしい。(+_+) パターンマッチによるフィールドへのアクセス(同上, p226)で書かれていたこと同じものに分類される。うーむ... CCC
Data.List
BBL::Wiki - Haskell::覚え書き によると、
Rubyでよく使うArray#joinはList.intersperse::a->[a]->[a]を利用すれば似たようなのが書ける。
Data.List の intersperse を見てみると、
The intersperse function takes an element and a list and `intersperses' that element between the elements of the list. For example,
intersperse ',' "abcde" == "a,b,c,d,e"
ところで、この語の意味は Yahoo!辞書 – intersperse には、
1 …を間隔をおいて配置する, ばらまく, ちりばめる, 点在させる
flowers interspersed among the grass
草むらに点々と咲く花.2 …に(…を)点在させる, …に(…で)変化をもたせる((with ...))
intersperse one's talk with good humor
おもしろいユーモアをはさんで話に変化をつける.
あるものの中に挟み込まさせるというイメージか。 join のように「つなげる」とは対照的な語が使われているところがおもしろい。
intersperse の実装を真似る
Haskell Code by HsColour にあるソースコードを見てみると、
intersperse :: a -> [a] -> [a] intersperse _ [] = [] intersperse _ [x] = [x] intersperse sep (x:xs) = x : sep : intersperse sep xs
あ~、綺麗。 (@_@) これを真似して先ほど書いたコードを修正してみよう。
join :: [a] -> [[a]] -> [a] join _ [] = [] join _ [x] = x join sep (x:xs) = x ++ sep ++ join sep xs
intercalate
intersperse のすぐに下に intercalate なる関数があった。
1 〈余分の日・月などを〉暦に挿入する, 閏(うるう)にする.
2 …を挿入する.
実装を見ると、intersperse を concat している。
intercalate :: [a] -> [[a]] -> [a] intercalate xs xss = concat (intersperse xs xss)
map に対する concatMap のようなものか。
使い方のまとめ
import Data.List main = do putStrLn $ intersperse ',' "abcd" putStrLn $ concat $ intersperse ", " ["aaa", "bbb", "ccc"] putStrLn $ intercalate ", " ["aaa", "bbb", "ccc"]
0コメント:
コメントを投稿