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.3k
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
君たちはどうコードをレビューする (される) か / 大吉祥寺.pm
utgwkk
21
12k
Dive into gomock / Go Conference 2024
utgwkk
14
4.8k
Goでリフレクションする、その前に / Kansai.go #1
utgwkk
5
1.6k
Go製Webアプリケーションのエラーとの向き合い方大全、あるいはやっぱりスタックトレース欲しいやん / Kyoto.go #50
utgwkk
7
2.9k
ありがとう、create-react-app
utgwkk
4
9.9k
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.2k
インプットとアウトプットのサイクルを回す暮らし / Kichijoji.pm 29
utgwkk
1
9k
Other Decks in Programming
See All in Programming
Cloud Adoption Framework にみる組織とクラウド導入戦略
tomokusaba
2
670
Going Staff - Keynote edition
pragtob
0
340
Програмиране с Rust, ФМИ, 2024
nikolads
0
120
Competitionsだけじゃない! Kaggle Notebooks Grandmasterのすすめ
corochann
2
920
DevFest Android in Korea 2024 - 안드로이드의 문단속 : 앱을 지키는 암호화 이야기
mdb1217
1
170
ポケモンで考えるコミュニケーション / Communication Lessons from Pokémon
mackey0225
5
220
Modern Functional Fluent CFML REST by Luis Majano
ortus24
0
160
ACES Meet におけるリリース作業改善の取り組み
fukucheee
0
150
Mercari AI/LLM Hackathon TeamBの発表資料
imaikosuke
0
180
【YAPC::Hakodate 2024】TypeScriptエンジニアが感じたPerlのここが面白い
kimitashoichi
1
460
Micro Frontends for Java Microservices - dev2next 2024
mraible
PRO
0
230
4年間変わらなかった YOUTRUSTのアーキテクチャ
daiki1003
2
670
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Art, The Web, and Tiny UX
lynnandtonic
296
20k
Imperfection Machines: The Place of Print at Facebook
scottboms
264
13k
Building Better People: How to give real-time feedback that sticks.
wjessup
362
19k
Keith and Marios Guide to Fast Websites
keithpitt
408
22k
Rails Girls Zürich Keynote
gr2m
93
13k
Navigating Team Friction
lara
183
14k
GraphQLとの向き合い方2022年版
quramy
43
13k
The Art of Programming - Codeland 2020
erikaheidi
51
13k
Embracing the Ebb and Flow
colly
84
4.4k
Producing Creativity
orderedlist
PRO
341
39k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.6k
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 で公開しています