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
当配置遇到 Scala宏
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Lunfu Zhong
June 06, 2015
Programming
370
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
当配置遇到 Scala宏
一个 Internal DSL 的应用案例
Lunfu Zhong
June 06, 2015
More Decks by Lunfu Zhong
See All by Lunfu Zhong
spring-boot 在统一架构体系中的价值
zhongl
2
890
如何准备一场主题分享
zhongl
1
330
项目求生指南
zhongl
0
380
LEGO - let's build everything by scala
zhongl
1
290
Real-world Scala
zhongl
2
170
JVM运行时诊断工具 HouseMD
zhongl
0
510
Art of The Code
zhongl
1
270
Other Decks in Programming
See All in Programming
Hatena Engineer Seminar #37「言語モデルの活用に関する研究」
slashnephy
0
510
共通化で考えるべきは、実装より公開する型だった
codeegg
0
210
音楽のための関数型プログラミング言語mimiumにおける多段階計算の活用
tomoyanonymous
1
310
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.4k
ランチタイムLT会3周年!ランチタイムLT会を3年間続けられたお話
y0hgi
1
140
【やさしく解説 設計編 #0】DDDのコード、読めるのに分からない人へ
panda728
PRO
2
250
なぜ型を書くのか? TSKaigi2026で改めて考える #tskaigi_smarthr
kajitack
0
340
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
150
Vite+ Unified Toolchain for the Web
naokihaba
0
740
ローカルLLMでどこまでコードが書けるか -縮小版 / How much code can be written on a local LLM Shortened
kishida
2
190
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
110
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
360
Featured
See All Featured
The Cult of Friendly URLs
andyhume
79
6.9k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
The Pragmatic Product Professional
lauravandoore
37
7.4k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
Code Review Best Practice
trishagee
74
20k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
3
1.1k
Between Models and Reality
mayunak
4
370
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.9k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
260
Visualization
eitanlees
152
17k
Transcript
当配置遇到Scala宏 ⼜又⼀一个 Internal DSL 的应⽤用案例
关于我 Scala, Java, Big Data, Message Middleware
这些年我们⽤用过的配置 都有哪些?
.properties .yaml .conf .xml
相较⽽而⾔言...
醉⼈人的命名⻓长度 1 // application.properties 2 db1.jdbc.url = jdbc:mysql:10.0.0.1/demo 3 db1.jdbc.driver
= com.mysql.jdbc.Driver 4 db1.jdbc.username = jushi 5 db1.jdbc.password = ********
啰嗦的对称包围 1 <!-- logback.xml --> 2 <configuration scanscan="true" scanPeriod="3 seconds"
> 3 4 <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 5 <encoder> 6 <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 7 </encoder> 8 </appender> 9 10 <root level="INFO"> 11 <appender-ref ref="STDOUT" /> 12 </root> 13 </configuration>
优雅地近乎完美 1 #.travis.yml 2 language: scala 3 scala: 4 -
2.11.5 5 jdk: 6 - openjdk7 7 script: 8 - sbt ++$TRAVIS_SCALA_VERSION test 9 notifications: 10 email: 11 -
[email protected]
强⼤大到没有朋友 1 // kafka.conf 2 kafka { 3 server {
4 host = localhost 5 port = 9092 6 } 7 socket { 8 timeout = 5s 9 buffer = 64K 10 } 11 client = id 12 debug = false 13 delays = 2s 14 }
None
只是...
我 讨厌 G.E.T 1 // Consumer.scala 2 class Consumer extends
Actor { 3 @inline def conf = context.system.settings.config 4 5 val client = new SimpleConsumer( 6 conf.getString("kafka.server.host"), 7 conf.getInt("kafka.server.port"), 8 conf.getDuration("kafka.socket.timeout", SECOND), 9 conf.getLong("kafka.socket.buffer"), 10 conf.getString("kafka.client") 11 ) 12 13 ... 14 }
None
然后,我想到了宏
Method or Annotation
Method 1 def conf(key: String) = macro impl 2 3
def impl(c: Context)(key: c.Expr[String]) : c.Expr[Unit] = { 4 // TODO 5 } 6 7 8 val host = conf("kafka.server.host") 9 10 val host = conf.getString("kafka.server.host")
Method
Annotation 1 class conf extends StaticAnnotation { 2 def macroTransform(annottees:
Any*): Any = macro impl 3 4 private def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { 5 import c.universe._ 6 7 annottees.map(_.tree) match { 8 case ClassDef(...) :: Nil => 9 // TODO 10 11 case _ => 12 c.abort(c.enclosingPosition, "Invalid annottee") 13 } 14 } 15 }
Annotation 1 @conf trait kafka { 2 val server =
new { 3 val host: String 4 } 5 } 6 7 trait kafka { 8 val server = new { 9 val host: String = conf.getString("kafka.server.host") 10 } 11 }
如果仅仅只是映射装载 就太 TYTSSN 了
由代码⽣生成配置 1 @conf trait kafka { 2 val server =
new { 3 val host = "wacai.com" 4 val port = 12306 5 } 6 7 val socket = new { 8 val timeout = 3 seconds 9 val buffer = 1024 * 64L 10 } 11 12 val client = "wacai" 13 } 1 kafka { 2 server { 3 host = wacai.com 4 port = 12306 5 } 6 7 socket { 8 timeout = 3s 9 buffer = 64K 10 } 11 12 client = wacai 13 }
之前提到的⼜又⼀一案例 1 import lego.dsl._ 2 3 new Server { 4
5 def name = "ping-pong" 6 7 tcp.bind(port = 12306) { 8 Codec() <=> Handle { 9 case Request(_, hs, _) => Response(200, hs) 10 } 11 } 12 }
参阅 github.com/wacai/config-annotation 使⽤用 Scala Macro Annotation 实现配置项绑定 ⾸首篇 续篇 终篇
What are macros good for ?
scala macro annotations real world example
[email protected]