Last active
October 3, 2025 23:55
-
-
Save kfly8/4bdb11d0cdf3f8785f350ef3ca297827 to your computer and use it in GitHub Desktop.
Perl Today
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use v5.42; | |
| use Test2::V0; | |
| use experimental qw(builtin); | |
| use builtin qw(is_bool); | |
| subtest 'スカラーの場合' => sub { | |
| subtest '比較演算などの結果は boolean' => sub { | |
| my @case = ( | |
| 1==1, true, '1==1 is true', | |
| 1<2, true, '1<2 is true', | |
| 2<1, false, '2<1 is false', | |
| !1, false, '!1 is false', | |
| ); | |
| for my ($v, $expected, $message) (@case) { | |
| is $v, $expected, $message; | |
| ok is_bool($v), 'and is boolean'; | |
| } | |
| }; | |
| subtest 'falsyなスカラー' => sub { | |
| my @case = ( | |
| # 1. 未定義値 | |
| undef, 'undef is falsy', | |
| # 2. 数値の0および0と評価される数値表現 | |
| 0, '0 is falsy', | |
| 0.0, '0.0 is falsy', | |
| 0e0, '0e0 is falsy', | |
| # 3. 文字列の空文字列""および"0" | |
| "", '""(空文字) is falsy', | |
| "0", '"0" is falsy', | |
| ); | |
| for my ($v, $message) (@case) { | |
| my $got = $v ? 'true' : 'false'; | |
| my $expected = 'false'; | |
| is $got, $expected, $message; | |
| ok !is_bool($v), 'but not boolean'; | |
| } | |
| }; | |
| subtest 'falsyなスカラー以外は truthy' => sub { | |
| my @case = ( | |
| 1, '1 is truthy', | |
| 123, '123 is truthy', | |
| 'foo', 'foo is truthy', | |
| # falsy に見えるけれど、 truthy なもの | |
| " ", '" "(空白文字) is truthy', | |
| "00", '"00"(文字列) is truthy', | |
| "0.0", '"0.0"(文字列) is truthy', | |
| "0e0", '"0e0"(文字列) is truthy', | |
| \0, '\0 is truthy', | |
| {}, '{} is truthy', | |
| [], '[] is truthy', | |
| ); | |
| for my ($v, $message) (@case) { | |
| my $got = $v ? 'true' : 'false'; | |
| my $expected = 'true'; | |
| is $got, $expected, $message; | |
| ok !is_bool($v), 'but not boolean'; | |
| } | |
| }; | |
| }; | |
| subtest 'リストの場合' => sub { | |
| subtest '要素のある配列は、truthy' => sub { | |
| my @array = (1, 2, 3); | |
| my $got = @array ? true : false; | |
| is $got, true, 'non-empty array is truthy'; | |
| # この配列の配列長が3なので、 truthy になる。 | |
| is scalar @array, 3; | |
| }; | |
| subtest '空配列は、falsy' => sub { | |
| my @array = (); | |
| my $got = @array ? true : false; | |
| is $got, false, 'empty array is falsy'; | |
| # EXPR ? true : false の EXPR は、スカラーコンテキストの真偽評価される。 | |
| # 配列を、スカラーコンテキストで評価すると、配列長が得られる。 | |
| # 空配列の配列長は0なので、falsy になる。 | |
| is scalar @array, 0; | |
| }; | |
| subtest 'falsyな要素を含む配列は、truthy' => sub { | |
| my @array = (undef); | |
| my $got = @array ? true : false; | |
| is $got, true, 'array with falsy elements is truthy'; | |
| # この配列の配列長が1なので、 truthy になる。 | |
| is scalar @array, 1; | |
| }; | |
| subtest '要素のあるハッシュは、truthy' => sub { | |
| my %hash = (a => 1, b => 2); | |
| my $got = %hash ? true : false; | |
| is $got, true, 'non-empty hash is truthy'; | |
| # このハッシュのキーの数が2なので、 truthy になる。 | |
| is scalar %hash, 2; | |
| }; | |
| subtest '空ハッシュは、falsy' => sub { | |
| my %hash = (); | |
| my $got = %hash ? true : false; | |
| is $got, false, 'empty hash is falsy'; | |
| # ハッシュをスカラーコンテキストで評価すると、ハッシュのキーの数が得られる。 | |
| # (この挙動は、Perl5.25 以降 Ref: https://perldoc.perl.org/perldata#Scalar-values ) | |
| # 空のハッシュのキーの数は0なので、falsy になる。 | |
| is scalar %hash, 0; | |
| }; | |
| subtest 'リストに要素がある場合' => sub { | |
| my $got1 = (1, 2) ? true : false; | |
| is $got1, true, 'last element is truthy, so the list is truthy'; | |
| my $got2 = (1, undef) ? true : false; | |
| is $got2, false, 'last element is falsy, so the list is falsy'; | |
| # リストをスカラーコンテキストで評価する時、カンマはカンマ演算子。 | |
| # カンマ演算子は、`EXPR1, EXPR2` の時、EXPR1 を評価し、その結果を捨てて、次に EXPR2 を評価し、その結果を返す。これは、C言語のカンマ演算子と同じ | |
| # 結果的に、リストの最後の要素が得られる。 | |
| my $i = 0; | |
| my $got = ($i++, $i++, $i++, $i); | |
| is $got, 3, 'the last element is returned'; | |
| # 補足: リストをリストコンテキストで評価する時、カンマはただの区切り文字 | |
| # 例: `@array = (1,2)`、`@hash = (a=>1, b=>2)`、`for my $i (1,2,3) { ... }` など | |
| }; | |
| subtest '空リストは、falsy' => sub { | |
| my $got = () ? true : false; | |
| is $got, false, 'empty list is falsy'; | |
| # リストに最後の要素がないので、undefが得られる | |
| my $x = (); | |
| is $x, undef; | |
| }; | |
| }; | |
| done_testing; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use v5.42; | |
| use Test2::V0; | |
| package Sample { | |
| our $foo = "Hello"; | |
| our @foo = (1,2,3); | |
| our %foo = ( a => 1, b => 2 ); | |
| sub foo { return "bar" }; | |
| } | |
| subtest 'シンボルテーブルへのアクセス' => sub { | |
| # グロブリファレンスの利用例の一つが、シンボルテーブルへのアクセスです。 | |
| # Sampleパッケージのfooシンボルをすべて取得 | |
| # すべて取得するので、* ワイルドカードが記号として使われている | |
| my $glob = *Sample::foo; | |
| # グロブのリファレンスを取得 | |
| my $globref = \$glob; | |
| is reftype $globref, 'GLOB'; | |
| # Sample パッケージのfooシンボルの各スロットを確認 | |
| is *$globref{SCALAR}, \"Hello", 'SCALAR slot for globref'; | |
| is *$globref{ARRAY}, [1,2,3], 'ARRAY slot for globref'; | |
| is *$globref{HASH}, { a => 1, b => 2 }, 'HASH slot for globref'; | |
| is *$globref{CODE}->(), "bar", 'CODE slot for globref'; | |
| # シンボルテーブルにアクセスする典型的なコードは、一時的にシンボルの挙動を変更し、元に戻すようなコードです。 | |
| # 例えば、このコードは、Sampleのfoo関数を一時的に書き換えをしています。 | |
| # テストなどの場面で、よく使われるテクニックです。 | |
| { | |
| local *Sample::foo = sub { "modified" }; | |
| is Sample::foo(), "modified", 'CODE slot modified'; | |
| is *$globref{CODE}->(), "modified", 'CODE slot from globref'; | |
| } | |
| is Sample::foo(), "bar", 'CODE slot restored'; | |
| is *$globref{CODE}->(), "bar", 'CODE slot from globref restored'; | |
| }; | |
| subtest 'ファイルハンドル' => sub { | |
| # グロブリファレンスが自然と現れるもう一つの場面は、ファイルハンドルです | |
| # このファイル自身を開きます | |
| my $filepath = __FILE__; | |
| open my $fh, '<', $filepath or die $!; | |
| # openで指定したファイルハンドル$fhは、グロブリファレンスです。 | |
| is reftype $fh, 'GLOB', 'filehandle is also a globref'; | |
| # 内部的にはこのグロブリファレンスのIOスロットにIO::Fileオブジェクトとして格納されます。 | |
| is *$fh{IO}, check_isa('IO::File'), 'IO slot for filehandle'; | |
| # ダイヤモンド演算子<>で行を読み込むことができます。 | |
| my $first_line = <$fh>; | |
| is $first_line, "use v5.42;\n", 'first line of this file'; | |
| # IO::Handleのメソッドも利用できます | |
| my $second_line = $fh->getline(); | |
| is $second_line, "use Test2::V0;\n", 'second line of this file'; | |
| }; | |
| done_testing; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| use v5.42; | |
| use Test2::V0; | |
| package Sample { | |
| our $foo = "Hello"; | |
| our @foo = (1,2,3); | |
| our %foo = ( a => 1, b => 2 ); | |
| sub foo { return "bar" }; | |
| } | |
| subtest 'シンボルテーブルへのアクセス' => sub { | |
| # グロブリファレンスの利用例の一つが、シンボルテーブルへのアクセスです。 | |
| # Sampleパッケージのfooシンボルをすべて取得 | |
| # すべて取得するので、* ワイルドカードが記号として使われている | |
| my $glob = *Sample::foo; | |
| # グロブのリファレンスを取得 | |
| my $globref = \$glob; | |
| is reftype $globref, 'GLOB'; | |
| # Sample パッケージのfooシンボルの各スロットを確認 | |
| is *$globref{SCALAR}, \"Hello", 'SCALAR slot for globref'; | |
| is *$globref{ARRAY}, [1,2,3], 'ARRAY slot for globref'; | |
| is *$globref{HASH}, { a => 1, b => 2 }, 'HASH slot for globref'; | |
| is *$globref{CODE}->(), "bar", 'CODE slot for globref'; | |
| # シンボルテーブルにアクセスする典型的なコードは、一時的にシンボルの挙動を変更し、元に戻すようなコードです。 | |
| # 例えば、このコードは、Sampleのfoo関数を一時的に書き換えをしています。 | |
| # テストなどの場面で、よく使われるテクニックです。 | |
| { | |
| local *Sample::foo = sub { "modified" }; | |
| is Sample::foo(), "modified", 'CODE slot modified'; | |
| is *$globref{CODE}->(), "modified", 'CODE slot from globref'; | |
| } | |
| is Sample::foo(), "bar", 'CODE slot restored'; | |
| is *$globref{CODE}->(), "bar", 'CODE slot from globref restored'; | |
| }; | |
| subtest 'ファイルハンドル' => sub { | |
| # グロブリファレンスが自然と現れるもう一つの場面は、ファイルハンドルです | |
| # このファイル自身を開きます | |
| my $filepath = __FILE__; | |
| open my $fh, '<', $filepath or die $!; | |
| # openで指定したファイルハンドル$fhは、グロブリファレンスです。 | |
| is reftype $fh, 'GLOB', 'filehandle is also a globref'; | |
| # 内部的にはこのグロブリファレンスのIOスロットにIO::Fileオブジェクトとして格納されます。 | |
| is *$fh{IO}, check_isa('IO::File'), 'IO slot for filehandle'; | |
| # ダイヤモンド演算子<>で行を読み込むことができます。 | |
| my $first_line = <$fh>; | |
| is $first_line, "use v5.42;\n", 'first line of this file'; | |
| # IO::Handleのメソッドも利用できます | |
| my $second_line = $fh->getline(); | |
| is $second_line, "use Test2::V0;\n", 'second line of this file'; | |
| }; | |
| done_testing; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment