Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Minify Ruby Code
Search
Koichi ITO
August 04, 2024
Programming
2.7k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Minify Ruby Code
大阪Ruby会議04 (
https://regional.rubykaigi.org/osaka04/
)
Koichi ITO
August 04, 2024
More Decks by Koichi ITO
See All by Koichi ITO
The Rails Doctrine Decade
koic
2
620
Reframing the Agile Manifesto
koic
5
4.9k
The NotImplementedError Problem in Ruby
koic
1
2.1k
Exploring RuboCop with MCP
koic
0
8.4k
Ruby and LLM Ecosystem 2nd
koic
1
2.3k
STYLE
koic
1
2.2k
Ruby and LLM Ecosystem
koic
3
14k
Write Code Every Day
koic
1
2.8k
Bliki (ja), and the Cathedral, and the Bazaar
koic
7
3.3k
Other Decks in Programming
See All in Programming
Kotlinize Is Not Just Converting to Kotlin
chigichan24
1
180
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
170
自作Discord音声botをLambda MicroVMsに移行した話 / Migrating My Discord Voice Bot to Lambda MicroVMs
akihisaikeda
0
140
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
110
AI主導のプログラミング学習アプリを作ってみた
econanringo
0
180
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
3
1.1k
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.7k
個人開発者よ、Honoを使え(おじさんver)
tanahiro2010
2
270
GraphQL の onError と Nullability のこれから
quramy
0
170
自サークルのIdPからログアウトできるようになるまで
taiseiue
1
150
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
4
800
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
320
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
225
10k
Side Projects
sachag
456
43k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.9k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
The untapped power of vector embeddings
frankvandijk
2
1.9k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.6k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Designing for Timeless Needs
cassininazir
1
530
Technical Leadership for Architectural Decision Making
baasie
3
610
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
3
3.9k
Rails Girls Zürich Keynote
gr2m
96
14k
Transcript
େࡕ3VCZձٞ த೭ౡϑΣεςΟόϧλϫʔɾΣετ ,PJDIJ*50&4. *OD .JOJGZ3VCZ$PEF Ruby Code Golf
with Practical Code
@koic w044ϓϩάϥϚʔ w3VCP$PQίΞνʔϜίϛολʔ wגࣜձࣾӬγεςϜϚωδϝϯτ &4. *OD ΤϯδχΞϦϯάϚωʔδϟʔ σΟεςΟϯάΠογϡυɾΤϯδχΞ
3VCZηϛφʔ౦ژ ݄ ۚ σϑΥϧτʹ͍ۙઃఆͰ͔͑ͬͯಡΈʹ͍͘मਖ਼Λ͍ͯ͠ΔํͷώϯτΛ
None
Support OSS community
w !LPJD1BSTFSHFNίϛολʔ w !KVOL-SBNBίϛολʔ w !4)(".&-*/,4QBSTFZίϯτϦϏϡʔλ w !GVHBLLCO3#4ίϯτϦϏϡʔλ w ෦һืूதʂ
ߏจղੳثݚڀ෦ IUUQTNBHB[JOFSVCZJTUOFUBSUJDMFT'PMMPX6Q,JSJTIJNB3VCZIUNM
None
.JOJGZ3VCZ$PEF ڝٕϓϩάϥϛϯάͰΈΔ 3VCZͷ๛͔͞ ʮಈ࡞͢Δ͖Ε͍Ͱͳ͍ίʔυʯͷ ࣄͰͦΜͳඪΛܝ͛·ͤΜͷͰ҆͝৺͍ͩ͘͞ dLPJD dIBSVHVDIJ
ʰ-3Ͱ+40/ύʔαʔΛ࡞Δʱ w dKVOL 1SFNJVN4QPOTPS w dIBSVHVDIJ w dLPJD "TLUIF4QFBLFST ग़ுʂߏจղੳثݚڀ෦
4QPOTPS-5 ݚᮎ3VCZϓϩάϥϛϯά ٳܜ࣌ؒʹϒʔε ͰखചΓ͞Ε·͢ ԿͰങ͓͏ʂ
ࠓͷ
None
w ൃද࣌ͷ࠷৽ͷ3VCZͰ͋ΔEFWͱɺ 1SJTNͷ࣍ͷ։ൃ൛Λલఏʹͯ͠·͢ ຊτʔΫʹ͓͚Δόʔδϣϯ $ ruby -rprism -ve 'p Prism::VERSION'
ruby 3.4.0dev (2024-07-30T06:31:58Z master 1870505f47) [x86_64-darwin23] "0.30.0" # ݫີʹ0.31.0͚ͷ։ൃ൛ rbenv install 3.4-devͳͲͰ͓खݩʹΠϯετʔϧ
.JOJGZͷݱ࣮ͱՄೳੑ 1SJTN"1*ͱ-FYFS .JOJGZ3VCZ$PEF ࣍
.JOJGZͷݱ࣮ͱՄೳੑ
w ιʔείʔυͷαΠζΛখ͘͢͞Δ w 8FCͷੈքͰɺ)5.- +BWB4DSJQU $44 ͳͲϦιʔεͷωοτϫʔΫసૹྔΛݮΒ͢ w ϓϩάϥϛϯάݴޠͷ.JOJGZπʔϧͱͯ͠ɺ ྫ͑+BWB4DSJQUͰ6HJMJGZ+4
5FSTFSͳͲ .JOJGZͱʁ
+BWB4DSJQUઌഐͰͷ.JOJGZྫ function greet(name) { console.log(`Hello! ${name}`); } greet("Osaka RubyKaigi 04");
// Hello, Osaka RubyKaigi 04! HSFFUKT $ npx terser greet.js function greet(name){console.log(`Hello! ${name}`)}\ greet("Osaka RubyKaigi 04"); .JOJGZ͢Δ εϖʔεͷ߹ʹ͖࣮ͭࡍߦ
w ಈ࡞͢ΔͨΊʹඞཁͷͳ͍εϖʔεɺվߦɺ ίϝϯτɺηϛίϩϯͷྨΛআڈ͢Δ w ϨΠΞτߦؒΛ่͠ɺݟͨΛ6HMJGZ͢Δ w ʮಈ࡞͢Δ͖Ε͍ͳίʔυʯͱҟͳΔՁ؍ ಈ࡞͢Δ͍ίʔυ $ npx
terser greet.js | tee >(node) function greet(name){console.log(`Hello! ${name}`)} greet("Osaka RubyKaigi 04"); Hello! Osaka RubyKaigi 04 UFSTFSͷ݁ՌΛϓϩηεஔͰ࣮ߦͨ݁͠Ռ
w ಉ͡ৼΔ͍ͳΒ͍ํ͕ྑ͍ w ܭࢉػʹͱͬͯίʔυՄಡੑॏཁͰͳ͘ɺ ωοτϫʔΫసૹΛқ͘͢͠Δͷ͕࣮ફత w લड़ͷαϯϓϧίʔυͰʹѹॖ͞ΕΔ .JOJGZͷՁ؍ $ wc
-c greet.js 120 greet.js $ npx terser greet.js | wc -c 80
w $PNQSFTTɺෆཁͳεϖʔείϝϯτͷ আɺߏจͷॖԽʹΑͬͯɺϓϩάϥϜ ͷ͍ͨΔՕॴΛ͘͢Δ ຊฤ͜ͷҰ෦ w .BOHMFม໊໊ؔΛॖ͢Δ w ಉ͡ৼΔ͍ͷ··ʮѹྗʯ͕ΑΓ
ߴ͍ํ͕ɺΑΓՁ͋Δ͍ίʔυ $PNQSFTTͱ.BOHMF
ͦͦͳͥ .JOJGZ
w 3BJMTΞϓϦέʔγϣϯͷσϓϩΠΛಛఆͷ αʔόʔʹߦͳ͍ɺͦ͜ʹରͯ͠ϦΫΤετ ͕ूத͢ΔݱͰແԑ w ͠.JOJGZࡁΈίʔυ͕σϓϩΠ͞ΕΔͱɺ ͕ى͖ͨͱ͖ߦ൪߸͕ࢦ͔͢ΒՕॴ ͷಛఆ͕ࠔʹͳͬͯࠔΔ ͦΕͦ͏ ݱͷ͓ࣄ3VCZͩͱͲ͏ʁ
w ໝͦͷɻSVCZXBTNͷίʔυͰ֎෦Ϧιʔ εΛཁٻͨ͠ࡍʹɺ*4FRͳͲͷதؒදݱͰͳ͍ QMBJOͳ3VCZίʔυͷωοτϫʔΫసૹྔݮʁ w ໝͦͷɻΤοδίϯϐϡʔςΟϯάͰɺΤο δαʔόʔ $%/ ΤοδσόΠε *P5
ͷ ίϯςϯπσʔλͷʹ͓͍ͯ༗༻ʁ ະདྷͷ͓ࣄ3VCZͩͱͲ͏ʁ NJOJGZ1JDP3VCZͷϝϞϦݮʹ͑ΔͣͳͷͰ͍ͯ͠·͢ɻ IUUQTYDPNIBTVNJLJOTUBUVT
w དྷ3VCZ,BJHJ দࢁ Ͱ53*$, ͕։࠵͞ΕΔΒ͍͠Ͱ͢Αʁ w ࣄ044Ͱࢦ͍ͯ͠Δʮಈ࡞͢Δ͖Ε͍ ͳίʔυʯͰͳ͍෯Λ࡞ΔػձॏཁͰʁ w .JOJGZ͢Δͷʹʮιʔείʔυͷղੳʯ͕
ඞཁͰͦΕ͢ͳΘͪɺ͍·ྲྀߦΓͷʂʁ དྷͷ3VCZΠϕϯτͩͱͲ͏ʁ
ߏจղੳث .BU[ݴ͍·ͨ͠ύʔαʔͱ($ͱίʔυδΣωϨʔλʹۙͮ͘ͳ
1SJTN"1*Ͱιʔεղੳ
ࣈ۟ղੳͱߏจղੳͷར༻ྫ ࣈ۟ղੳ ߏจղੳ ੩తղੳ Ϩϙʔτ ιʔείʔυ ೖྗ ॲཧ ग़ྗ
w τʔΫϯྻιʔείʔυΛࠨ͔ΒӈʹಡΜͩ τʔΫϯͷྻ w ߏจϓϩάϥϜͷߏจߏΛϊʔυͱͯ͠ πϦʔߏͰදݱ͍ͯ͠Δ w ྫ͑ΫϥεఆٛͷϊʔυͷԼʹϝιουఆٛͷ ϊʔυ͕͋ΔͳͲߏจͷํ͕๛͔ͳσʔλߏ τʔΫϯྻͱߏจ
w γϯϘϧΛҾʹͨ͠ϝιουݺͼग़͠ τʔΫϯྻͷαϯϓϧ puts :hello [:IDENTIFIER, :SYMBOL_BEGIN, :IDENTIFIER, :EOF] puts
: hello %w(foo) [:PERCENT_LOWER_W, :STRING_CONTENT, :STRING_END, :EOF] w ཁૉͻͱͭͷXϦςϥϧ %w( foo )
ߏจͷαϯϓϧ $ ruby -rprism -e 'p Prism.parse("42").value' @ ProgramNode (location:
(1,0)-(1,2)) ├── flags: ∅ ├── locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,2)) ├── flags: ∅ └── body: (length: 1) └── @ IntegerNode (location: (1,0)-(1,2)) ├── flags: newline, static_literal, decimal └── value: 42 Prism.parseͰPrism::ParseResultΛಘΔ
ߏจ ࠓճׂѪ ࠓ͖ͬͱۚࢠ͞Μ͕ࢁ͍ͯ͠Δʂ
w 3VCP$PQͷΑ͏ʹߏจͷैଐؔΛࠪ͠ ͯɺΦʔτίϨΫτͰߏจॻ͖͍͑ͨ͠Α ͏ͳέʔεߏจΛѻ͑ͳ͍ͱ͍͠ w ࠓճͷ.JOJGZͰجຊతʹߏจΛॻ͖͑ ͳ͍ͷͰɺτʔΫϯྻͰेͱ͍͏அ τʔΫϯྻͱߏจͷ͍͚ ͬ͘͟Γ͍͏ͱߏจߏͷॲཧ͢ΔͱͳͬͨΒߏจ͕ཉ͘͠ͳΔ
ࠓճτʔΫϯྻ
w Ripper.lexͱPrism.lex͍ͣΕϓϩάϥϜ ͷτʔΫϯྻΛखʹೖΕΔ͜ͱ͕Ͱ͖Δ"1* w ͔ͤͬ͘ͳͷͰɺ·ͩใ͕গͳ͍1SJTNΛͬ ͯΈͨํ͕͓͠Ζͦ͏ ϓϩϙʔβϧతʹ w Prism.lex_ripperͱPrism.lex_compat
3JQQFSʹ͍ۙ"1*͕ͩɺࠓճૉʹPrism.lex 3VCZͷτʔΫϯऔಘ"1*બఆ
1SJTNMFYͷجຊ"1*
w Prism.lexϝιουͰղੳ݁ՌΛද͢ Prism::LexResultΦϒδΣΫτΛಘΒΕΔ w 📝1SJTN·ͰPrism::ParseLexResult Λޡͬͯฦͯ͠Δ ৄ͘͠SVCZQSJTN 1SJTNMFY require 'prism'
result = Prism.lex('puts :hello') result.class #=> Prism::LexResult
w LexResult.valueͰτʔΫϯΛද͢ Prism::TokenͱMFYTUBUF CJU ͷྻ֫ಘ w MFYTUBUFԼهࢀর ຊฤະ༻ʹׂ͖ͭѪ 1SJTN-FY3FTVMU require
'prism' result = Prism.lex('puts :hello') result.value.class #=> Array result.value.first #=> [#<Prism::Token>, 32] IUUQTHJUIVCDPNSVCZQSJTNCMPCWJODMVEFQSJTNQBSTFSI--
w LexResult.valueͷྻͷୈҰཁૉ Prism::TokenܕɺɺҐஔใΛ࣋ͭ 1SJTN5PLFO result = Prism.lex('puts :hello') token, _state
= result.value.first token.class #=> Prism::Token token.type #=> :IDENTIFIER token.value #=> "puts" token.location.class #=> Prism::Location
w ParseToken.locationͰτʔΫϯͷҐஔ ใΛ࣋ͭPrism::LocationΛಘΒΕΔ 1SJTN-PDBUJPO result = Prism.lex('puts :hello') token, _state
= result.value.first location = token.location location.first_line #=> 1 location.start_offset #=> 0 location.length #=> 4
τʔΫϯॲཧͷఆੴαϯϓϧ tokens = Prism.lex(source).value tokens.each_cons(2)do|(token,_),(next_token,_)| case token.type when :COMMENT #
do_something when :IDENTIFIER # do_something end prev_token = token end FBDI@DPOT Ͱ࣍ͷτʔΫϯใΛઌಡΈ͢Δ QSFW@UPLFOͰલͷτʔΫϯใΛอ͓࣋ͯ͘͠ ͜ͷ͋ͱհ͢Δ.JOJGZ3VCZ͜ͷͭ͘Γ UPLFOUZQFͷछྨͰॲཧΛผ͢Δ ࠨ͔ΒӈͷτʔΫϯྻͷϧʔϓ
ࣈ۟ղੳͱߏจղੳͷར༻ྫ ࣈ۟ղੳ ߏจղੳ ѹॖॲཧ ѹॖ͞Εͨίʔυ ιʔείʔυ ೖྗ ॲཧ ग़ྗ
.JOJGZ3VCZ$PEF
github.com/koic/minifyrb
w minifyrbίϚϯυͰɺෆཁͳίʔυ෦ɺ ͭ·ΓτʔΫϯΛআڈͯ͠ίʔυΛѹॖ͢Δ .JOJGZ3VCZHFN $ gem i minifyrb $ echo
"puts :hello" | minifyrb puts:hello
0SJHJOBM$PEF
.JOJ fi FE$PEF
ઃܭํ
w ͳͯ͘ྑ͍ۭനվߦΛۃྗআڈ͢Δ w ίϝϯτΛআڈ͢Δ w ඞཁʹԠͯ͡ηϛίϩϯʹΑΔϫϯϥΠφʔ w ม໊ϝιου໊Λॖ͢Δ.BOHMF ෳࡶʹͳΔͨΊߦΘͳ͍ ࠓޙͷల
ݱ࣌ͷجຊతͳߟ͑ํ
w {}ϕʔεͷߏจͱͳΔ+BWB4DSJQUͰྫ͑ functionΛҰߦͰෳఆٛͰ͖Δ +BWB4DSJQUͷϫϯϥΠφʔʹֶͿ $ cat example.js | tee >(npx
terser) function foo() { console.log(bar()); } function bar() { 42; } function foo(){console.log(bar())}function bar(){42} εϖʔεɺηϛίϩϯෆཁ ಡΈ͢͞ͷվߦΛ͢Δ
w FOEϕʔεͷߏจͱͳΔ3VCZͰྫ͑վߦ Ληϛίϩϯʹஔ͖͑ͯɺ݁ہόΠτ ͷαΠζֻ͕͔Δ͜ͱมΘΒͳ͍ w FOE^ͱൺɺ۠Γεϖʔε͕ඞཁ͔அ w ॳσόοά࣌ͷߦ൪߸ΛΔҙຯͰɺ ෳߦͷ··Ͱྑ͍ͱ͍͏τϨʔυΦϑஅ 3VCZͷϫϯϥΠφʔ
ِ 1όΠτ
w FOEϕʔεͷߏจͱͳΔ3VCZͰྫ͑վߦ Ληϛίϩϯʹஔ͖͑Δͱɺ8JOEPXTͳΜ ͔ͷaSaOͷόΠτվߦόΠτʹݮΒͤΔ w .JOJGZͱ͍͏ํʹ͓͚ΔτϨʔυΦϑஅ ੑΑΓ͍ίʔυΛऔΔ w ݁Ռͱͯ͠෭࡞༻ʹएׯͷಡԽ͕͍͖ͭͯͨ 3VCZͷϫϯϥΠφʔ
ਅ
Prism.lex&SSPS5PMFSBODFʹͳͬͯΔ &SSPS5PMFSBODF $ ruby -ce 'cond(arg)?x:y' # εϖʔεͳ͠ѹॖߏจΤϥʔͷྫ -e:1: syntax
error, unexpected symbol literal, expecting 'do' or '{' or '(' cond(arg)?x:y ruby: compile error (SyntaxError) $ ruby -ce 'cond(arg)?x: y' # ͜ͷ߹:ͱyͷؒʹཁεϖʔε Syntax OK $ ruby -rprism -e "p Prism.lex('cond(arg)?x:y').value" [[#<Prism::Token:0x0000000104c87b70 @source=#<Prism::ASCIISource:0x000000011f7f5dd0 ͍ͭ͜ಈͧ͘ʂ
w .JOJGZ-41ͷΑ͏ͳೖྗ్தͷίʔυΛॲཧ ͢ΔͷͰͳ͍ w ಈ͔ͳ͍ίʔυΛ.JOJGZͯ͠ํͳ͍ͷͰɺ ݩίʔυ͕ߏจΤϥʔͷͱ͖Τϥʔͱͨ͠ w Prism.lex(code).errorsͷ݁Ռྻ Prism.parse_success?ͰΔ͜ͱ͕Ͱ͖Δ &SSPS5PMFSBODFͷஅ
Prism::ParseLexResult#errors
τʔΫϯॲཧͷ࣮
w *(/03&%@/&8-*/&ଥͳγϯλοΫ εͰ͋ΔͨΊʹෆඞཁͳվߦ ୯ʹআՄೳ w /&8-*/&ଥͳγϯλοΫεͰ͋Δͨ Ίʹඞཁͳվߦ ୯ʹআ͢ΔͱߏจΤϥʔ छྨͷվߦτʔΫϯ
ݱࡏͷ1SJTN ࣮ͩͱظͱҧ͏෦͋Γޙड़
w ͜ͷվߦ͕ͳ͘ͳͬͯߏจͱͯ͠ଥͰ͋Δ w ηϛίϩϯͳ͠ͰվߦআͲ͜·ͰͰ͖Δʁ *(/03&%@/&8-*/&τʔΫϯ begin rescue CustomError=>e else ensure
end ݩόΠτ aOͷ߹ begin rescue CustomError=>e else ensure end *(/03&%@/&8-*/&ద༻ όΠτ begin rescue CustomError=>e;else ensure end ࢀߟผ్ηϛίϩϯஔ όΠτ
w ʮಈ࡞͢Δ͖Ε͍Ͱͳ ͍ίʔυʯ͕ຊτʔΫͷ ςʔϚͰ͢Α w .JOJGZͱ53*$,ີ ʹؔ࿈͢ΔԾઆ w 53*$,ͷLJOBCB͞ Μ࡞ͷཧղʹ͚ۙͮΔʁ
͜ͷτʔΫϯ͔ΒಘΒΕΔֶͼ IUUQTHJUIVCDPNUSJDUSJDLCMPCNBTUFSLJOBCBFOUSZSC 53*$,໊࡞ͷͻͱͭ
w "\r\n"͔͠Εͳ͍վߦΛ۠ΓτʔΫϯʹ ͢Δ͜ͱͰόΠτΛݮΒͤΔՄೳੑ͕͋Δ w *(/03&%@/&8-*/&ͱҧ͍ɺdef foo͕ deffooʹͳΒͳ͍Α͏దٓ۠Γௐ͕ඞཁ w ࣍τʔΫϯͷܕ͕&0'ͷ߹104*9४ڌͷ ςΩετϑΝΠϧͱ͢ΔͨΊվߦΛҡ࣋͢Δ
/&8-*/&τʔΫϯ
104*9४ڌҧ👮 (JU)VCͷΞϨ /&8-*/& &0'
w BMJBTFRM ͕BMJBTFRM ߏจΤϥʔ w GPP 'PP͕GPP 'PPҙຯ͕มΘΔ w BSSBZ͕
BSSBZߏจΤϥʔ w GPPX BCD ͕GPPX BCD ҙຯ͕มΘΔ w GPPX BGPSC ͕GPPX BGPSC ߏจΤϥʔ ݁߹͍͚ͯ͠ͳ͍γϦʔζͷҰ෦ unexpected char literal unexpected operator assignment unexpected ')'
w ด͡ΧοίલͷվߦIGNORED_NEWLINEʹͰ͖Δ ͕ͣͩɺΧϯϚͳͩ͠ͱNEWLINEͱ͞ΕΔ ҙਤతͳ3JQQFSޓɺSVCZQSJTNࢀর w ;ͷ୯७ͳஔ[foo, bar, baz;]ͷߏจΤϥʔ <ิ>୯७ͳηϛίϩϯஔෆՄ
[ foo, bar, baz ] :BRACKET_LEFT_ARRAY,:IGNORED_NEWLINE :IDENTIFIER, :COMMA,:IGNORED_NEWLINE :IDENTIFIER, :COMMA,:IGNORED_NEWLINE :IDENTIFIER, :NEWLINE :BRACKET_RIGHT, :NEWLINE, :EOF
վߦͷτʔΫϯॲཧ֓ཁ tokens.each(2) do |(token, _), (next_token, _)| case token.type when
:IGNORED_NEWLINE # noop when :NEWLINE token_value = if next_token.type == :EOF token.value elsif CLOSING_DELIMITER_TYPES.include?(next_token.type) # noop else ';' end 104*9ͷΞϨͷOFXMJOFରԠ Ճ͑ͯɺdeffooͳͲ༧ޠ͕݁߹͠ͳ͍Α͏ͳॲཧΛผ్͍ͯ͠Δ > ^ͷτʔΫϯͷఆɻຊདྷ*(/03&%@/&8-*/&͔ͳύον
w )&3&%0$@45"35ͱ)&3&%0$@&/%ͷ τʔΫϯʹғ·ΕͨτʔΫϯ͕ຊจ )&3&%0$@ 45"35c&/% τʔΫϯ <<HEREDOC text HEREDOC [:HEREDOC_START,
:STRING_CONTENT, :HEREDOC_END, :NEWLINE, :EOF]
w γϯϓϧͳώΞυΩϡϝϯτͳΒ )&3&%0$@45"35͔Β)&3&%0$@&/%· ͰͷτʔΫϯΛ݁߹͢ΕऴΘΓͦ͏ w τʔΫϯྻιʔείʔυΛࠨ͔ΒӈʹಡΜ ͩ݁Ռͷྻͱݴͬͨͳʁ ώΞυΩϡϝϯτ
w :DOT, :IDENTIFIER:HEREDOC_STARTʹ ଓ͘τʔΫϯͰͳ͍ w ώΞυΩϡϝϯτΛจࣈྻϦςϥϧͷҰछͩͱࢥ ͑"text".do_somethingͳͷͰͦΕͦ͏ )&3&%0$EP@TPNFUIJOH <<HEREDOC.do_something text
HEREDOC [:HEREDOC_START, :STRING_CONTENT, :HEREDOC_END, :DOT, :IDENTIFIER, :NEWLINE,:EOF]
w ͍όΠτʹ͢Δํʹج͖ͮIFSFEPD จࣈྻϦςϥϧʹஔ͢Δ͜ͱͱͨ͠ w )&3&%0$@45"35͔Β)&3&%0$@&/%· ͰώΞυΩϡϝϯτͰ͋Γɺdͷ߹ IFSFEPDऴྃͰEFEFOU͢ΔΑ͏ঢ়ଶΛอͭ )&3&%0$EP@TPNFUIJOH <<HEREDOC.do_something text
HEREDOC " text"
IFSFEPDͷτʔΫϯॲཧ֓ཁ tokens.each(2) do |(token, _), (next_token, _)| case token.type when
:HEREDOC_START @in_heredoc = true squiggly_heredoc = token.value.start_with?('<<~') # SNIP: <<'HEREDOC', <<"HEREDOC", <<`HEREDOC`ͷॲཧׂѪ when :HEREDOC_END heredoc_contents = @heredoc_content_tokens.join # SNIP: <<~ͷdedentॲཧΛׂѪ @minified_values << heredoc_contents @minified_values << (@string_quote == '`' ? '`' : '"') @heredoc_content_tokens.clear @in_heredoc = false IFSFEPDதͷτʔΫϯॲཧΛ༗ޮԽ IFSFEPDதͷτʔΫϯॲཧΛແޮԽ EFEFOUॲཧ͕ඞཁ͔ঢ়ଶΛ࣋ͨͤΔ IFSFEPDແҹҎ֎ΫΥʔτ͕ͱ͓Γ IFSFEPDຊจͷτʔΫϯͷྻΛ݁߹
ͯ͢ΛޠΔλΠτϧɻࠓճͷHFNIFSFEPD͕ਖ਼·ͩόΪʔ IUUQTTQFBLFSEFDLDPNZVJ@LOLIFSFEPDJOEFNPODBTUMF
ࠓޙͷ֦ுʹ͚ͨҙ def m(a) bar unless cond end def m(a)bar unless
cond end w ҾΧοί͋Γͷɺվߦηϛίϩϯͳ͠Ͱॻ͚ΔFOE͋Γͷ ϫϯϥΠφʔϝιουఆٛʹ͍ͭͯߟ͑Δ ಉ͡ߏจ
FOEMFTTEFGͱߏจ͕ҟͳΔ w .BOHMJOHΛߟ͑Δ߹-FYFSτʔΫϯΑΓ ߏจͰͷॲཧ͕͍͍ͯΔ͔ def foo(a)=bar unless cond def foo(a)bar
unless cond end ҟͳΔߏจ
ެ։ ͜ΜͳࢥߟΛͭͭ͠Ͱ͖·ͨ͠
# Original $ find . -name '*.rb' -type f -print0
| \ xargs -0 wc -c | awk 'END{print $1}' 49825 # Original $ find . -name '*.rb' -type f -print0 | \ xargs -0 wc -c | awk 'END{print $1}' 49825 # Minify $ bundle exec rake minify $ find . -name '*.rb' -type f -print0 | \ xargs -0 wc -c | awk 'END{print $1}' 31598 # Original $ find . -name '*.rb' -type f -print0 | \ xargs -0 wc -c | awk 'END{print $1}' 49825 # Minify $ bundle exec rake minify $ find . -name '*.rb' -type f -print0 | \ xargs -0 wc -c | awk 'END{print $1}' 31598 # Ratio $ ruby -e 'p 31598 / 49825.0' 0.6341796287004515 .JOJGZͰͲΕ͘Β͍ݮΔʁ
w MJC όΠτ͔Β όΠτʹͳΓɺ TQFD όΠτ͔Β όΠτʹ ͳΔ w ͭ·Γݮ͞Εͨίʔυ34QFDͷํ͕ߴ͍
w ࣮ફత ͱʁ ʹϓϩμΫτίʔυͷޮ Ռ͕ߴ͍ํ͕͍͍Μ͚ͩͲݱ࣮͜͏Β͍͠ ଌఆͱධՁΛ͏গ͠
github.com/koic/minifyrb gem install minifyrbͰ༡ΜͰΈͯͶ
͓΅͍͑ͯ·͔͢ʁ
@koic w044ϓϩάϥϚʔ w3VCP$PQίΞνʔϜίϛολʔ wגࣜձࣾӬγεςϜϚωδϝϯτ &4. *OD ΤϯδχΞϦϯάϚωʔδϟʔ σΟεςΟϯάΠογϡυɾΤϯδχΞ
One More Thing
" ࠞಱͱடং
.JOJGZͨ͠ίʔυͱ ͬͱٔΕΔ
w ಡԽʹର͢Δ෮߸ԽΈ͍ͨͳͷ w ͓ࣄʹݶΒͣɺ;ͩΜΈΜͳߦّͷྑ͍ ίʔυΛແҙࣝʹࢦͯ͠͠·͍·͢ΑͶʁ w 3VCP$PQͷΦʔτίϨΫτͱ͍͏ ϑΥʔϚολʔͷྗͷ࠶ൃݟ .JOJGZͰյͯ͠3VCP$PQͰ͢ .JOJGZͨ͠ίʔυ͕Ͳ͏෮ݩͰ͖Δ͔ڵຯΛ࣋ͪ·͢ΑͶʁ
w .JOJGZͱ3VCP$PQͱ͍͏ࠞಱ͔Βͷ w 3VCP$PQͷΤοδέʔεॲཧʹ͍ͭͯɺ NJOJGZͨ͠ίʔυΛݩʹ͢Ε؆୯ʹҧ͋ ΓͷίʔυΛ࡞ΕΔΑ͏ʹͳͬͨ w .JOJGZ͚ͩͰͳ͘3VCP$PQͷࣗಈमਖ਼όά ݟ͚ͭͯ͢ػձʹͳ͍ͬͯΔ .JOJGZ։ൃͷࢥΘ͵෭࡞༻
0SJHJOBM$PEF
.JOJ fi FE$PEF
"VUPDPSSFDUFE$PEF .JOJGZͷத֩ͷίʔυΛ.JOJGZͯ͠ɺͦͷ͋ͱ3VCP$PQͰϑΥʔϚοτ
%&.0
w ࠓճͷ෮߸ԽσϞͷͨΊʹ͍͔ͭͨ͘͠ w ;ͭ͏ਓॻ͔ͳ͍ϫϯϥΠφʔʹରͯ͠ɺ 3VCP$PQ͕͍ ͦΕͦ͏ w .JOJGZແݶʹΛᖰΓग़ͨ͢Ίͷڰؾͷ ڟث͔͠Εͳ͍
ਓ͕ॻ͔ͳ͍ίʔυΛಘΔ ਓཧͰ͖Ε͍ͳίʔυΛॻ͜͏ͱ͢Δ͕ɺϓϩάϥϜࢦࣔ௨Γಈ͚ͩ͘
PTSL@FGGFDU Ϛονϙϯϓͷ .JOJGZΛ࡞ͬͨΒ3VCP$PQͷࣗಈमਖ਼ΫΦϦςΟ͕͕͋ͬͨ
l ख़ͨ͠จԽɺྫ͑ԻָͰָේΛٯ͞ʹͯ͠ ͘͜ͱ͕Ͱ͖ΔԻָͱ͔ͦ͏͍͏ͷ͕͋ͬ ͯɺ தུ ख़ͨ͠จԽʹ͜͏͍͓ͬͨ༡ͼ ͕ൃల͍ͯͯ͠ɺϓϩάϥϛϯάͱ͍͏ ख़ͨ͠จԽʹͳ͍ͬͯΔͱ͍͑ΔΜͰ͔͢Ͷ !LJOBCB TRICK
2018 (FINAL) ʹͯ
Կͷʹཱͨͳ͍ ϓϩάϥϜΛָ͠ΉจԽ IUUQTXXXZPVUVCFDPNXBUDI W5#ON((VV