Slide 1

Slide 1 text

Perl ブートキャンプ id:onk 2025-11-14 YAPC::Fukuoka 2025 1

Slide 2

Slide 2 text

元ネタ: はてなインターン講義資料 2 2 特に最後にブートキャンプ講義を 担当した id:anatofuz

Slide 3

Slide 3 text

$self ● 大仲 能史 a.k.a. id:onk ● 芸歴20年目 ● 株式会社はてな ● チーフエンジニア 3

Slide 4

Slide 4 text

4 Perl 読んだこと/書いたこと ありますか?

Slide 5

Slide 5 text

5 Perl?

Slide 6

Slide 6 text

Perl? Perl(パール)とは、ラリー・ウォールによって開発さ れたプログラミング言語である。実用性と多様性を重視 しており、C言語やsed、awk、シェルスクリプトなど他 のプログラミング言語の優れた機能を取り入れている。 ウェブ・アプリケーション、システム管理、テキスト処 理などのプログラムを書くのに広く用いられている。 6

Slide 7

Slide 7 text

Perl? ● Goと違って、コンパイルをしないインタプリ タ型言語 ○ Better shell としても使えるし、ウェブアプリケー ションを書くことだってできる ● 素早いウェブ開発の道具として、古くから人 気のLightweight Language ○ はてな/DeNA/Mobile Factory/mixi/LINE... 7

Slide 8

Slide 8 text

Perl? ● Perl == Perl5 ○ 偶数が安定版、奇数が開発版 ● Perl6がリリースされた時期もあった ○ 今はRakuという別言語になっている ○ Perl5とPerl6(Raku)はJavaとJavaScriptくらいの差 がある 8

Slide 9

Slide 9 text

Perl? ● はてなでは今も元気に使っている ○ HTMLのテンプレートエンジンとして(Xslate) ○ GraphQLサーバーとして ● 他にもUNIXではよく使われている ○ git ○ Linux ○ LaTeX 9

Slide 10

Slide 10 text

10 今日のゴール

Slide 11

Slide 11 text

11 1時間強で 「Perl完全に理解した」 になる

Slide 12

Slide 12 text

ゴール 12 のはもちろん難しいので... ● 既存のコードを読むための取っ掛かりが作れ るようになる ○ 困ったときのインデックスとして ○ AIに聞くにも最低限の情報を持っていると便利 ● 周りのコードを参考にできる=書ける

Slide 13

Slide 13 text

Perlコードはこんな見た目 package Example::Greeter; use v5.42; sub greet { my ($class, $what) = @_; say "Hello, $what!"; } 13 ● モジュール ○ 拡張子は.pm

Slide 14

Slide 14 text

Perlコードはこんな見た目 14 ● メインスクリプト ○ 拡張子は.pl ● 実行 $ perl hello.pl Hello, World! use v5.42; use lib 'lib'; use Example::Greeter; Example::Greeter->greet('World');

Slide 15

Slide 15 text

15 Perlに触れていく前に...

Slide 16

Slide 16 text

ドキュメントはperldocで引く $ perldoc Carmel # モジュール (後述)のドキュメント $ perldoc -f print # 組み込み関数は -f $ perldoc -v @_ # 組み込み変数は -v $ perldoc perl 16

Slide 17

Slide 17 text

CPAN ● The Comprehensive Perl Archive Network ○ https://metacpan.org/ ● 世界中のさまざまなPerlモジュールが集まっ ている ● Perlの言語的な強みの一つ=コミュニティ 17

Slide 18

Slide 18 text

Carmel, Carton ● Rubyで言うBundler ○ cpanfile, cpanfile.snapshotで依存を管理して ○ carmel exec ...で実行する ● プロジェクトのlocal/に展開して使う ○ vendor/bundleと思えばOK 18

Slide 19

Slide 19 text

Perlとコミュニティ ● 日本でPerlが流行った理由の1つにコミュニ ティがある ○ なんとか.pmを始めた (Perl Mongers) ● アドベントカレンダー文化はPerlコミュニ ティ由来 ○ https://perl-users.jp/articles/advent-calendar/ 2008/ 19

Slide 20

Slide 20 text

Perlとコミュニティ ● YAPC::Japan ○ Yet Anotherな草の根カンファレンス ○ YAPC::Asiaの後継としてリブート ● TPRC ○ The Perl and Raku Conference ○ Formerly known as YAPC::NA 20

Slide 21

Slide 21 text

21 Perlの環境

Slide 22

Slide 22 text

非常に高い後方互換性 互換性を失った先は狂気です 後方互換性よりもはるかに高い「後方『バ グ』互換性」を守ってきました perldoc perlpolicy 22

Slide 23

Slide 23 text

Perlバージョン ● おそらくよく使われていたのはv5.8やv5.10 ○ 2002-2010 ○ CentOS 6のPerlが最後までv5.10.1だったはず ● v5.12からは毎年リリースしている ○ 現在v5.42 23

Slide 24

Slide 24 text

Perlバージョン ● 公式にサポートすると謳っているのは 最新2つの安定バージョンのみ ○ 今ならv5.42とv5.40 ● コミュニティ的にはv5.10も保守しているこ とが多い ○ Rubyで言うと1.9が出た時期 ○ さすがにv5.10は凄くてv5.16ぐらいをよく見る 24

Slide 25

Slide 25 text

Perlバージョン ● 最近は新しい書き方を取り入れている ○ built-in Boolean、defer、class構文、... ● バージョン指定によって動きが変わる ○ use v5.42; の行 ○ よりよいデフォルト値に 25

Slide 26

Slide 26 text

よりよいデフォルト値 ● 古い定型文が減る方向に ○ use strict; use warnings; ○ use strictはJSにも輸出された プラグマ ■ 互換性を壊さずに進化するため ● 良いfeatureを有効にする ○ say, module_true, isa, try, ... 26 use v5.42; # 以下の記述と同じ use warnings; use strict; no feature ':all'; use feature ':5.42';

Slide 27

Slide 27 text

use strict; use warnings; 27 ● ファイルの先頭には必ず書きましょう my $message = "hello"; print $messsage; # typo! # => エラーにならない! $messagge = "bye"; # typo! # => $messagge がグローバル変数になる!

Slide 28

Slide 28 text

前半戦 リファレンス見れば載ってるので 体力温存しながら聞いて 28

Slide 29

Slide 29 text

29 データ型

Slide 30

Slide 30 text

データ型 ● スカラー ● 配列 ● ハッシュ 30

Slide 31

Slide 31 text

データ型 > シジル ● $scalar, @array, %hashの記号がつきます ○ S/$, a/@, H/% が似てる、で覚えるらしい 31

Slide 32

Slide 32 text

データ型 > スカラー ● 「1つの値」 ● 文字列や数値、Bool、リファレンス 32

Slide 33

Slide 33 text

● Defined ○ Ref ■ ArrayRef ■ HashRef ■ ScalarRef ■ CodeRef ■ RegexpRef ■ GlobRef ■ FileHandle ■ Object データ型 > スカラー 33 ● Bool ● Undef ● Defined ○ Value ■ Str ● Int

Slide 34

Slide 34 text

データ型 > 配列 ● いわゆる配列です ○ my @array = (1, 2, 'foo', 'bar'); ● 1要素を取り出すときは$でアクセス ○ my $elem = $array[2]; ○ 超絶に分かりづらいと思う ■ $arrayも同時に存在できるので死 ■ 普段は直接配列を扱わずにArrayRefを使う(後述)ので 今は流してくれ 34

Slide 35

Slide 35 text

データ型 > 配列 ● 複数要素を取り出すときは@ ○ my @foo = @array[1,2] ● 分割代入もできます ○ my ($one, $two, @rest) = (1, 2, 'foo', 'bar'); ○ my ($foo) = @array; は先頭要素を取り出している 35

Slide 36

Slide 36 text

データ型 > 配列 36 ● 基本操作たち $array[0]; # get $array[1] = 'hoge'; # set my $length = scalar @array; # 長さ my $last_idx = $#array; # 最後の添字 my @slice = @array[1..4]; # スライス for my $e (@array) { # 全要素ループ print $e; }

Slide 37

Slide 37 text

データ型 > 配列 ● 最後の添字って何 ○ こういう使い方でeach_with_index的で便利 37 my @array = ('apple', 'banana', 'cherry'); my @result = map { "$_: $array[$_]" } 0..$#array; # => ('0: apple', '1: banana', '2: cherry')

Slide 38

Slide 38 text

データ型 > ハッシュ ● key, valueの組です ○ my %hash = (foo => 1, bar => 2); ● 取り出すときは $hash{foo} ○ =>の左や{}の中はbare wordが許される 38

Slide 39

Slide 39 text

データ型 > ハッシュ ● 配列との相互変換ができる ○ my @array = %hash; ○ my %hash = @array; ● => はfat commaと呼ばれる ○ my %h = (foo, 1) と my %h = (foo => 1) が同じ ○ hashにするときは要素が偶数じゃないとwarn 39

Slide 40

Slide 40 text

データ型 > ハッシュ ● 配列と何が違うの ○ 順序じゃなくキーでアクセスしたい、がそもそもの差 ○ my $name = $hash{name}; ● 代入時に何 ($, @, %) に入れるかが大事 40

Slide 41

Slide 41 text

データ型 > ハッシュ 41 ● 基本操作たち $hash{perl}; # get $hash{perl} = 'larry'; # set for my $key (keys %hash) { # 全要素のキー my $value = $hash{$key}; # キーで各要素を get }

Slide 42

Slide 42 text

データ型 > 真偽値 42 ● falseや0、空文字はfalsy ○ "0" もfalsy ● 空リストもfalsy ○ スカラーコンテキストで0になる(後述) ● 他はtruthy

Slide 43

Slide 43 text

43 リファレンス

Slide 44

Slide 44 text

リファレンス ● 素の配列やハッシュは素朴なリスト過ぎる ○ 配列もハッシュも、スカラーしか持てないため、 複雑なデータ構造を作れない ● 基本的にArrayRef, HashRefで生活します 44

Slide 45

Slide 45 text

リファレンス > ArrayRef 45 ● 入れ子の行列を作ってみるか... my @matrix = ( (0, 1, 2, 3), (4, 5, 6, 7), );

Slide 46

Slide 46 text

リファレンス > ArrayRef 46 ● このコードは配列の合成になる ○ リストを入れ子にできない my @matrix = (0, 1, 2, 3, 4, 5, 6, 7);

Slide 47

Slide 47 text

リファレンス > ArrayRef my @array = ('a', 'b', 'c'); my $ref = \@array; # @array へのリファレンス my $ref = ['a', 'b', 'c']; # 上記の略記。 # ちなみに \('a', 'b', 'c') は別物 47

Slide 48

Slide 48 text

リファレンス > ArrayRef # 2つのArrayRefをもった(長さ2の)配列 my @matrix = ( [0, 1, 2, 3], [4, 5, 6, 7], ); 48

Slide 49

Slide 49 text

リファレンス > ArrayRef 49 # 普段はArrayRefの中にArrayRefを入れる # ArrayRefはスカラーなのでシジルが $ に my $matrix = [ [0, 1, 2, 3], [4, 5, 6, 7], ];

Slide 50

Slide 50 text

リファレンス > ArrayRef 50 # デリファレンス my @array = @$ref; # 頭に @ をつけて配列に戻す # もしくは my $scalar = $ref->[1]; # -> を使って直接要素を取り出す ● リファレンスから値を取り出す

Slide 51

Slide 51 text

my %hash = ( perl => 'larry', ruby => 'matz', ); my $ref = \%hash; リファレンス > HashRef 51 # 略記 my $ref = { perl => 'larry', ruby => 'matz', };

Slide 52

Slide 52 text

リファレンス > HashRef 52 # % を頭につけてデリファレンス # keysは組み込み関数。ハッシュのキーの一覧を取得する my @keys = keys %$ref; print $ref->{perl}; # -> で直接アクセス ● リファレンスから値を取り出す

Slide 53

Slide 53 text

デリファレンスいろいろ 53 my $a_of_a = [ [1, 2, 3], [4, 5, 6],]; my @array = @{ $a_of_a->[1] }; ● なにかの式をデリファレンスするときは @{ ... } とか %{ ... } で囲む

Slide 54

Slide 54 text

デリファレンスいろいろ 54 my $a_of_a = [ [1, 2, 3], [4, 5, 6]]; my @array = $a_of_a->[1]->@*; # => (4, 5, 6) ● Postfix dereference

Slide 55

Slide 55 text

デリファレンスいろいろ 55 my $list = [1, 2, 3]; push @$list, 4; ● 必要なときだけデリファレンスする

Slide 56

Slide 56 text

56 コンテキスト

Slide 57

Slide 57 text

コンテキスト ● 代表的ハマりポイント ● 式が評価される場所( = コンテキスト)によっ て結果が変わる 57

Slide 58

Slide 58 text

コンテキスト 58 my @array = (10, 20, 30); my @x = @array; my $y = @array; my ($z) = @array; ● それぞれ何が入っているでしょうか

Slide 59

Slide 59 text

コンテキスト 59 my @array = (10, 20, 30); my @x = @array; # @array はリストコンテキストで評価される my $y = @array; # @array はスカラコンテキストで評価される my ($z) = @array; # @array はリストコンテキストで評価される ● それぞれ何が入っているでしょうか

Slide 60

Slide 60 text

● $yには、配列をスカラコンテキストで評価す るので個数が返る コンテキスト 60 my @array = (10, 20, 30); my @x = @array; # @x = (10, 20, 30) my $y = @array; # $y = 3 my ($z) = @array; # $z = 10

Slide 61

Slide 61 text

● $zには、配列の先頭要素が代入され、残りは 捨てられている コンテキスト 61 my @array = (10, 20, 30); my @x = @array; # @x = (10, 20, 30) my $y = @array; # $y = 3 my ($z) = @array; # $z = 10

Slide 62

Slide 62 text

● ifの条件式はスカラコンテキスト ● 要素があればtruthy、空配列は0になりfalsy コンテキストは便利 62 if (@$items) { ... }

Slide 63

Slide 63 text

63 演算子、制御構造

Slide 64

Slide 64 text

演算子 64 ● 普通の演算子はだいたいある ○ defined-or (//) があるのは便利 ● 文字列の比較は == ではなく eq ○ ==は数値比較用なので注意 ○ 文字列比較にはeq, ne, gt, le等を用いる

Slide 65

Slide 65 text

制御構造 65 ● if文とかは想像通りのものがだいたいある ○ else if は無くelsif ● forとforeachは同じキーワード ○ for my $e (@$array) ○ foreach my $e (@$array)

Slide 66

Slide 66 text

制御構造 66 ● for my $e と受けないと$_が使われる ○ for (@$array) { say $_ }; ○ $_はここでは処理中の要素を表す特殊変数 ● forのキーワードは珍しいか? ○ continueではなくnext, breakではなくlast

Slide 67

Slide 67 text

Enumerable色々 67 my $items = [(3..7)]; for my $item (@$items) { ... } my $res = [ grep { $_ % 2 } @$items ]; # => # [3, 5, 7]

Slide 68

Slide 68 text

Enumerable色々 68 my $items = [(3..7)]; my $doubled = [ map { $_ * 2 } @$items ]; #=> [6, 8, 10, 12, 14] use List::Util qw(all); if (all { $_ > 0 } @$items) { say "すべて 0 より大きい" } # List::Util には min, uniq, sample, first 等だいたいある

Slide 69

Slide 69 text

例外 69 ● ないことはない (eval期) ● 便利モジュールでやる (Try::Tiny期) ● そこにある (try-catch期)

Slide 70

Slide 70 text

例外 70 # eval ブロックでエラーをトラップする # (これは典型的なよくないコードだけどevalブロックの説明のため) eval { ...; }; if ($@) { # eval内で死ぬと特殊変数$@にエラーメッセージが入る ...; }

Slide 71

Slide 71 text

例外 71 use Try::Tiny; try { ...; } catch { my $err = $_; # $_にエラーメッセージが入っている # die $err; # 再スロー };

Slide 72

Slide 72 text

例外 72 # feature try で圧倒的自然なコードに try { ...; } catch ($e) { ...; }

Slide 73

Slide 73 text

73 サブルーチン

Slide 74

Slide 74 text

サブルーチン 74 # サブルーチン宣言 sub foo { my ($a, $b, $c) = @_; } # サブルーチン呼び出し foo(1, 2, 3); # 引数なしで呼び出す場合はカッコを省略できる

Slide 75

Slide 75 text

サブルーチン > 引数 75 sub add { my ($x, $y) = @_; return $x + $y; } my $three = add(1, 2); ● 引数1,2は@_という特殊な配列に格納される ○ これが($x, $y)に分割代入される

Slide 76

Slide 76 text

サブルーチン > 引数 76 sub add { my $x = shift; my $y = $_[0]; # shift したので y が先頭要素 return $x + $y; } ● shiftを使う ○ 引数なしだと暗黙的に@_になり、先頭要素を取り出す ● $_[0]で配列の最初を取り出すことも

Slide 77

Slide 77 text

サブルーチン > 引数 77 sub func1 { my ($arg1, $arg2, %args) = @_; my $opt1 = $args{opt1}; my $opt2 = $args{opt2}; } func1('hoge', 'fuga', opt1 => 1, opt2 => 2); ● よくやるイディオム ○ 最後に%argsと受けると省略可能な名前付き引数に

Slide 78

Slide 78 text

サブルーチン > 引数(現代) 78 sub add($x, $y) { return $x + $y; } ● Perl界にも仮引数があります! ● 私はISUCON以外で見たことない

Slide 79

Slide 79 text

サブルーチン > はてなでは 79 use Smart::Args::TypeTiny qw(args); sub add { args my $x => 'Int', my $y => 'Int'; return $x + $y; } ● 実行時型チェックも同時に実現する Smart::Args::TypeTinyを使っている

Slide 80

Slide 80 text

サブルーチン > 値の返し方 80 ● returnで返せるが、省略可能 ● 省略した場合は最後に評価された式の返り値

Slide 81

Slide 81 text

サブルーチン > 値の返し方 81 sub swap_list($x, $y) { return ($y, $x) } my ($x, $y) = swap_list('Hello','World'); #=> ($x: World', $y: 'Hello') ● 多値を返して分割代入で受けられる ○ スカラーで受け取ると個数になるから注意

Slide 82

Slide 82 text

サブルーチン > 引数 82 ● 無名サブルーチンを引数で渡すのもよく見る ○ 高階関数やブロックと同じ sub with_block { say "start"; $_[0]->(); # 渡された無名サブルーチンを実行 say "end"; } with_block(sub { say "in block" });

Slide 83

Slide 83 text

83 パッケージ

Slide 84

Slide 84 text

パッケージ 84 ● 名前空間 ● モジュールロードのしくみ ● クラス(後述)

Slide 85

Slide 85 text

パッケージ > 名前空間 85 package Example::Greeter; ● と書くと、それ以降のコードは Example::Greeter名前空間に属する ● パッケージとは関数等の名前が所属する先

Slide 86

Slide 86 text

パッケージ > 名前空間 86 package A; sub foo { ... } package B; sub bar { ... } ● それぞれA::foo、B::barで呼び出せる

Slide 87

Slide 87 text

パッケージ > モジュールロードの仕組 み 87 use My::File; # => My/File.pm がロードされる ● @INC(グローバル変数)に設定されたパスを検索 ○ 慣習的に ./lib を@INCに含めている

Slide 88

Slide 88 text

パッケージ > モジュールロードの仕組 み 88 use My::File; # => My/File.pm がロードされる ● .pm=PerlModule。書き捨て以外は基本.pm ● Carmel/Cartonで入れる他、コアモジュール (Perlインストール時に同梱)が数百ある ○ $ corelist -v v5.34.1 で見てみよう

Slide 89

Slide 89 text

89 ここで休憩

Slide 90

Slide 90 text

90 オブジェクト指向

Slide 91

Slide 91 text

● オブジェクトとは ○ プログラムの対象となるモノ ○ データ + 手続き ● クラスで実装されることが多い ○ クラスには自身の持つデータに対する手続き(メソッ ド)が定義されている オブジェクト指向 91

Slide 92

Slide 92 text

オブジェクト指向 ● Perlはもともとオブジェクト指向言語として 始まったわけではないので後付け ○ ここが非常に面白い ● パッケージとリファレンスだけで使える 92

Slide 93

Slide 93 text

オブジェクト指向 93 OOP用語 Perlでの用語 クラス パッケージ メソッド パッケージに定義された 関数 オブジェクト パッケージにblessされた リファレンス

Slide 94

Slide 94 text

bless 94 # なんかデータがある(普通はハッシュリファレンス) my $data = { name => 'motemen' }; # データにパッケージを紐付けると my $self = bless $data, 'Hatena::Engineer'; # メソッドが呼べる! ここでは Hatena::Engineer::tweet $self->tweet();

Slide 95

Slide 95 text

いいか、みんな         (゚д゚ )         (| y |) ハッシュリファレンスと package では手続き型プログラミングしかできないが       {}  ( ゚д゚) package        \/| y |\/     二つ合わさればOOPとなる         ( ゚д゚)  bless         (\/\/ オブジェクト指向 95

Slide 96

Slide 96 text

● コンストラクタも自分で書く ○ newは慣習的な命名 オブジェクト指向 > コンストラクタ 96 package Person; use v5.42; sub new { my ($class, %args) = @_; return bless \%args, $class; }

Slide 97

Slide 97 text

● Person->new(age => 18)は Person::new('Person', age => 18) オブジェクト指向 > コンストラクタ 97 my $person = Person->new(age => 18); # { age => 18 } が Person に bless されたもの

Slide 98

Slide 98 text

● Klass->fooはKlass::foo('Klass')の糖衣構文 ● $obj->fooはKlass::foo($obj)の糖衣構文 ○ blessしているので$objからKlassに辿れる オブジェクト指向 98 package Klass; sub class_method { my ($class, %args) = @_; ...; } package Klass; sub instance_method { my ($self, %args) = @_; ...; }

Slide 99

Slide 99 text

オブジェクト指向言語として使う 99 my $person = Person->new(name => 'motemen', age => 18); # 元々 HashRef を bless しただけなので中身にアクセス可能 $person->{age} = 3; # だけど、当然 $person->age(3) でアクセスする package Person; sub age { $self = shift; $self->{age} = $_[0]; }

Slide 100

Slide 100 text

オブジェクト指向 後付けだが、データと手続きを繋げるblessの 導入と、ちょっとした糖衣構文だけで、手作 り感のあるオブジェクト指向だけど言語仕様 に非常に綺麗に収まっている 100

Slide 101

Slide 101 text

package Person; use Class::Accessor::Lite ( new => 1, rw => [ qw(name age) ], ); オブジェクト指向(ライブラリ) 101 ● ものすごく書きやすくて便利だったが……

Slide 102

Slide 102 text

オブジェクト指向(現代) 102 use v5.42; use experimental 'class'; # まだ experimental だが class Person { # class 記法が入った! field $name :param :reader; # 属性とアクセサ定義 method hello { say "Hi, I'm $name." } # メソッド定義 } my $onk = Person->new(name => 'onk'); $onk->hello;

Slide 103

Slide 103 text

103 スコープ

Slide 104

Slide 104 text

{ my $x = 10; say $x; # 10 } say $x; # エラー(見えない) スコープ ● 変数の見える範囲 ○ myはレキシカルスコープ内に限定する宣言 ○ スコープを絞るために任意にブロックを作れる 104

Slide 105

Slide 105 text

スコープ 105 ● スコープ単位での変更を多用する文化 ○ use strict; のようなプラグマもスコープ単位 ● 参照カウント方式のメモリ管理の影響? ○ スコープを抜けるときに破棄されるので

Slide 106

Slide 106 text

106 入出力

Slide 107

Slide 107 text

入出力 > 読み込み 107 open my $fh, '<', 'input.txt' or die $!; while (my $line = <$fh>) { ...; } close $fh; ● 有名なor die ○ or の優先順位が低いおかげでカッコが要らない ○ ( open my $fh, '<', $file ) or die $!

Slide 108

Slide 108 text

open my $fh, '<', 'input.txt' or die $!; local $/ = undef; # 入力区切り文字を変更 my $content = <$fh>; # ファイル全体を一度に読める close $fh; 入出力 > 読み込み 108 ● いわゆるslurpパターン ● 行指向言語なことを示していて慣れたら好き

Slide 109

Slide 109 text

my $content = do { # スコープを抜けたら自動 close open my $fh, '<', 'input.txt' or die $!; local $/; # 代入しなくても undef になる <$fh>; }; 入出力 > 読み込み 109 ● こういう書き方をしているところも多いかも ○ do {} はブロックの結果を式として返す

Slide 110

Slide 110 text

open my $fh, '>', 'output.txt' or die $!; print $fh "Hello\n"; close $fh; 入出力 > 書き込み 110 ● printの第1引数にファイルハンドルを渡す ○ デフォルトでSTDOUT ○ 第1引数なのにカンマがないけどそういうものらしい

Slide 111

Slide 111 text

111 特殊変数

Slide 112

Slide 112 text

特殊変数 112 ● 今まで説明してきたもの ○ $_ : 色んなところで使う。mapやgrepの処理対象等 ○ @_ : 引数 ○ $@ : evalブロックの例外メッセージ ○ $! : システムコール失敗時のエラーメッセージ ○ $/ : 入力の区切り文字

Slide 113

Slide 113 text

特殊変数 113 ● English module で別名が付いている ○ $_ : $ARG ○ @_ : @ARG ○ $@ : $EVAL_ERROR ○ $! : $ERRNO ○ $/ : $INPUT_RECORD_SEPARATOR

Slide 114

Slide 114 text

114 UTF-8

Slide 115

Slide 115 text

use utf8; 115 ● Perlでは文字列は以下のどちらか ○ Perl の内部表現に変換された文字列 ○ バイト列

Slide 116

Slide 116 text

print 'ほげ'; use utf8; 116 ● UTF-8 でファイル(hoge.pl)に保存します ● 実行します $ perl hoge.pl ほげ ● ええやん

Slide 117

Slide 117 text

print length 'ほげ'; use utf8; 117 ● length は文字数をカウントする関数 ● 実行します $ perl hoge.pl 6 ● あかんやん

Slide 118

Slide 118 text

use utf8; 118 ● 'ほげ' はマルチバイト文字 ● 何もしないとPerlは'ほげ'をバイト列とみなす ● UTF-8だと6バイトなのでlengthが6になる ● 文字数数えるのに (それ以外も色々) 困る

Slide 119

Slide 119 text

use utf8; print length 'ほげ'; use utf8; 119 ● そこでuse utf8; ● 実行します $ perl hoge.pl 2 ● ええやん!

Slide 120

Slide 120 text

use utf8; 120 ● utf8 プラグマをつけると Perl はコード内の マルチバイト文字を UTF-8 の文字列として解 釈し、Perl 内部表現の文字列に変換する ● UTF-8 で記述された "ほげ" を UTF-8 として 解釈すると length "ほげ" は 2 になる

Slide 121

Slide 121 text

use utf8; print 'ほげ'; use utf8; 121 ● けど…… $ perl hoge.pl Wide character in say at hoge.pl line 2. ほげ ● なんか出た

Slide 122

Slide 122 text

use utf8; 122 ● Perl内部文字列になっている"ほげ"をそのま まPerlの世界の外に出そうとすると怒られる ● 再びバイト列に変換してあげる必要がある

Slide 123

Slide 123 text

use utf8; use Encode qw(encode_utf8); print encode_utf8 'ほげ'; use utf8; 123 ● これでOK

Slide 124

Slide 124 text

use utf8; 124 ● utf8プラグマは文字列リテラルに効く ○ 自動的に内部文字列になる ● プログラムの外から渡された値は自分で内部 文字列に変換する ○ decode_utf8; ● 入口でdecode、出口でencodeの鉄則

Slide 125

Slide 125 text

use utf8; 125 ● これはガチ ● 「ããã¯ã¬ãぁぁはぬぁ」を見て気 づけるようになる

Slide 126

Slide 126 text

126 正規表現

Slide 127

Slide 127 text

正規表現 127 ● Perlと言えば正規表現 ○ 出自からしてテキスト処理に特化 ○ Practical Extraction and Report Language ● 正規表現リテラルで、読み下しやすい if ($line =~ /ERROR/) { warn "error detected"; }

Slide 128

Slide 128 text

正規表現 128 ● m// マッチ演算子 ○ if ($str =~ m/foo/) { ... } # m は省略可 ● s/// 置換演算子 ○ $str =~ s/foo/bar/; ■ $strを破壊的に変更する ○ Perl v5.14 で非破壊操作が可能になった ■ my $new = $str =~ s/foo/bar/r;

Slide 129

Slide 129 text

正規表現 129 while () { next unless /^ERROR\b/; # $_ =~ m/^ERROR\b/ と同じ s/^ERROR\s+//; # $_ を破壊的に書き換える print; # これも $_ 省略 } ● 暗黙の$_を使うと急に読みづらくなるが、 慣れてるとサラッと書ける

Slide 130

Slide 130 text

正規表現 > PCRE 130 ● Perl Compatible Regular Expressions ● CライブラリとしてPerl以外からでも使えるよ うに ○ grep -PとかPHPとかに輸出されている

Slide 131

Slide 131 text

131 テスト

Slide 132

Slide 132 text

テスト 132 ● テストを書くエコシステムが整っている ○ prove というテスト実行用コマンドを同梱 ● テストはt/ディレクトリ以下に置く ○ 拡張子は.t(中身はPerlスクリプト)

Slide 133

Slide 133 text

テスト 133 use Test2::V0; use Person; my $person = Person->new(age => 18); is $person->age, 18, '最初は18歳'; $person->incr_age; is $person->age, 19, 'incr_age 呼んだら19歳'; done_testing;

Slide 134

Slide 134 text

テスト 134 $ prove -lv t/Person.t .. # Seeded srand with seed '20251114' from local date. ok 1 - 最初は18歳 ok 2 - incr_age 呼んだら19歳 1..2 ok All tests successful. Files=1, Tests=2, 0 wallclock secs ( 0.00 usr 0.00 sys + 0.02 cusr 0.00 csys = 0.02 CPU) Result: PASS

Slide 135

Slide 135 text

テスト 135 ● テスト結果をTAP形式で表示 ○ Test Anything Protocol ○ TAPを読み取って加工するエコシステムがある ● テストはファイル単位 ○ .t ファイルが独立している ○ 分散テスト=テスト対象ファイルを分割するだけ

Slide 136

Slide 136 text

136 よくある罠5選

Slide 137

Slide 137 text

autovivification 137 my $config = {}; if ($config->{foo}->{bar} eq 'debug') { ...; } # autovivification によって $config->{foo} がHashRefに変化 # $config = { foo => { } }

Slide 138

Slide 138 text

文字列と数値の区別を付けづらい 138 ● 文字列と数値の区別が非常に弱い ● 文字列にしたらJSON出力も文字列になる ○ { "id": "1" } ○ params も DB からの取得も基本は文字列…… ● $val+0, $val.'' というテクニック ○ 数値と計算すると数値に、文字列と結合すると文字列に ○ JSON::Types という最高のライブラリ

Slide 139

Slide 139 text

localtimeでコンテキストを間違える 139 ● localtime ○ 現在時刻を取得できる関数 ● スカラコンテキスト ○ Fri Nov 14 13:07:32 2025 ● リストコンテキスト ○ (32, 7, 13, 14, 10, '125', 5, 317, 0);

Slide 140

Slide 140 text

$_[0]に破壊的変更 140 ● @_ を直接触ると、呼び出し元の値が変わる ● 引数を一度 ($x) = @_; 等で引数に受けた後は $x に破壊的な変更をしても大丈夫

Slide 141

Slide 141 text

意図しないカンマ演算子 ● my $a = ("a", "b", "c"); は $a に "c" が入る ● カンマ演算子は複数の式を左から順に評価し、 最後の式の値を返す演算子 ○ my $x = (print "a", print "b", 100); ○ ab を出力して $x == 100 になる ○ 短絡評価のない && みたいな 141

Slide 142

Slide 142 text

142 まとめ

Slide 143

Slide 143 text

まとめ データ型 リファレンス コンテキスト 演算子 制御構造 143 サブルーチン モジュール オブジェクト指向 入出力 スコープ 特殊変数 UTF-8 正規表現 テスト 罠5選

Slide 144

Slide 144 text

まとめ ● Perlの読み書きに必要なものと、知っている と面白い情報をまとめてお伝えした ● これで今日からあなたもPerl Monger 144