2006年06月08日
_ Symbol#[]
<URL:http://d.hatena.ne.jp/shinichiro_h/20051121#p1>と <URL:http://wota.jp/ac/?date=20060314#c03>をマージして さらに boost::bindっぽい見た目をふりかけてみました。
class BindParamPlaceHolder
def initialize(ord)
@ord = ord
end
attr_reader :ord
Holders = (0..30).map{|n| BindParamPlaceHolder.new(n)}
end
(1..30).each do |n|
eval <<-EOS
def _#{n}
BindParamPlaceHolder::Holders[#{n}]
end
EOS
end
class Symbol
def [](*a1)
proc do |*a2|
obj, *args = a1.map{|a| a.is_a?(BindParamPlaceHolder) ? a2[a.ord-1] : a}
obj.__send__(self, *args)
end
end
end
if __FILE__ == $0
p (1..10).map(&:/[2.0, _1])
p (1..10).map(&:/[_1, 2.0])
end
1から30までなのは適当。その他も適当
[ツッコミを入れる]
2006年06月15日
_ 日本Rubyカンファレンス2006
日本Rubyカンファレンス2006に行ってきました。LTで発表もしました。
記憶が残っているうちにいろいろ書いておきます。
- 田中さんの発表が良かった
- 良いAPIとは、良く使う機能は使いやすく、あまり使わない機能は使いにくく
- 使わせたい機能は使いやすく、使わせたくない機能は使いにくく
- この話からいろんなことを演繹できそう
- なひさんのセキュリティプログラミングはわかりやすかった。
- 懇親会などでdanさんと色々話した。
- いろいろ面白い話を聞かせてもらった
- 青木さんと会った
- YARVは本当に1.9.1に入るのか?
- LTの発表資料
あとスタッフの皆様に感謝。
[ツッコミを入れる]
2006年06月23日
_ C++いろいろ
以下の OCaml の コードを
open List
let f lst =
let even n = n mod 2 = 0 in
let pow2 n = n * n in
fold_left (+) 0 (map pow2 (filter even lst))
C++ で表現しようとします。
で、コードその1。
int f(std::vector<int>& v)
{
int sum = 0;
for(int i = 0; i < v.size(); ++i){
if(v[i] % 2 == 0)
sum += v[i] * v[i];
}
return sum;
}
コードその2。次にイテレータでちょっと抽象化。
template<typename Iter> int f(Iter first, Inter last)
{
int sum = 0;
for(Iter it = first; it != last; it++){
if(*it % 2 == 0)
sum += (*it)*(*it);
}
return sum;
}
これだと最初のOCamlのコードとは1対1対応していません。 というわけで stl の algorithm を使ってみます。コードその3
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
class Odd{
public:
bool operator()(int n){
return (n%2==1);
}
};
class Pow2{
public:
int operator()(int n){
return n*n;
}
};
template<typename Iter> int f(Iter first, Iter last)
{
vector<int> v1, v2;
remove_copy_if(first, last, back_insert_iterator<vector<int> >(v1),
Odd());
transform(v1.begin(), v1.end(), back_insert_iterator<vector<int> >(v2),
Pow2());
return accumulate(v2.begin(), v2.end(), 0);
}
コードその4。関数オブジェクトのクラスが邪魔なので boost::lambda を使います。
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <boost/function.hpp>
#include <boost/lambda/lambda.hpp>
using namespace std;
template<typename Iter> int f(Iter first, Iter last)
{
using namespace boost::lambda
boost::function<bool (int)> odd = (_1%2!=0);
boost::function<int (int)> pow2 = (_1 * _1);
vector<int> v1, v2;
remove_copy_if(first, last, back_insert_iterator<vector<int> >(v1), odd);
transform(v1.begin(), v1.end(), back_insert_iterator<vector<int> >(v2), pow2);
return accumulate(v2.begin(), v2.end(), 0);
}
コードその5。中間データ用の vector は別に必要ないはず、ということで iterator_adaptor を使ってみます。
#include <algorithm>
#include <numeric>
#include <functional>
#include <boost/functional.hpp>
#include <boost/function.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/lambda/lambda.hpp>
using namespace std;
template<typename Iter> int f(Iter first, Iter last)
{
using namespace boost::lambda;
using boost::make_transform_iterator;
using boost::make_filter_iterator;
boost::function<bool (int)> is_even = (_1%2==0);
boost::function<int (int)> pow2 = (_1 * _1);
return accumulate(make_transform_iterator(make_filter_iterator(is_even,first, last), pow2),
make_transform_iterator(make_filter_iterator(is_even,last, last), pow2),
0);
}
以上。<URL:http://www.kmonos.net/alang/boost/> や <URL:http://shinh.skr.jp/boost/iterator_adaptors.html> を参考にして書きました。iterator_adaptorを使いたかったというだけだという気もします。
個人的にはコードその2くらいにしておくのが良いのではと思います。
[ツッコミを入れる]