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
440
Reframing the Agile Manifesto
koic
5
4.6k
The NotImplementedError Problem in Ruby
koic
1
2.1k
Exploring RuboCop with MCP
koic
0
7.6k
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.7k
Bliki (ja), and the Cathedral, and the Bazaar
koic
7
3.3k
Other Decks in Programming
See All in Programming
UPDATE をやめる — EF Core でマスタをバージョン管理する
panda728
PRO
0
1k
Security issues being discussed on Web Platforms
petamoriken
0
1.4k
モバイル交通系ICへのチャージ実例から考える、クロスプラットフォーム開発におけるiOS実機テスト設計とCI運用
yusuga
1
570
[2026-09-26]空論ジェネリックプロセス~テスト資産とAIで紡ぐ、再現可能なパフォーマンスチューニングの話~
tosite
0
250
海上で動くGoサーバー: goroutineとchannelでさばく航行データストリーム
atsuki_seo
0
1k
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
150
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
430
速習iPhone Duo対応
yuukiw00w
2
910
Java 27新機能 / Java 27 new features
kishida
2
190
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
1
330
すこし踏み込む CancellationToken
htkym
2
1.5k
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
4
400
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
2
930
Why Our Code Smells
bkeepers
PRO
340
58k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
350
Ruling the World: When Life Gets Gamed
codingconduct
0
380
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.5k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.9k
Technical Leadership for Architectural Decision Making
baasie
3
580
Darren the Foodie - Storyboard
khoart
PRO
4
4k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
560
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