Upload
hiro-h
View
1.140
Download
5
Embed Size (px)
Citation preview
最近書いた 関数型言語と関連する? C++プログラムの紹介
H.Hiro (Maraigue)
Web: http://hhiro.net/about/
Twitter: @h_hiro_
2011 関数型都市忘年会
自己紹介
H.Hiro
自己紹介
札幌C++から
来ました
自己紹介
H.Hiro
• 大学院生(情報系)
• アルゴリズムを考案し、それを実装して 効果を確かめたりしています(主にC++利用)
• 最近、C++11の機能をいろいろと使いたいが ために、研究室のマシンをUbuntuを11に アップしました (gcc4.5標準搭載のため)
自己紹介
H.Hiro
• 好んで使うもの:C++、Ruby、JavaScript
• 用途次第では使うもの:C#、Python、PHP
• 一応書けるもの:Perl、Java、etc...
自己紹介
H.Hiro
• 好んで使うもの:C++、Ruby、JavaScript
• 用途次第では使うもの:C#、Python、PHP
• 一応書けるもの:Perl、Java、etc...
• まだ使えてないもの:Scala、F#、etc...
自己紹介
• Twitter: @h_hiro_
• Facebook: 諸事情により非公開
• github: maraigue(まれーぐ)
• ブログ: LivedoorブログのID "maraigue"
• ニコ動: 探せば見つかります
自己紹介(宣伝)
数学勉強会@札幌 • 大学数学の内容を取り扱ってます (現在は「群論」をやっています)
• 毎週土曜日の10:00~12:00に 開催 ※今週については 日曜10:00~12:00
• 公式サイト:ぐぐって!
自己紹介(宣伝)
交通勉強会(trafficonf) • 主に首都圏のメンバーがやっている 勉強会ですが、私も乗っかってます (10/8 札幌でust観覧会を実施)
• 不定期開催(2~3ヶ月に1回)
• 次の開催は1/7
• 次の札幌開催は3/17?
• 公式サイト: 「交通勉強会準備会」でぐぐって!
最近書いた 関数型言語と関連する? C++プログラムの紹介
H.Hiro (Maraigue)
Web: http://hhiro.net/about/
Twitter: @h_hiro_
おことわり
別に、直接 "関数型言語" 的な
ことをするわけではないです
おことわり
別に、直接 "関数型言語" 的な
ことをするわけではないです ※C++で、「直接 "関数型言語" 的なことをする」例:
Boost.勉強会 #6 札幌のuskz氏の発表 http://sites.google.com/site/boostjp/study_meeting/study6
最近書いた 関数型言語と関連する? C++プログラムの紹介
H.Hiro (Maraigue)
Web: http://hhiro.net/about/
Twitter: @h_hiro_
例題
与えられた文字列に対し、
「どの単語が何番目にあるか」を示す
連想配列を生成したい。
例えば
const std::string text = "I love C++";
という文字列があったとき、連想配列dataを
data["I"] == 0;
data["love"] == 1;
data["C++"] == 2;
となるようにしたい。
回答例(1)
void position(const std::string & str,
std::map<std::string, size_t> & result){
size_t number = 0, begin_pos = 0, end_pos;
result.clear();
for(;;){
end_pos = str.find(' ', begin_pos);
if(end_pos == std::string::npos){
result[str.substr(begin_pos)] = number;
break;
}else{
result[str.substr(begin_pos, end_pos - begin_pos)] = number;
}
begin_pos = end_pos + 1;
number++;
}
}
回答例(1)
void position(const std::string & str,
std::map<std::string, size_t> & result){
size_t number = 0, begin_pos = 0, end_pos;
result.clear();
for(;;){
end_pos = str.find(' ', begin_pos); // スペースの位置を発見して
if(end_pos == std::string::npos){
result[str.substr(begin_pos)] = number;
break;
}else{
result[str.substr(begin_pos, end_pos - begin_pos)] = number;
}
begin_pos = end_pos + 1;
number++;
}
}
回答例(1)
void position(const std::string & str,
std::map<std::string, size_t> & result){
size_t number = 0, begin_pos = 0, end_pos;
result.clear();
for(;;){
end_pos = str.find(' ', begin_pos); // スペースの位置を発見して
if(end_pos == std::string::npos){
result[str.substr(begin_pos)] = number;
break;
}else{
result[str.substr(begin_pos, end_pos - begin_pos)] = number;
} // ↑その部分までの部分文字列をキーとし連想配列に渡す
begin_pos = end_pos + 1;
number++;
}
}
回答例(1)
void position(const std::string & str,
std::map<std::string, size_t> & result){
size_t number = 0, begin_pos = 0, end_pos;
result.clear();
for(;;){
end_pos = str.find(' ', begin_pos); // スペースの位置を発見して
if(end_pos == std::string::npos){
result[str.substr(begin_pos)] = number;
break;
}else{
result[str.substr(begin_pos, end_pos - begin_pos)] = number;
} // ↑その部分までの部分文字列をキーとし連想配列に渡す
begin_pos = end_pos + 1;
number++;
}
}
!!!???
回答例(1)
void position(const std::string & str,
std::map<std::string, size_t> & result){
size_t number = 0, begin_pos = 0, end_pos;
result.clear();
for(;;){
end_pos = str.find(' ', begin_pos); // スペースの位置を発見して
if(end_pos == std::string::npos){
result[str.substr(begin_pos)] = number;
break;
}else{
result[str.substr(begin_pos, end_pos - begin_pos)] = number;
} // ↑その部分までの部分文字列をキーとし連想配列に渡す
begin_pos = end_pos + 1;
number++;
}
}
関数型な方にとっては 普通なことなのかも
しれないけど
回答例(1)
void position(const std::string & str,
std::map<std::string, size_t> & result){
size_t number = 0, begin_pos = 0, end_pos;
result.clear();
for(;;){
end_pos = str.find(' ', begin_pos); // スペースの位置を発見して
if(end_pos == std::string::npos){
result[str.substr(begin_pos)] = number;
break;
}else{
result[str.substr(begin_pos, end_pos - begin_pos)] = number;
} // ↑その部分までの部分文字列をキーとし連想配列に渡す
begin_pos = end_pos + 1;
number++;
}
}
文字列インスタンスを 別途生成するとか
(C++的には)言語道断!
ポイント
関数型言語では、メモリや速度よりも
処理の実現方法を気にする傾向がある。
ポイント
関数型言語では、メモリや速度よりも
処理の実現方法を気にする傾向がある。
(個人的な印象)
ポイント
関数型言語では、メモリや速度よりも
処理の実現方法を気にする傾向がある。
(個人的な印象)
(例:変数への再代入を避ける)
ポイント
関数型言語では、メモリや速度よりも
処理の実現方法を気にする傾向がある。
(個人的な印象)
でも、メモリを重視しなければ
C++の美学に反する。(個人的な印象)
ポイント
関数型言語では、メモリや速度よりも
処理の実現方法を気にする傾向がある。
(個人的な印象)
でも、メモリを重視しなければ
C++の美学に反する。(個人的な印象)
メモリを節約しつつ、関数型言語くらいの
レベルで記法を簡略化したい
回答例(2)
Boost::splitを使う (参考URL http://www.gesource.jp/weblog/?p=4531)
void position(const std::string & str,
std::map<std::string, size_t> & result){
std::list<std::string> splited;
boost::split(splited, str, boost::is_space());
size_t number = 1;
BOOST_FOREACH(std::string tmp, splited){
result[tmp] = number;
}
}
回答例(2)
Boost::splitを使う (参考URL http://www.gesource.jp/weblog/?p=4531)
void position(const std::string & str,
std::map<std::string, size_t> & result){
std::list<std::string> splited;
boost::split(splited, str, boost::is_space());
size_t number = 1;
BOOST_FOREACH(std::string tmp, splited){
result[tmp] = number;
}
}
記述は分かりやすいけど でも文字列インスタンスを 別途生成してるだろ!
つまりは
• すでに存在する文字列(constであることを 仮定してよい)の部分文字列を 1つの文字列として扱いたい ("I love C++" から "love" や "C++" を得たい)
• ただし、その「部分文字列」インスタンスを 作る際、文字列をコピーしてはならない
• でも楽に書きたい (substrが使えれば楽に書けるんだけど…)
…という状況が私の手元で発生したので
ライブラリを書いたのです。
そのライブラリの名は
そのライブラリの名は
http://www.flickr.com/photos/m-louis/3391434507/
Creative Commons 2.0 Attribution-ShareAlike
そのライブラリの名は
fundoshi
http://www.flickr.com/photos/m-louis/3391434507/
Creative Commons 2.0 Attribution-ShareAlike
そのライブラリの名は
fundoshi (「他人のふんどしで相撲を取る」より)
http://www.flickr.com/photos/m-louis/3391434507/
Creative Commons 2.0 Attribution-ShareAlike
fundoshiについて
gist.githubにあります
https://gist.github.com/1372506
(「fundoshi C++」でぐぐっても出ます)
以下のコマンドで入手可能です git clone git://gist.github.com/1372506.git
回答例(1)
void position(const std::string & str,
std::map<std::string, size_t> & result){
size_t number = 0, begin_pos = 0, end_pos;
result.clear();
for(;;){
end_pos = str.find(' ', begin_pos);
if(end_pos == std::string::npos){
result[str.substr(begin_pos)] = number;
break;
}else{
result[str.substr(begin_pos, end_pos - begin_pos)] = number;
}
begin_pos = end_pos + 1;
number++;
}
}
回答例(3)
void position(const std::string & str,
std::map<fundoshi::string, size_t> & result){
size_t number = 0, begin_pos = 0, end_pos;
result.clear();
for(;;){
end_pos = str.find(' ', begin_pos);
if(end_pos == std::string::npos){
result[fundoshi::string(&(str[begin_pos]))] = number;
break;
}else{
result[fundoshi::string(&(str[begin_pos]),
end_pos - begin_pos)] = number;
}
begin_pos = end_pos + 1;
number++;
}
}
実行例
int main(void){
std::map<fundoshi::string, size_t> result;
position("I love C++", result);
std::cout << result["I"] << std::endl;
std::cout << result["C++"] << std::endl;
std::cout << result["love"] << std::endl;
}
実行例
int main(void){
std::map<fundoshi::string, size_t> result;
position("I love C++", result);
std::cout << result["I"] << std::endl;
std::cout << result["C++"] << std::endl;
std::cout << result["love"] << std::endl;
}
↓
0
2
1
きたこれ!
簡単なリファレンス(1)
• クラス名
– template <class CharType> fundoshi::basic_string<CharType>;
– typedef basic_string<char> string;
– typedef basic_string<wchar_t> wstring;
※std::stringとかに名前を合わせてます メソッド名も基本的には合わせてます
簡単なリファレンス(2)
• コンストラクタ – basic_string();
// 空文字列
– basic_string(const CharType * newstr, size_t length); // 文字列の一部を切り出す場合
– basic_string(const CharType * newstr); // '¥0'終端の文字列を使う場合
– basic_string( const std::basic_string<CharType> & newstr); // std::basic_string (std::stringなどを含む) を使う場合
簡単なリファレンス(3)
• ポインタを貰う const CharType * c_str(void) const;
• 長さを取得 size_t length(void) const;
• 文字を取り出す CharType operator [](size_t pos) const;
• 文字列比較 bool operator ==(const basic_string<CharType> & other) const; bool operator < (const basic_string<CharType> & other) const; bool operator <=(const basic_string<CharType> & other) const; bool operator > (const basic_string<CharType> & other) const; bool operator >=(const basic_string<CharType> & other) const;
おことわり
APIは
(今のところ)これで
全部です!
おわりに
• 私はよくRubyも使ってるのだが Rubyに慣れてしまうと C++って記法がエレガントじゃないよね
• だから記法にこだわっている
• boostとかその点頑張ってるっぽいので タイミングを見て勉強してみたいです
おわりに
(再掲)
関数型言語
あまり関係なかった。
本当申し訳ない。
おわりに
(もし時間が余ったら)
もう一つ「記法にこだわる」
ネタをします
おわりに
ありがとう
ございました