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


はじめに

これの続き.

PrePAN でいただいたコメント(ポジティヴなニュアンスであると解釈していいよね?) の中に何気に $foo="az" とかあって,やっぱりこういう使い方できた方がいいよね,と思ってたので,overload モジュールでできるかと思いきや,そうも行かない感じになってきて

などとぼやいたところ(よく見たら “use” でなくて “user” になってるなw),lestrrat さんから

というアドヴァイスが.まぁオススメされてませんがw

とりあえず実装してみた

とりあえず実装すべく.

そういえば, tie とか触ったことなかったので,

をはじめどういったことができるものなのか,から少し調べてました.

で,実装した差分がこれになります:

これにより,次のようなことができるようになりました:

use String::Incremental;
 
tie my $str, 'String::Incremental', ( format => '%2=', orders => [ 'abc' ] );
print "$str";  # -> 'aa';
 
$str = 'bc';   # same as `$str->set( 'bc' )` <- ココ!
print "$str";  # -> 'bc'
 
$str++;
print "$str";  # -> 'ca'

まぁ メソッド ->set() を簡略化できるだけですね.

この実装を始めた頃,

sub tied_constructor {
    my ($class, @args) = @_;
    tie my $tied, 'String::Incremental::Tied', @args;
    return $tied;
}

みたいなものを準備して,呼ぶ側では tie を書かずに済むようにしたかったのですが,どうやらその戻り値は tie されていないご様子.そのへん調べきれていないので,現段階では先のような実装になってしまいました.

あと,この変更で $str++$str-- の挙動にも影響が出たため,元のテストが pass するよう,(ヒューリスティックな感じで)SOTORE メソッドを調整しています><

おわりに

少し前に書いた CPAN 未満モジュール String::Incremental に変更を加えて,tie したときには,代入感覚でメソッド ->set() を呼び出せる ようにしてみたお話でした.

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


ss-1402452303

メモ

昔に書いたこれを,今になって少しだけ使い勝手の向上をはかってみました.

具体的には次の 2点:

  • -c foobar とした際,最初に ~/.imtail.d/foobar.toml を探しにいく
  • -t を指定した場合,設定ファイルテストのみ行って終了する

個人的に普段使いしているのですが,設定ファイルがプロジェクトごとに分散したり,設定ファイルをフルパスで毎回指定するのがメンドウだったり,といったことが背景ですかね.ホント今さらですがw

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


はじめに

ここからさらに 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 なんかもお待ちしております><

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


メモ

今朝からハマっていた記録.

ハマったこと

# test.pl
use 5.18.0;
use warnings;
use Data::Validator;
use MouseX::Types::Mouse qw( Str ArrayRef );
 
sub main {
    my $v = Data::Validator->new(
        foo => { isa => Str|ArrayRef[Str], optional => 1 },
    )->with( 'StrictSequenced' );
    my $args = $v->validate( @_ );
    say 'OK';
}
 
main( @ARGV );

バリデーションルールの方針は次のとおり:

  • 最初の引数は Str 型,もしくは Str 型を要素とする ArrayRef

これを実行するとエラーになります:

% carton exec perl test.pl
Too many arguments for ArrayRef at test.pl line 7.

モジュールのバージョン

Data::Validator と,それに関連しているのは Mouse かな,のバージョンはそれぞれ以下.

Data::Validator

package Data::Validator;
use 5.008_001;
use Mouse;
use Mouse::Util::TypeConstraints ();
use Mouse::Util                  ();
use Carp                         ();
 
our $VERSION = '1.04';

Mouse

package Mouse;
use 5.006_002;
 
use Mouse::Exporter; # enables strict and warnings
 
our $VERSION = '2.2.0';

試行錯誤

optional => 1 を外してみる:

        foo => { isa => Str|ArrayRef[Str] },
% carton exec perl test.pl
Missing parameter: 'foo'
... found at /Users/issm/sandbox/perl/2014-05-22.data-validator/local/lib/perl5/Data/Validator.pm line 219.
	Data::Validator::validate('Mouse::Meta::Class::__ANON__::1=HASH(0x7fad31831f00)') called at test.pl line 10
	main::main() called at test.pl line 14
% carton exec perl test.pl hogehoge
OK

問題なさげ.

先の Too many ... のエラーメッセージから察するに,optional まわりが ArrayRef の引数として認識されているのか?

ということで,次のように修正:

        foo => { isa => ( Str|ArrayRef[Str] ), optional => 1 },
% carton exec perl test.pl hogehoge
OK

...ここまで 3時間弱...orz

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


IMGP1166

はじめに

aqua さんに乗り始めて初めて サイコン を装備して 5年くらい.

  • 記録データの汎用性がない
  • それを管理するためのアプリケーションが Window のみ対応とか
  • 脈拍センサもついてたけど,使用感がビミョーだったのでずっと使っていない
  • 数ヶ月前にコケて曲げてしまったハンドル交換時の試走の際に,外したままだったマウントをホイールに引っ掛けてセンサ・マウント間の線をぶっちぎってしまった
  • 次買うなら GPS による位置情報記録もできたらいいな.iPhone のバッテリ気にしなくてもよくなるし
  • 一応ケイデンスも記録できるといいよね
  • 地図はなくてもいいや

こんな背景で,そろそろ新調するかって感じになりました.

で,GARMIN EDGE 510J を選んでみました.ちょっと奮発!

センサはこんな感じ

IMGP1169

スピードセンサ,ケイデンスセンサが一体になっていて,チェーンステイに取り付ける感じです.それに伴い,スピードセンサのためのスポークマグネットも後輪側に.

記録データを蓄積・管理する

GARMIN 製サイコンで記録したデータは,「Garmin Connect」という Web サービスに蓄積・管理できるようです.また,そのデータにスマートフォンからアクセスするためのアプリ 「Garmin Connect Mobile」もあるようです.

スマートフォンと同サイコンとを Bluetooth ペアリングすることで,サイコン内の記録データを,スマートフォンを経由してアップロード?同期?することもできました.

Cyclemeter で記録したデータを Garmin Connect へアップロードする

ss-1399893842

いくらか触ってみて,gpx データなんかも手動でアップロードできることもわかりました.

なので,Cyclemeter で記録したデータを gpx 形式でエクスポート:

写真 2014-05-12 20 27 10

したファイルをアップロードすることで,サイコン装備前の記録なんかも管理できてしまいます.すべて移行するにはかなりメンドイけど.

ちなみに Cyclemeter での最初の記録は 2011-10-18 でした:

ss-1399893895

Garmin Connect Mobile ではこんな感じ:

写真 2014-05-12 20 29 54

おわりに

以上,aqua さんに 2代目となるサイコン GARMIN EDGE 510J を取り付けたお話でした.

この 2 〜 3週間ほど,プールも自転車もサボっていたので,改めてモチベーションを上げていかねば.

Amazon さん

4 of 1221...23456...102030...122