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
0
3.9k
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
ありがとう、create-react-app
utgwkk
2
7k
mockgenによるモック生成を高速化するツール bulkmockgenのご紹介 / Kyoto.go #43
utgwkk
1
1.4k
SPAでもデータをURLでシェアしたい / Kyoto.js 19
utgwkk
1
1.4k
なんでもPull Requestにする / Kichijoji.pm 31
utgwkk
2
5.9k
インプットとアウトプットのサイクルを回す暮らし / Kichijoji.pm 29
utgwkk
1
8.8k
prototypeとjust epic. と私 / YAPC::Japan::Online 2022
utgwkk
0
9.3k
GraphQLを使った共同開発の心構え 〜 フロントエンドの視点から / Hatena Engineer Seminar #18
utgwkk
0
8.7k
他言語ユーザから見たPerlのおもしろさ / YAPC::Nagoya::Tiny 2019
utgwkk
1
8k
VJに使えそうなコマンドたち、そしてjustifyのご紹介 / YAPC::Nagoya::Tiny 2019 LT
utgwkk
0
5.4k
Other Decks in Programming
See All in Programming
もうすぐ新年度、Babylon.jsがお勧めな3個の理由
hideg
0
160
クソコード動画『カプセル化 Mk-II』 で考える 上手くカプセル化できない理由 / encapsulation2
minodriven
11
7.8k
生成 AI の中身を覗いてみよう〜基礎から医療現場での応用まで〜
soh9834
2
760
デザインシステムで Tailwind CSSとCSS in JSに分散投資をしたら良かった話
fsubal
14
3.2k
Laravel標準バリデーションでできること
hmb_ok
2
360
TCAの Shared Stateって どういう仕組みになってんの?
yimajo
0
330
Kotlinを用いたDSL的な設計手法と使用上の注意
kohii00
3
530
Open Source Swift Workshop - Foundation and first party libraries
ikesyo
0
180
Learning PHP and Static Analysis with PHP Parser
inouehi
1
250
オブジェクト指向コードレビューの新しいアプローチ
akkie76
3
1.5k
品質が高いコードって何?Rev2.1
ickx
1
490
DocC Tutorial と TCA におけるテスト機能の紹介
kalupas226
1
330
Featured
See All Featured
Adopting Sorbet at Scale
ufuk
66
8.5k
Infographics Made Easy
chrislema
237
18k
Scaling GitHub
holman
456
140k
Facilitating Awesome Meetings
lara
39
5.5k
GraphQLの誤解/rethinking-graphql
sonatard
48
9.1k
The Art of Programming - Codeland 2020
erikaheidi
40
12k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
12
1.4k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
272
12k
The Straight Up "How To Draw Better" Workshop
denniskardys
227
130k
Practical Orchestrator
shlominoach
180
9.7k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
226
16k
Stop Working from a Prison Cell
hatefulcrawdad
265
19k
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 で公開しています