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
面倒なことはScalaスクリプトにやらせよう / let scala scripts do t...
Search
Takumi Kadowaki
September 16, 2019
Programming
1.2k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
面倒なことはScalaスクリプトにやらせよう / let scala scripts do the troublesome things
2019/09/13 Scala秋祭り
Takumi Kadowaki
September 16, 2019
More Decks by Takumi Kadowaki
See All by Takumi Kadowaki
Datadog Error Tracking & Claude Code Action で アプリケーションエラーを(半)自動修正 / Datadog Error Tracking & Claude Code Action (semi-)auto-correct application errors
nomadblacky
1
200
Reckoner における Datadog Browser Test の活用事例 / Datadog Browser Test at Reckoner
nomadblacky
0
630
Scala アプリケーションのビルドを改善してデプロイ時間を 1/4 にした話 | How I improved the build of my Scala application and reduced deployment time by 4x
nomadblacky
1
1.4k
Reckoner の Scala プロジェクトにおける オブザーバビリティの取り組み / Observability Initiatives in Reckoner's Scala Project
nomadblacky
0
2.8k
AWS CDK on Scala ~ Scalaでインフラ管理してみたはなし / Manage infrastructure with AWS CDK on Scala
nomadblacky
0
4.8k
Slinky で Scala.js 製 React Webアプリケーションを つくったはなし / How to build a Scala.js React web application in Slinky
nomadblacky
1
5.4k
Other Decks in Programming
See All in Programming
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
140
React Native에 현대적인 빌드 도구 더하기: Rollipop 구현기
leegeunhyeok
0
180
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
170
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
3
1.5k
Vue.jsで作る空間解析アプリとCapacitorプラグインのData Bridge
hal_spidernight
1
170
AIで開発が速くなった先で、開発チームは何を目指すか
shihochan
1
2k
Seven New Principles of Software Engineering
yegor256
0
470
Web3Dライブラリを作ってVue Custom Rendererの仕組みを理解しよう / lets learn vue custom renderer by making 3d library
drumath2237
1
130
Crash Auto Pipelines
veronikapj
1
410
Distance field of Julia set
kinakomoti321
0
310
AWS CDKを理解するために公式の定義を深掘って解説してみる / Understanding AWS CDK by Digging into Its Official Definition
akihisaikeda
3
290
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
200
Featured
See All Featured
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.9k
Writing Fast Ruby
sferik
630
63k
Test your architecture with Archunit
thirion
2
2.5k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
290
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
800
Unsuck your backbone
ammeep
672
58k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5.7k
Building the Perfect Custom Keyboard
takai
2
950
Optimizing for Happiness
mojombo
378
71k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.6k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
Transcript
面倒なことは Scalaスクリプトにやらせよう 2019/09/16 Scala秋祭り Takumi Kadowaki @blac_k_ey
どなた? Takumi Kadowaki Twitter: @blac_k_ey GitHub: NomadBlacky セプテーニ・オリジナル PYXISチーム所属 広告運用自動化ツールのバックエンド開発が主な仕事
海と温泉とテトリスが好き ScalaMatsuri2019で頒布した「技術読本」に 「ServerlessFramework + Scala」なアプリケーションについて記事を書き ました
突然ですが問題です
DockerHubからあるイメージのタグ一覧をAPIから取得して、 最もサイズの小さいものと大きいものを出力してください { "count": 257, "page": 1, "page_size": 25, "results":
[ { "id": 2255500, "name": "stable", "last_updated": "2019-09-12T14:51:49.113501Z", "full_size": 50665062 }, { "id": 19451, "name": "latest", "last_updated": "2019-09-12T14:51:29.159817Z", "full_size": 50665667 }, ... ] } https://hub.docker.com/api/content/v1/repositories/public/library/nginx/tags
シェルスクリプトで複雑なことをするとつらい… $ curl \ https://hub.docker.com/api/.../nginx/tags \ | jq .results[].full_size ...
(ここで考えるのをやめる) (我々は jq コマンドのプロではない…) (ページングとか考えるとさらにめんどい…) とりあえずシェルスクリプトで…
みんな大好きScala! みんな大好きsbt!
小さいプログラムを書くにはオーバー… • build.sbt ◦ ビルド定義 ◦ 依存解決 • build.properties ◦
sbtバージョンの指定 ◦ プラグイン (sbt-assembly etc.) • src/main/scala/.../Hoge.scala ◦ 目的のコード
世の中には色々なスクリプト言語がある JavaScript Ruby Python Groovy PHP Perl etc...
それでもやっぱりScalaで書きたい〜 JavaScript Ruby Python Groovy PHP Perl
この間を埋めるものはないだろうか… コード量/プロジェクト規模 大 小 Shell Script
そんなあなたに、 Ammonite 大 小 @ コード量/プロジェクト規模 Shell Script
Ammoniteとは? https://ammonite.io lihaoyi/Ammonite • Scala REPL • Script Runner •
File System Library • Shell これらの総称
Ammonite-REPL
http://ammonite.io/#Ammonite-REPL 何はともあれ、まずはインストールしてみよう (Linuxなど ※執筆時の最新版) $ sudo sh -c '(echo "#!/usr/bin/env
sh" && curl -L https://github.com/lihaoyi/Ammonite/releases/download/1.6.9/2.13-1.6.9) > /usr/local/bin/amm && chmod +x /usr/local/bin/amm' && amm コマンドをひとつ実行するだけ! (Macのかた) $ brew install ammonite-repl
Hello World!!
Ammonite-REPLの便利な機能 • シンタックスハイライト • 複数行のコード編集 • Undo & Redo •
Magic Import • browse ◦ 大きな配列など、文字列表現が長い評価結果をページャで確認 • source ◦ REPL上でソースコードを閲覧
Magic Import Maven Central からJarを取得して、すぐにライブラリを使える! import $ivy.`<group_id>::<artifact_id>:<version>` // cats の例
import $ivy.`org.typelevel::cats-core:2.0.0` // sbt との比較 libraryDependencies += "org.typelevel" %% "cats-core" % "2.0.0"
None
Ammonite-Script
Scalaコードをコマンドラインから直接コンパイル・実行! sample.sc println("Hello Ammonite!!")
Scalaコードをコマンドラインから直接コンパイル・実行! sample.sc println("Hello Ammonite!!") Scalaスクリプトでよく使われる拡張子
Scalaコードをコマンドラインから直接コンパイル・実行! sample.sc println("Hello Ammonite!!") $ amm sample.sc amm コマンドの後ろにスクリプトのパ ス
Scalaコードをコマンドラインから直接コンパイル・実行! sample.sc println("Hello Ammonite!!") $ amm sample.sc Compiling (synthetic)/ammonite/predef/DefaultPredef.sc Compiling
/home/blacky/sample.sc Hello Ammonite!! その場でコンパイル &実行!
Scalaコードをコマンドラインから直接コンパイル・実行! sample.sc println("Hello Ammonite!!") $ amm sample.sc Compiling (synthetic)/ammonite/predef/DefaultPredef.sc Compiling
/home/blacky/sample.sc Hello Ammonite!! $ amm sample.sc Hello Ammonite!! 2回目以降はコンパイルしないので実行が早い !
Magic Importとの合わせ技 sample_magic.sc import $ivy.`org.jsoup:jsoup:1.12.1` val doc = org.jsoup.Jsoup.connect("https://www.google.com").get println(doc.getElementsByTag("title"))
$ amm sample_magic.sc <title>Google</title> もちろんスクリプトでも Magic Importが使える!
Ammoniteに含まれるライブラリ依存
デフォルトで使える便利なライブラリたち Ammoniteに含まれている依存はMagicImportをせずとも使えます。 その中でもスクリプトの実装に役立つライブラリを一部紹介します。 $ coursier resolve com.lihaoyi:ammonite_2.13.0:1.6.9 ... com.lihaoyi:ammonite-ops_2.13:1.6.9:default com.lihaoyi:os-lib_2.13:0.3.0:default
com.lihaoyi:requests_2.13:0.2.0:default com.lihaoyi:upickle_2.13:0.7.5:default ... ...
デフォルトで使える便利なライブラリたち • ammonite-ops / os-lib ◦ https://github.com/lihaoyi/os-lib ◦ ファイル操作、サブプロセス実行などを提供 •
requests ◦ https://github.com/lihaoyi/requests-scala ◦ HTTPクライアント • upickle ◦ https://github.com/lihaoyi/upickle ◦ シリアライゼーションライブラリ ◦ MsgPack / JSON に対応
実際の活用例
esa.ioの利用状況をDatadogで可視化してみる Stats取得 メトリクス送信 GitLab CI の Scheduled Jobで 1時間に1回実行
ソースコード スライドには収まりきらなかったのでgistで… https://gist.github.com/NomadBlacky/2c56814a1993e327ed2c2e3d 8da01eed
GitLab CI での実行ログ ./amm esa-stats-to-datadog.sc --team septeni-original Get septeni-original.esa.io stats
... { "members": 55, "posts": 298, "posts_wip": 51, "posts_shipped": 247, "comments": 157, "stars": 197, "daily_active_users": 1, "weekly_active_users": 13, "monthly_active_users": 26 } Post stats to Datadog ... Done!
あとはダッシュボードを作ってあげるだけ
Scala製のDatadog APIクライアントを作りました! Starください!!! https://github.com/NomadBlacky/scaladog (宣伝)
そのほか… • Twitterの「いいね」から画像を取得する ◦ https://github.com/NomadBlacky/ammonite-scripts/blob/master/bin/get-twitter-images.sc • 何度閉じてもダイアログが出てくるScalaスクリプト ◦ https://gist.github.com/NomadBlacky/a70d76f5d699994da83c92775935f3f6 ◦
実行は自己責任でお願いします • ScalaからAWS CDKを叩いてインフラを構築する ◦ http://nomadblacky.hatenablog.com/entry/2019/07/14/194607 ◦ Scalaでインフラを作る!
おわりに
参考資料 • Document ◦ http://ammonite.io/ • GitHub ◦ https://github.com/lihaoyi/ammonite •
Blog ◦ http://www.lihaoyi.com • Video ◦ https://vimeo.com/148552858 • IntelliJ IDEA + AmmoniteでScalaスクリプトの開発を始めよう ◦ 弊社エンジニアブログ ◦ http://labs.septeni.co.jp/entry/2018/12/20/120000
まとめ • 便利なREPLとしてのAmmonite ◦ ちょっとScalaを書いて試したい時にAmmoniteを! ◦ 特に「Magic Import」が便利! • ScalaスクリプトとしてのAmmonite
◦ シェルスクリプトだと面倒、sbtだとオーバーという時の選択肢に! ◦ ざっくり書いてもコンパイラが怒ってくれる ▪ (ちょっとしたテスト代わり) ◦ Java/Scalaの資産が使える! ◦ 何よりScalaでスクリプトを書ける!! ▪ 楽しい!!!!
ちなみに: 最初の問題の回答 import upickle.default._ case class Response(page: Int, page_size: Int,
results: Seq[Tag]) case class Tag(name: String, full_size: Long) implicit val responseReader: Reader[Response] = macroR implicit val tagReader: Reader[Tag] = macroR def fetchAllTags(image: String): Seq[Tag] = Stream.from(1).map { page => read[Response]( requests.get( url = s"https://hub.docker.com/api/content/v1/repositories/public/library/$image/tags", params = Map("page" -> page.toString) ).text ) }.takeWhile(r => r.page < r.page_size) .flatMap(_.results) @main def main(image: String): Unit = { val allTags = fetchAllTags(image) println(allTags.minBy(_.full_size)) println(allTags.maxBy(_.full_size)) }