エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

selectを知った

今日になって、Rubyの配列やハッシュにselectというメソッドがあるのを知った。
Rubyを使い始めて何年目。Enumerableの存在は知っていたものの、きちんと調べたことがなかったなぁ。

始めて使ったselectは、こんな感じ。

Info = Struct.new(:id, :name)

infos = [
  Info.new(1, "Alice"),
  Info.new(2, "Bill"),
  Info.new(3, "Chris"),
  Info.new(4, "Dan"),
  Info.new(5, "Elen")
  ]

infos.select{ |item| (2 <= item.id) && (item.id <= 4) }.each { |item| puts "(#{item.id},#{item.name})" }


最近気に入っている、Haskellだとどうなるか、書いてみた。

selectAndPuts is = mapM_ print [x|x <- is, (2 <= fst x) && (fst x <= 4)]

infos = [(1, "Alice"), (2, "Bill"), (3, "Chris"), (4, "Dan"), (5, "Elen")]

main = selectAndPuts infos


加えて、C++でも。

#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <iterator>

struct Info
{
    int         id;
    std::string name;
};

std::ostream& operator << (std::ostream& out, const Info& info)
{
    return out << '(' << info.id << ',' << info.name << ')';
}

struct cond : public std::unary_function<const Info&, bool>
{
    bool operator () (const Info& info)
    {
        return (2 <= info.id) && (info.id <= 4);
    }
};

void selectAndPuts(std::vector<Info> infos)
{
    std::copy(infos.begin(), partition(infos.begin(), infos.end(), cond()), std::ostream_iterator<Info>(std::cout, "\n"));
}

main(int, char* [])
{
    Info infos[] = { {1, "Alice"}, {2, "Bill"}, {3, "Chris"}, {4, "Dan"}, {5, "Elis"} };

    selectAndPuts(std::vector<Info>(infos, infos + 5));

    return 0;
}


やっぱり、C++では不利か。

明日の自分のために捕捉。selectAndPuts関数の仮引数が参照でなくて実体になっているのは、関数内で値を破壊してしまっているので、呼び出し元の引数の値を破壊しないようにするためです。