Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
prototype大全 / YAPC::Kyoto 2023
Search
utagawa kiki
March 19, 2023
Programming
1
4.4k
prototype大全 / YAPC::Kyoto 2023
サンプルコードはGitHubで公開しています
https://github.com/utgwkk/yapc-kyoto-2023-prototype
utagawa kiki
March 19, 2023
Tweet
Share
More Decks by utagawa kiki
See All by utagawa kiki
ゆるやかにgolangci-lintのルールを強くする / Kyoto.go #56
utgwkk
2
390
君たちはどうコードをレビューする (される) か / 大吉祥寺.pm
utgwkk
21
13k
Dive into gomock / Go Conference 2024
utgwkk
14
5.4k
Goでリフレクションする、その前に / Kansai.go #1
utgwkk
5
2k
Go製Webアプリケーションのエラーとの向き合い方大全、あるいはやっぱりスタックトレース欲しいやん / Kyoto.go #50
utgwkk
7
3.4k
ありがとう、create-react-app
utgwkk
4
10k
mockgenによるモック生成を高速化するツール bulkmockgenのご紹介 / Kyoto.go #43
utgwkk
2
2.2k
SPAでもデータをURLでシェアしたい / Kyoto.js 19
utgwkk
2
1.8k
なんでもPull Requestにする / Kichijoji.pm 31
utgwkk
3
6.3k
Other Decks in Programming
See All in Programming
Jakarta EE meets AI
ivargrimstad
0
250
暇に任せてProxmoxコンソール 作ってみました
karugamo
2
720
Haze - Real time background blurring
chrisbanes
1
510
フロントエンドのディレクトリ構成どうしてる? Feature-Sliced Design 導入体験談
osakatechlab
8
4.1k
創造的活動から切り拓く新たなキャリア 好きから始めてみる夜勤オペレーターからSREへの転身
yjszk
1
130
テストコード書いてみませんか?
onopon
2
110
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
240
From Translations to Multi Dimension Entities
alexanderschranz
2
130
「とりあえず動く」コードはよい、「読みやすい」コードはもっとよい / Code that 'just works' is good, but code that is 'readable' is even better.
mkmk884
3
390
Kaigi on Railsに初参加したら、その日にLT登壇が決定した件について
tama50505
0
100
PHPUnitしか使ってこなかった 一般PHPerがPestに乗り換えた実録
mashirou1234
0
190
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
120
Featured
See All Featured
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
Fontdeck: Realign not Redesign
paulrobertlloyd
82
5.3k
We Have a Design System, Now What?
morganepeng
51
7.3k
Keith and Marios Guide to Fast Websites
keithpitt
410
22k
Code Reviewing Like a Champion
maltzj
520
39k
How to train your dragon (web standard)
notwaldorf
88
5.7k
Fashionably flexible responsive web design (full day workshop)
malarkey
405
66k
Rails Girls Zürich Keynote
gr2m
94
13k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
28
4.4k
Facilitating Awesome Meetings
lara
50
6.1k
Adopting Sorbet at Scale
ufuk
73
9.1k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Transcript
prototype大全 YAPC::Kyoto 2023 @utgwkk (うたがわきき)
自己紹介 @utgwkk (うたがわきき) 株式会社はてな Webアプリケーションエンジニア in 京都 最近は主にGoを書いて暮らしています
突然ですがこちらのコードをご覧ください (1) push @arr, "new value"; map { $_ +
2 } @arr; try { everything() } catch { up() };
突然ですがこちらのコードをご覧ください (2) push @arr, "new value"; # なんでこれでpushできるの? map {
$_ + 2 } @arr; # { } の中は何? try { everything() } catch { up() }; # try-catchだ!!1 →prototypeが関係している
今日の目標 (1) push @arr, "new value"; map { $_ +
2 } @arr; try { everything() } catch { up() }; これらの裏で起こっていることからprototypeを読み解く
今日の目標 (2) ↓のサブルーチン定義 (prototype) の意味が分かるようになる sub foo ($) { }
sub bar ($;$@) { } sub mymap (&@) { } sub zip (\@\@) { } sub foo () { 1 }
try-catchから始めるprototype入門
prototypeとは とても限られた形のコンパイル時引数チェック サブルーチンの引数の解釈方法を制御できる パーサーの挙動が変わる!! (表現力が上がる) メソッドにはprototypeを指定できない
prototypeの書き方 (1) sub name (prototype) { ... } サブルーチン定義の後ろに括弧で書く sub
name :prototype(prototype) { ... } attributeを使うこともできる (subroutine signaturesと衝突しない)
prototypeの書き方 (2) sub name (prototype) { ... } ← この発表ではこっちを使う
サブルーチン定義の後ろに括弧で書く sub name :prototype(prototype) { ... } attributeを使うこともできる (subroutine signaturesと衝突しない)
prototypeに出てくる記号 シジル (変数につける記号) に対応すると考えるとよさそう $はscalar, @はlist, %はhash, &はサブルーチン, *はglob \を付けるとリファレンスになる
\[] で囲むといずれか1つのリファレンス (バックスラッシュが必要) ; 以降は省略可能
prototypeの例 sub foo ($) { } sub bar ($;$@) {
} sub mymap (&@) { } sub zip (\@\@) { } sub foo () { 1 }
prototypeの読み方 (再掲) sub foo ($) { } # 括弧の中に記号を書く sub
bar ($;$@) { } # ; 以降は省略可能 sub mymap (&@) { } # &はサブルーチン、@はリスト sub zip (\@\@) { } # リストをリファレンスとして受ける sub foo () { 1 } # 定数をreturnなしで返する
prototypeに書けるもの だいたいなんでも書けてすごい だいたいなんでも書けるけどwarningされる sub f (hello!!1) { } # prototypeは
hello!!1 sub g (こんにちは) { } # prototypeは こんにちは なんでだいたいなんでも書けるのかは不明 (知ってたら教えてください)
prototypeの例 (Try::Tiny) try-catch構文をprototypeで再現 https://metacpan.org/pod/Try::Tiny try { } catch { }
finally { }; 最近のPerlにはtry-catch構文が組み込まれている
Try::Tinyのコードを読んでいく (1) sub try(&;@) try-catch構文のスタート コードブロック (無名サブルーチン) を受け取る 省略せずに書くと try(sub
{ }, ...) 例外が送出されたらcatch/finallyブロックの処理が実行される
Try::Tinyのコードを読んでいく (2) sub catch(&;@) 例外を捕捉する ブロック内では $_ 変数に例外の内容が入っている 省略せずに書くと catch(sub
{ }, ...) Try::Tiny::Catch packageでblessしているけど実体は無名サブルーチン
Try::Tinyのコードを読んでいく (3) sub finally(&;@) try-catchの最後に必ず呼ばれる finallyブロックの処理はTry::Tiny::ScopeGuard packageでblessされる
Try::Tinyのコードを読んでいく (まとめ) try { } catch { } finally {
}; try(sub { }, catch(sub { }, finally(sub { }))); 単なるサブルーチン呼び出し式なので、ブロックの後ろに ; が必要 ブロックではなく無名サブルーチンなのでreturnしても関数全体を抜けない (罠)
ちなみに別のtry-catchは? Syntax::Keyword::Try syntax pluginという仕組みでtry-catch構文を再現 (セミコロン不要) 詳細は以下の記事など Syntax::Keyword::TryとPerlのキーワードプラグイン (その1) - Masteries
最近のPerlにはtry-catch構文が組み込まれている (再掲)
prototypeについて網羅的に知るには (1) perldoc perlsubにまとまっている 今回解説しきれていない項目もあります https://perldoc.perl.org/perlsub#Prototypes https://perldoc.jp/docs/perl/5.36.0/perlsub.pod#Prototypes
prototypeについて網羅的に知るには (2) prototypeを使ってtry-catch構文を再現する例がperldoc perlsubに書いてある!!
こんなにあるぞ!! prototype
こんなにあるぞ!! prototype prototypeによって得られている効能についてご紹介します
リストにpushするには push @arr, @elems; sub mypush(\@@) 第1引数はリストのリファレンスを受け取る 第2引数以降はリストとして解釈される 第1引数のリストに破壊的変更を加えることができる
mapの正体 map { $_ + 2 } @arr; ブロックだと思っているのは無名サブルーチン ブロック内でreturnしてもサブルーチン全体から抜けるわけではない
紛らわしいのでブロックに渡すサブルーチンを用意するのがよさそう
定数展開 sub a1 () { "aaa" } say a1 .
"bbb"; コンパイル時に say "aaabbb" に展開される use constantしたときと似たような効能が得られる sub a2 { "aaa" } だと展開されない https://perldoc.perl.org/perlsub#Constant-Functions
身近に潜むprototype採用事例 (Test2::V0) is $obj, object { prop isa => 'Foo';
call meth => 'blah'; }; $obj の性質を宣言的にテストできる ちなみにTest::Deepだと↓のように書ける cmp_deeply $obj, isa('Foo') & methods(meth => 'blah);
身近に潜むprototype採用事例 (Module::Find) usesub Foo::Plugin; indirectだと思って読むと Foo::Plugin->usesub になるのでは? sub usesub(*) {
… } barewordを受け取ってパッケージ名だと解釈できる
身近に潜むprototype採用事例 (Scope::Guard) my $g = guard { }; 変数 $g
のスコープが終わったらブロックに渡した処理が呼ばれる これも無名サブルーチン スコープが終わったらDESTROYメソッドが呼ばれる 最近のPerlだとdeferがある (experimental)
身近に潜むprototype採用事例 (List::MoreUtils) (1) zip6 @xs, @ys, @zs; 6はPerl6 (現Raku) の6
別名zip_unflatten [$xs[0], $ys[0], $zs[0]], [$xs[1], $ys[1], $zs[1]], ... のリストを返す
身近に潜むprototype採用事例 (List::MoreUtils) (2) ところで say @xs, @ys, @zs ってやったらリストが平坦になるのでは? zip6
@xs, @ys, @zs では各リストはリファレンスとして渡されている リファレンスなら平坦になることはない % perl -E '@xs = (1, 2); @ys = (3, 4); @zs = (5, 6); say @xs, @ys, @zs' 123456
身近に潜むprototype採用事例 (List::MoreUtils) (3) sub zip6 (\@\@;\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\@\ @\@\@\@\@) \@ が32個!! 一番好きなprototypeです
リストを33個渡すとコンパイルエラーになる (無限に渡せない) https://metacpan.org/release/REHSACK/List-MoreUtils-0.430/source/lib/List/More Utils/PP.pm#L520
身近に潜むprototype採用事例 (List::MoreUtils) (4) 実際にリストを33個渡してみましょう…… (ここでデモ)
身近に潜むprototype採用事例 (List::MoreUtils) (5) % carmel exec perl 02-list-moreutils-zip6.pl Too many
arguments for List::MoreUtils::XS::zip6 at 02-list-moreutils-zip6.pl line 16, near ")" Execution of 02-list-moreutils-zip6.pl aborted due to compilation errors.
身近に潜むprototype採用事例 (ほかいろいろ) きっと無限にprototype採用事例があるはず!! 心当たりがある方はTwitterとかでシェアーしてください
気になるあのサブルーチンのprototype、 コッソリ教えます
prototypeサブルーチン https://perldoc.perl.org/functions/prototype サブルーチンのprototypeを文字列として返す 組み込みサブルーチンのprototypeはうまく取得できないことがある (mapとか)
組み込みサブルーチンのprototype 実はperldoc perlsubに例示されている (全てではない) https://perldoc.perl.org/perlsub#Prototypes
実装を読みにいったほうが早い説 サブルーチン定義をがんばって探す XSなら PROTOTYPE: に書いてある けどREPLとかでサクッと見れるのはよいと思う
Deparseすると何が起こっているのか分かる説 perl -MO=Deparse は友達 どのように構文解析されたのかが分かる コンパイラの気持ちを知れば何が起こっているのかが分かるかも
prototypeを使う/使わない理由
prototypeを使う理由 DSL的に書きたい かっこよく書けるとかっこいい subって書きたくない あわよくばコンパイラの最適化を効かせたい
prototypeを使わない理由 ブロックのつもりで書いても無名関数になる 最近のPerlにはtry-catch構文が入っている なんでもprototypeを使えばよいというものではない (銀の弾丸ではない) use constantでよくない??
おさらい 読めるようになりましたね? sub foo ($) { } sub bar ($;$@)
{ } sub mymap (&@) { } sub zip (\@\@) { } sub foo () { 1 }
おわり prototypeによってPerlコードの表現力が広がる とはいえprototypeを濫用すればするほどよいというものではない 用法用量を守って楽しいprototypeライフを送りましょう { } は無名サブルーチンだというのを忘れずにいると罠を回避できるかも?
参考文献 • https://perldoc.perl.org/perlsub • https://perldoc.jp/docs/perl/5.36.0/perlsub.pod#Prototypes • https://metacpan.org/pod/Try::Tiny • https://papix.hatenablog.com/entry/2019/12/02/170611 •
https://metacpan.org/pod/Test2::V0 • https://metacpan.org/pod/List::MoreUtils • https://metacpan.org/pod/Scope::Guard • https://perldoc.perl.org/functions/prototype
サンプルコード https://github.com/utgwkk/yapc-kyoto-2023-prototype で公開しています