• このエントリーをはてなブックマークに追加


はじめに

ここからさらに 1日ほど書いてたりして,とりあえずまとまってきたのでいったん記録.

Links

Github:

モジュールを作るにあたり,今回初めて,最初から Travis CI を回してみています:

PrePAN:

SYNOPSIS

use String::Incremental;
 
my $str = String::Incremental->new(
    format => 'foo-%2=-%=',
    orders => [
        [0..2],
        'abcd',
    ],
);
 
# or
 
use String::Incremental qw( incremental_string );
 
my $str = incremental_string(
    'foo-%2=-%=',
    [0..2],
    'abcd',
);
 
print "$str";  # -> 'foo-00-a'
 
$str++; $str++; $str++;
print "$str";  # -> 'foo-00-d'
 
$str++;
print "$str";  # -> 'foo-01-a'
 
$str->set( 'foo-22-d' );
print "$str";  # -> 'foo-22-d';
$str++;  # dies, cannot ++ any more

ざっと解説

new

インクリメントさせたい文字に相当する位置に,sprintf でいう「フォーマッタ」のようなもの %= を指定し,sprintf でいう値リストの部分で,変わりうる文字の集合を文字列(もしくは ArrayRef)として与えます.

use String::Incremental qw( incremental_string );
 
my $str = incremental_string(
    'foo-%2=-%=',  # フォーマッタ `%=`
    [0..2],        # ArrayRef でも
    'abcd',        # Str でも
);

また,フォーマッタとして %3= のような書式も利用でき,「定義したルールの文字が 3桁連続する」といった感じになります(インクリメントは独立しています).次の 2変数 $str1$str2 は同様の意味を持ちます:

my $str1 = incremental_string( '%3=', 'abc' );
my $str2 = incremental_string( '%=%=%=', 'abc', 'abc', 'abc' );

文字列

メソッド ->as_string() を呼ぶか,オブジェクト自身を文字列として評価することで,「現在の状態」が文字列として返ります:

say $str1->as_string();  # -> aaa
say "$str2";             # -> aaa

インクリメント

メソッド ->increment() を呼ぶか,数値変数同様に ++ することで,「現在の状態」が 1段階インクリメントされます:

$str->increment();
say $str1->as_string();  # -> aab
 
$str2++;
say "$str2";             # -> aab

なお,インクリメント可能な文字がすべて「最後」の状態でインクリメントを行おうとした場合,die します:

say "$str1";  # -> ccc
$str1++;      # dies!

あと,「繰り上がり」っぽいことも起きます:

say "$str1";  # -> bcc
$str1++;
say "$str1";  # -> caa

値をセットする

メソッド ->set() で,「現在の状態」を指定した値にセットすることができます.指定した値が,そのオブジェクトが持っているフォーマットや「インクリメントのルール」に合致しない場合,die します:

$str1->set( 'abc' );
say "$str1";  # -> abc
 
$str1->set( 'daa' );  # dies! 'd' is not defined

簡単なサンプル

その 1

# sample1.pl
use strict;
use warnings;
use String::Incremental qw( incremental_string );
use feature 'say';
 
my $str = incremental_string(
    'foo-%2=-%2=-%=',
    'abc',
    ['x'..'z'],
    '147',
);
say "$str";
 
while ( 1 ) {
    $str++;
    say "$str";
}

出力:

%perl -Ilib sample1.pl
foo-aa-xx-1
foo-aa-xx-4
foo-aa-xx-7
foo-aa-xy-1
foo-aa-xy-4
foo-aa-xy-7
foo-aa-xz-1
foo-aa-xz-4
foo-aa-xz-7
foo-aa-yx-1
foo-aa-yx-4
...
foo-cc-zy-1
foo-cc-zy-4
foo-cc-zy-7
foo-cc-zz-1
foo-cc-zz-4
foo-cc-zz-7
cannot increment at lib/String/Incremental/Char.pm line 110.

その 2

# sample2.pl
use strict;
use warnings;
use String::Incremental qw( incremental_string );
use feature 'say';
 
my $str = incremental_string(
    'foo-%2=-%2=-%=',
    'abc',
    ['x'..'z'],
    '147',
);
say "$str";
 
say q{set to 'foo-ac-zz-7'};
$str->set( 'foo-ac-zz-7' );
say "$str";
 
say q{increment};
$str++;
say "$str";
 
say q{set to 'foo-aa-uz-7'};
$str->set( 'foo-aa-uz-7' );
say "$str";

出力:

foo-aa-xx-1
set to 'foo-ac-zz-7'
foo-ac-zz-7
increment
foo-ba-xx-1
set to 'foo-aa-uz-7'
specified value does not match with me at lib/String/Incremental.pm line 133.

おわりに

以上,自分ルールに基づいてインクリメントするような文字列を扱うためのモジュール String::Incremental を書いてみたお話でした.

個人的に望んでいる機能(冒頭のとおり,プロジェクトローカルなとある要件を満たすもの)あたりはひとまずできている感じなので,実際に使いながらバグを潰していこうかな,などと考えております.

既にこんなモジュールあるし,とか,こんな名前の方がいいんじゃね?とかのアドヴァイスや Pullreq なんかもお待ちしております><