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
5k
Goでリフレクションする、その前に / Kansai.go #1
utgwkk
5
1.7k
Go製Webアプリケーションのエラーとの向き合い方大全、あるいはやっぱりスタックトレース欲しいやん / Kyoto.go #50
utgwkk
7
3k
ありがとう、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.2k
インプットとアウトプットのサイクルを回す暮らし / Kichijoji.pm 29
utgwkk
1
9k
Other Decks in Programming
See All in Programming
初めてDefinitelyTypedにPRを出した話
syumai
0
400
ふかぼれ!CSSセレクターモジュール / Fukabore! CSS Selectors Module
petamoriken
0
150
3 Effective Rules for Using Signals in Angular
manfredsteyer
PRO
0
100
ローコードSaaSのUXを向上させるためのTypeScript
taro28
1
610
CSC509 Lecture 11
javiergs
PRO
0
180
リアーキテクチャxDDD 1年間の取り組みと進化
hsawaji
1
220
Jakarta EE meets AI
ivargrimstad
0
580
Nurturing OpenJDK distribution: Eclipse Temurin Success History and plan
ivargrimstad
0
870
とにかくAWS GameDay!AWSは世界の共通言語! / Anyway, AWS GameDay! AWS is the world's lingua franca!
seike460
PRO
1
860
Webの技術スタックで マルチプラットフォームアプリ開発を可能にするElixirDesktopの紹介
thehaigo
2
1k
Amazon Bedrock Agentsを用いてアプリ開発してみた!
har1101
0
330
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
10
1.3k
Featured
See All Featured
[RailsConf 2023] Rails as a piece of cake
palkan
52
4.9k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
The World Runs on Bad Software
bkeepers
PRO
65
11k
Speed Design
sergeychernyshev
24
610
Into the Great Unknown - MozCon
thekraken
32
1.5k
RailsConf 2023
tenderlove
29
900
How to Think Like a Performance Engineer
csswizardry
20
1.1k
A Philosophy of Restraint
colly
203
16k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
6
410
Building Better People: How to give real-time feedback that sticks.
wjessup
364
19k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Practical Orchestrator
shlominoach
186
10k
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 で公開しています