Send to your Kindle RIGHT:[[:t/検索]] #contents *流れ [#ob994459] 検索/フォーマット、検索/ソートは機能で。いくつでも何種類でも組み合わせて。 検索/フィルタリングが検索特有の処理。 検索/スコアリング、検索/フォーマット、検索/ソートは汎用の機能で。 検索/クエリーはページ/作成処理の一部。 **ページ生成時 [#l95b1a28] +ページ(文字列)→ページ(オブジェクト) 保存。永続化。検索時に使えるようにするため。 #br **検索時 [#x7261d2e] +検索式→オブジェクト 検索式(文字列)→検索式(オブジェクト) ページ(オブジェクト)と同じ型。比較するため。 ++オブジェクト選択 比較時、検索/クエリー側のオブジェクト1つとページを構成するオブジェクト1つを選択しなければならない。 検索/クエリー側は評価順が静的に決まっている。 ページ側の順序はページが決めるので後回し。 検索/クエリー側は1回だけ走査。ページ側は検索/クエリーの要素数だけ繰り返し参照される。 ++比較 同じクラスのオブジェクト同士の比較。 検索/クエリーのスコア算出処理にページ側のオブジェクトを渡す→検索/スコアリング ++スコア計算 検索/スコアリングの方法でページを構成するオブジェクトごとに計算。 計算方法は検索/クエリーに含まれる修飾句オブジェクト次第。 **検索時(オプション) [#p279b843] 検索以外にも使える機能で。 順序も組み合わせも自由。 +出力用データ生成 検索/フォーマットの機能で検索結果に含めるデータと、検索/ソートに渡すデータ生成。 ページ単位で結果を出すなら、ページごとにスコアを集計、ページごとにデータ生成。 +ソート %%検索/ソートの機能で検索結果に含めるデータを並び替え。%% →検索/ソートは機能/表に移す。 ---- で、検索結果生成。 HTML化。これはページ/責務。正確にはページの下位にある検索用記法の責務。 ※スコア加算、集計、ソートが分かれているのは繰り返しの単位や範囲が違うから。 ※すべて検索/クエリーで作ったオブジェクトの機能で行う。 →[[プロトタイピング]] * コード [#xd31fa4e] package main; use strict; use Smart::Comments; { my @elements; @elements = (Element::PlainText->new(' *** Sample sites ***'), Element::URI->new('http://1.com/3rd'), Element::URI->new('http://3.com/2nd/'), Element::URI->new('http://2.com/1st/')); { ### not sorted, not filtered: my $page = Page->new(@elements); print $page->out(); } print "\n--------\n"; { ### sorted: my $page = Page->new(Element::Container::Sort->new(@elements)); print $page->out(); } print "\n--------\n"; { ### link list: my $page = Page->new(Element::Container::Filter->new(@elements)); print $page->out(); } print "\n--------\n"; { ### link list sorted by label: my $page = Page->new(Element::Container::Sort->new(Element::Container::Filter->new(@elements))); print $page->out(); } print "\n--------\n"; } package Page; sub new { my $class = shift; bless { element => [@_] }, $class; } sub elements { my $self = shift; map { $_->elements() } @{$self->{element}}; } sub out { my $self = shift; join "\n", map { $_->out() } $self->elements(); } sub string { my $self = shift; join '', map { $_->string() } $self->elements(); } package Element::Container::Sort; sub new { my $class = shift; bless { element => [@_] }, $class; } sub elements { my $self = shift; my @r; foreach (@{$self->{element}}){ push @r, $_->elements(); } sort { $a->string() cmp $b->string() } @r; } sub out { my $self = shift; map { $_->out() } $self->elements(); } sub string { my $self = shift; join '', map { $_->string() } $self->elements(); } package Element::Container::Filter; sub new { my $class = shift; bless { element => [@_] }, $class; } sub elements { my $self = shift; my @r; foreach (@{$self->{element}}){ push @r, map { $_->fetch_by('label') =~ m%http://[^/]*/([^/]*)%; ref($_)->new($_->fetch_by('uri'), $1); } grep { $_->isa('Element::URI'); } $_->elements(); } @r; } sub out { my $self = shift; map { $_->out() } $self->elements(); } sub string { my $self = shift; join '', map { $_->string() } $self->elements(); } package Element::URI; sub new { my $class = shift; my($uri, $label) = @_; $label = $label ? $label : $uri; bless { uri => $uri, label => $label }, $class; } sub elements { $_[0]; } sub out { my $self = shift; '<a href="'.$self->{uri}.'">'.$self->{label}.'</a>'; } sub fetch_by { my $self = shift; my($request) = @_; my $r; if ($request eq 'label'){ $r = $self->_label(); } elsif ($request eq 'uri'){ $r = $self->_uri(); } else { $r = $self->string(); } $r; } sub string { my $self = shift; $self->{label}; } sub _uri { my $self = shift; $self->{uri}; } sub _label { my $self = shift; $self->{label}; } package Element::PlainText; sub new { my $class = shift; bless { text => $_[0] }, $class; } sub elements { $_[0]; } sub out { $_[0]->{text}; } sub fetch_by { my $self = shift; $self->string(); } sub string { $_[0]->{text}; } ------------------------------------------------ ### not sorted, not filtered: *** Sample sites *** <a href="http://1.com/3rd">http://1.com/3rd</a> <a href="http://3.com/2nd/">http://3.com/2nd/</a> <a href="http://2.com/1st/">http://2.com/1st/</a> -------- ### sorted: *** Sample sites *** <a href="http://1.com/3rd">http://1.com/3rd</a> <a href="http://2.com/1st/">http://2.com/1st/</a> <a href="http://3.com/2nd/">http://3.com/2nd/</a> -------- ### link list: <a href="http://1.com/3rd">3rd</a> <a href="http://3.com/2nd/">2nd</a> <a href="http://2.com/1st/">1st</a> -------- ### link list sorted by label: <a href="http://2.com/1st/">1st</a> <a href="http://3.com/2nd/">2nd</a> <a href="http://1.com/3rd">3rd</a> -------- RIGHT:[[:t/検索]] #contents *流れ [#ob994459] 検索/フォーマット、検索/ソートは機能で。いくつでも何種類でも組み合わせて。 検索/フィルタリングが検索特有の処理。 検索/スコアリング、検索/フォーマット、検索/ソートは汎用の機能で。 検索/クエリーはページ/作成処理の一部。 **ページ生成時 [#l95b1a28] +ページ(文字列)→ページ(オブジェクト) 保存。永続化。検索時に使えるようにするため。 #br **検索時 [#x7261d2e] +検索式→オブジェクト 検索式(文字列)→検索式(オブジェクト) ページ(オブジェクト)と同じ型。比較するため。 ++オブジェクト選択 比較時、検索/クエリー側のオブジェクト1つとページを構成するオブジェクト1つを選択しなければならない。 検索/クエリー側は評価順が静的に決まっている。 ページ側の順序はページが決めるので後回し。 検索/クエリー側は1回だけ走査。ページ側は検索/クエリーの要素数だけ繰り返し参照される。 ++比較 同じクラスのオブジェクト同士の比較。 検索/クエリーのスコア算出処理にページ側のオブジェクトを渡す→検索/スコアリング ++スコア計算 検索/スコアリングの方法でページを構成するオブジェクトごとに計算。 計算方法は検索/クエリーに含まれる修飾句オブジェクト次第。 **検索時(オプション) [#p279b843] 検索以外にも使える機能で。 順序も組み合わせも自由。 +出力用データ生成 検索/フォーマットの機能で検索結果に含めるデータと、検索/ソートに渡すデータ生成。 ページ単位で結果を出すなら、ページごとにスコアを集計、ページごとにデータ生成。 +ソート %%検索/ソートの機能で検索結果に含めるデータを並び替え。%% →検索/ソートは機能/表に移す。 ---- で、検索結果生成。 HTML化。これはページ/責務。正確にはページの下位にある検索用記法の責務。 ※スコア加算、集計、ソートが分かれているのは繰り返しの単位や範囲が違うから。 ※すべて検索/クエリーで作ったオブジェクトの機能で行う。 →[[プロトタイピング]] * コード [#xd31fa4e] package main; use strict; use Smart::Comments; { my @elements; @elements = (Element::PlainText->new(' *** Sample sites ***'), Element::URI->new('http://1.com/3rd'), Element::URI->new('http://3.com/2nd/'), Element::URI->new('http://2.com/1st/')); { ### not sorted, not filtered: my $page = Page->new(@elements); print $page->out(); } print "\n--------\n"; { ### sorted: my $page = Page->new(Element::Container::Sort->new(@elements)); print $page->out(); } print "\n--------\n"; { ### link list: my $page = Page->new(Element::Container::Filter->new(@elements)); print $page->out(); } print "\n--------\n"; { ### link list sorted by label: my $page = Page->new(Element::Container::Sort->new(Element::Container::Filter->new(@elements))); print $page->out(); } print "\n--------\n"; } package Page; sub new { my $class = shift; bless { element => [@_] }, $class; } sub elements { my $self = shift; map { $_->elements() } @{$self->{element}}; } sub out { my $self = shift; join "\n", map { $_->out() } $self->elements(); } sub string { my $self = shift; join '', map { $_->string() } $self->elements(); } package Element::Container::Sort; sub new { my $class = shift; bless { element => [@_] }, $class; } sub elements { my $self = shift; my @r; foreach (@{$self->{element}}){ push @r, $_->elements(); } sort { $a->string() cmp $b->string() } @r; } sub out { my $self = shift; map { $_->out() } $self->elements(); } sub string { my $self = shift; join '', map { $_->string() } $self->elements(); } package Element::Container::Filter; sub new { my $class = shift; bless { element => [@_] }, $class; } sub elements { my $self = shift; my @r; foreach (@{$self->{element}}){ push @r, map { $_->fetch_by('label') =~ m%http://[^/]*/([^/]*)%; ref($_)->new($_->fetch_by('uri'), $1); } grep { $_->isa('Element::URI'); } $_->elements(); } @r; } sub out { my $self = shift; map { $_->out() } $self->elements(); } sub string { my $self = shift; join '', map { $_->string() } $self->elements(); } package Element::URI; sub new { my $class = shift; my($uri, $label) = @_; $label = $label ? $label : $uri; bless { uri => $uri, label => $label }, $class; } sub elements { $_[0]; } sub out { my $self = shift; '<a href="'.$self->{uri}.'">'.$self->{label}.'</a>'; } sub fetch_by { my $self = shift; my($request) = @_; my $r; if ($request eq 'label'){ $r = $self->_label(); } elsif ($request eq 'uri'){ $r = $self->_uri(); } else { $r = $self->string(); } $r; } sub string { my $self = shift; $self->{label}; } sub _uri { my $self = shift; $self->{uri}; } sub _label { my $self = shift; $self->{label}; } package Element::PlainText; sub new { my $class = shift; bless { text => $_[0] }, $class; } sub elements { $_[0]; } sub out { $_[0]->{text}; } sub fetch_by { my $self = shift; $self->string(); } sub string { $_[0]->{text}; } ------------------------------------------------ ### not sorted, not filtered: *** Sample sites *** <a href="http://1.com/3rd">http://1.com/3rd</a> <a href="http://3.com/2nd/">http://3.com/2nd/</a> <a href="http://2.com/1st/">http://2.com/1st/</a> -------- ### sorted: *** Sample sites *** <a href="http://1.com/3rd">http://1.com/3rd</a> <a href="http://2.com/1st/">http://2.com/1st/</a> <a href="http://3.com/2nd/">http://3.com/2nd/</a> -------- ### link list: <a href="http://1.com/3rd">3rd</a> <a href="http://3.com/2nd/">2nd</a> <a href="http://2.com/1st/">1st</a> -------- ### link list sorted by label: <a href="http://2.com/1st/">1st</a> <a href="http://3.com/2nd/">2nd</a> <a href="http://1.com/3rd">3rd</a> --------