SlideShare a Scribd company logo
1 of 40
Download to read offline
はてなブックマーク
in Scala
伊奈 林太郎
id:tarao @oarat
2015-08-01
@ Scala 関西 Summit 2015
自己紹介
名前  
い な
伊奈   
りんたろう
林太郎  (id:tarao @oarat)
2008-08 はてなインターン
2008-10 はてなアルバイト (ブックマークチーム)
2010-04 日本学術振興会 特別研究員 (DC1)
2013-04 はてな正社員
2013-12 ブックマークチーム
◮ アルゴリズム屋さん
◮ 検索技術 > 機械学習 ≫ アドテク
◮ 最近は設計したり基盤寄りな部分を担当したり
自己紹介
名前  
い な
伊奈   
りんたろう
林太郎  (id:tarao @oarat)
Scala 歴: 4ヶ月
◮ slick-jdbc-extension
◮ 型レベルのラムダ計算
◮ Software Design 2015 年 8 月号
大学時代は
◮ 研究室: 型理論, プログラム意味論, 証明支援系
◮ OCaml が公用語
◮  
gradual typing
漸進的型付け の Java 系言語への応用を研究
いちから作りなおし!
いちから作りなおし!
Scalaで!
いちから作りなおし!
Scalaで!
ねらい
◮ コードベースの肥大化・老朽化への対処
◮ 根本的なアーキテクチャの再設計
DISCLAIMER
◮ 内容は開発中のもの
◮ 実際のリリース時には変更の可能性あり
◮ 最終的にどうなったか公表するかどうか未定
構成
◮ 前後で Perl/Scala に分割
◮ コアは B!以外からも利用
◮ Presso
◮ B!KUMA
ビュー (Perl)
◮ ユーザ認証
◮ HTML のレンダリング
コア (Scala)
◮ API サーバ
◮ 社内基盤的側面
Why Scala?
◮ 変更の少ない重要部分は堅牢にしたい
◮ 型安全性
◮ ドメイン駆動設計
◮ Mackerel チームでの使用実績
◮ LL 勢にも書きやすい
◮ エンジニアのチーム異動が容易になる
◮ Perl との心中を避ける
◮ 個人的には
◮ 新言語を導入するなら関数型でないと許さん
◮ 強い静的型付言語でないと許さん
◮ 型推論ないと許さん
Why Perl?
◮ 頻繁に変更があっても開発が楽
◮ デザイナも HTML テンプレートを触る
◮ コンパイルしなおさなくてよい
◮ ローカル開発環境での作業が容易
◮ 学習コスト 0
◮ 認証まわりは共通 Perl モジュールでやりたい
◮ あとで捨ててまた作り直すかもしれない
フレームワークフレームワークフレームワークフレームワークフレームワークフレームワークフレームワーク
これまで (Perl)
第 1 世代 Apache mod perl 上の簡易的なもの
第 2 世代 内製の Perl 版 RoR 的な重厚なもの
◮ 学習コスト高
◮ 自由がきかない
第 3 世代 薄いフレームワークの集合
◮ よくできた小モジュールの組み合わせ
◮ 自由度が高く入れ替え可能
◮ ≫ YAPC::Asia 2015 talk by id:hitode909
新コアサーバ (Scala)
Web
◮ Scalatra
◮ APISchemaのScala 版 (予定)
DB
◮ Slick 3.0
◮ slick-jdbc-extension
◮ 独自のべんりに使う層
テスト
◮ ScalaTest
Webフレームワーク
Scalatra
◮ API サーバなので簡素でよい
◮ 返り値が Any なの嫌なのでラップして利用
APISchema
◮ Perl での実績を元に Scala 版を実装予定
◮ 簡単な DSL で定義
◮ JSON Schema によるリソース定義
◮ パスごとのリクエストとレスポンス定義
◮ 同じ定義から自動生成
◮ ドキュメント
◮ ルーティング処理
DBフレームワーク
Slick 3.0
◮ 非同期 DB アクセスも利用したい
◮ 文字列補間による生 SQL のみで利用
◮ 予想外のクエリが生成されるのを防ぐ
◮ インフラエンジニアでも読めるように
◮ (あとでクエリビルダ導入の可能性はある)
◮ 拡張モジュール slick-jdbc-extension
◮ 文字列補間のリストの扱いなどを強化
◮ カラム名での結果型へのマッピング
◮ ≫ 『Scala で生 SQL - Slick の SQL 補間子にリストを渡す 他』
DBフレームワーク
独自層
◮ DB インスタンス管理
◮ マスター/スレーブ切り替え
◮ テスト時のプロセス毎 DB 分離
◮ モード管理 (トランザクション, 非同期)
◮ リクエストスレッドごとの非同期接続数管理
ドメイン駆動設計ドメイン駆動設計ドメイン駆動設計ドメイン駆動設計ドメイン駆動設計ドメイン駆動設計ドメイン駆動設計
旧ブックマークでは
DDDっぽいこともやられていた
◮ アプリケーションサービス
◮ ドメインサービス
◮ ドメインモデル
◮ CQRS (コマンドクエリ責務分離)
旧ブックマークでは
失敗
◮ ユビキタス言語がないまま進んだ
◮ e.g. お気に入り or フォロー
◮ e.g. 3 つの「インタレスト」概念
◮ 方針が徹底されなかった
◮ アプリ層とコントローラ層が互いに侵食
◮ 内製の Perl 版 Active Record 的 O/R マッパ
◮ モデル, サービス, リポジトリが渾然一体
◮ 近頃の他 Perl プロダクトではまともになった
◮ Perl の限界
◮ インタフェースが言語機能にない
きちんとDDDしたい!
◮ 有志の社内勉強会を実施
◮ 非エンジニアメンバーとも共有・議論
◮ Scala でのよいやり方を模索
方針
◮ リポジトリはインタフェース (依存関係逆転の原則)
◮ ドメインに実装上の都合を持ち込まない
悩んだ点と作戦
◮ 依存性の注入どうするか
◮ Cake Pattern を積極採用
◮ has-a 関係を引くときの N+1 問題
◮ 関係モナドを定義
◮ トランザクションどこで張るか
◮ いったん極小な範囲 (インフラ層) で
◮ 全体的に結果整合性
悩んだ点と作戦
◮ 依存性の注入どうするか
◮ Cake Pattern を積極採用
◮ has-a 関係を引くときの N+1 問題
◮ 関係モナドを定義
◮ トランザクションどこで張るか
◮ いったん極小な範囲 (インフラ層) で
◮ 全体的に結果整合性
Cake Pattern
package repo
trait SomeComponent {
def someLoader: SomeLoader
// リポジトリインタフェース
trait SomeLoader {
def find(...) = ...
} }
package db
trait SomeComponent
extends repo.SomeComponent {
def someLoader: SomeLoader =
SomeLoader
// 実装
object SomeLoader
extends SomeLoader { ... }
}
package app
trait ServiceComponent {
// 依存の明示
self: repo.SomeComponent =>
trait SomeService {
...
someLoader.find(...)
...
} }
package main
object AppRoot
extends db.SomeComponent
with app.ServiceComponent
with ...
Cake Pattern
ポイント
◮ trait を入れ子にしておく
◮ 使う側は自分型アノテーションで依存を明示
◮ AppRootには実装コンポーネントを結合
◮ TestRoot等を用意して別実装に入れ替えも可
◮ 単体テストでコンポーネント単位で入れ替え
◮ 全体でテスト用 DB ハンドラ実装に入れ替え
object TestRoot
extends repo.SomeMockedComponent
with app.ServiceComponent
with ...
N+1問題1 件の場合
val bookmark: Bookmark = ...
val locaiton: Location = bookmark.toLocation
// SELECT * FROM location WHERE ...
n 件の場合: n + 1 回のクエリが必要
val bookmarks: Seq[Bookmark] = ...
// SELECT * FROM bookmark WHERE ...
val locations: Seq[Location] = bookmarks.map(_.toLocation)
// SELECT * FROM location WHERE ...
// SELECT * FROM location WHERE ...
//
... × n
本当はせいぜい 2 回で済む
val locations: Seq[Location] =
locationLoader.findAll(bookmarks.map(_.locationId))
// SELECT * FROM location WHERE location_id IN (...)
N+1問題回避策(1) JOIN
解決方法
◮ bookmarksと locaitonsをいっぺんに引く
◮ JOIN して引けば可能
問題点
◮ 一般的には JOIN したくない場合もある
◮ e.g. bookmarksが入力となるサービス内
◮ NG: 実装上の都合がモデルの引き方を左右する
N+1問題回避策(2) 愚直に
解決方法
◮ ていねいに関係先を引いてくる
問題点
◮ 元の要素と対応づけたい場合に面倒
val bookmarks: Seq[Bookmark] = ...
val locations: Seq[Location] =
locationLoader.findAll(bookmarks.map(_.locationId))
val id2loc = locations.map{ l => l.id -> l }.toMap
val bookmarkAndLocationList: Seq[(Bookmark, Location)] =
bookmarks.map{ b => (b, id2loc(b.locationId)) }
関係モナド
class BookmarkRelation(b: Bookmark) {
def toLocation: Monad[Location, Bookmark] =
HasA.Monadic(b, new HasA[Bookmark, Location] { ... }) }
implicit def bookmarkRel(b: Bookmark) =
new BookmarkRelation(b)
val bookmark: Bookmark = ... // 1 件の場合
val location: Option[Location] = bookmark.toLocation
val bookmarks: Seq[Bookmark] = ... // n 件の場合
val locations: Seq[Location] = bookmarks.map(_.toLocation)
関係モナド
class BookmarkRelation(b: Bookmark) {
def toLocation: Monad[Location, Bookmark] =
HasA.Monadic(b, new HasA[Bookmark, Location] { ... }) }
implicit def bookmarkRel(b: Bookmark) =
new BookmarkRelation(b)
val bookmark: Bookmark = ... // 1 件の場合
val location: Option[Location] = bookmark.toLocation
val bookmarks: Seq[Bookmark] = ... // n 件の場合
val locations: Seq[Location] = bookmarks.map(_.toLocation)
◮ toLocationの返り値はモナドのインスタンス
関係モナド
class BookmarkRelation(b: Bookmark) {
def toLocation: Monad[Location, Bookmark] =
HasA.Monadic(b, new HasA[Bookmark, Location] { ... }) }
implicit def bookmarkRel(b: Bookmark) =
new BookmarkRelation(b)
val bookmark: Bookmark = ... // 1 件の場合
val location: Option[Location] = bookmark.toLocation
val bookmarks: Seq[Bookmark] = ... // n 件の場合
val locations: Seq[Location] = bookmarks.map(_.toLocation)
◮ toLocationの返り値はモナドのインスタンス
◮ クエリはモナドから結果への暗黙変換で発生
関係モナド
class BookmarkRelation(b: Bookmark) {
def toLocation: Monad[Location, Bookmark] =
HasA.Monadic(b, new HasA[Bookmark, Location] { ... }) }
implicit def bookmarkRel(b: Bookmark) =
new BookmarkRelation(b)
val bookmark: Bookmark = ... // 1 件の場合
val location: Option[Location] = bookmark.toLocation
val bookmarks: Seq[Bookmark] = ... // n 件の場合
val locations: Seq[Location] = bookmarks.map(_.toLocation)
◮ toLocationの返り値はモナドのインスタンス
◮ クエリはモナドから結果への暗黙変換で発生
◮ 関係の引き方はモナド生成時に指定
関係モナド
モナドのパラメータ
◮ 複数件の引き方のみを実装
new HasA[Bookmark, Location] {
def map(bookmarks: Seq[Bookmark]): Seq[Location] =
locationLoader.findAll(bookmarks.map(_.locationId)) }
暗黙変換
◮ Seq[] を一気に変換して N+1 問題を解決
implicit def run[R, Q](
ms: Seq[Monad[R, Q]]
): Seq[R] = ... // HasA.map を使った処理
implicit def toResultOption[R, Q](
m: Monad[R, Q]
): Option[R] = run(Seq(m)).headOption
関係モナド
元の要素と対応づける場合
type JoinBookmarkLocation =
Join[(Bookmark, Location), LocationId, Bookmark, Location]
def withLocation = Join.Monadic(b, new JoinBookmarkLocation {
def map(bs: Seq[Bookmark]): Seq[Location] = ...
def leftKey(b: Bookmark): LocationId = b.locationId
def rightKey(l: Location): LocationId = l.id
def merge(b: Bookmark, l: Location) = (b, l)
})
val bookmarks: Seq[Bookmark] = ...
val bookmarkAndLocationList: Seq[(Bookmark, Location)] =
bookmarks.map(_.withLocation)
◮ ID による紐づけは変換時にやってくれる
詳しくは
OSS 化された実装
◮ github.com/tarao/bullet-scala
日本語での解説
◮ bullet-scala: N+1 クエリ問題を回避する
CICICICICICICI
CI
docker で
◮ 単一の.jar ファイルを生成
◮ テストを実行
◮ 開発用ホスト環境 (予定)
◮ chrootして本番環境に?
生成した.jar ファイル
◮ テストに使用 (本番と同一バイナリ)
◮ デプロイに使用
まとめ
◮ はてなブックマークを作りなおし
◮ Perl と Scala のハイブリッド
◮ 薄いフレームワークを採用
◮ Scala での DDD 実践方法を模索
◮ docker でモダンな CI
WE ARE HIRING
◮ Scala エンジニア 絶賛募集中
◮ 東京 / 京都 どちらの勤務でも可

More Related Content

What's hot

なぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriなぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriYuta Okamoto
 
rpscala35-scala2.9.0
rpscala35-scala2.9.0rpscala35-scala2.9.0
rpscala35-scala2.9.0Kenji Yoshida
 
Why Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriWhy Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriYuta Okamoto
 
Sns suite presentation
Sns suite presentationSns suite presentation
Sns suite presentationJason Namkung
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Naoki Aoyama
 
これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6TanUkkii
 
Frege, What a Non-strict Language
Frege, What a Non-strict LanguageFrege, What a Non-strict Language
Frege, What a Non-strict Languagey_taka_23
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdfHiroshi Ono
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
 
LINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XMLLINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XMLShinichiAoyagi
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/PrismNaoki Aoyama
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたってTsuyoshi Matsudate
 
15分でざっくり分かるScala入門
15分でざっくり分かるScala入門15分でざっくり分かるScala入門
15分でざっくり分かるScala入門SatoYu1ro
 
197x 20090704 Scalaで並行プログラミング
197x 20090704 Scalaで並行プログラミング197x 20090704 Scalaで並行プログラミング
197x 20090704 Scalaで並行プログラミングNet Penguin
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Ra Zon
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルなおき きしだ
 
【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream APIdcomsolution
 

What's hot (20)

なぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuriなぜリアクティブは重要か #ScalaMatsuri
なぜリアクティブは重要か #ScalaMatsuri
 
rpscala35-scala2.9.0
rpscala35-scala2.9.0rpscala35-scala2.9.0
rpscala35-scala2.9.0
 
Why Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuriWhy Reactive Matters #ScalaMatsuri
Why Reactive Matters #ScalaMatsuri
 
Sns suite presentation
Sns suite presentationSns suite presentation
Sns suite presentation
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
Rpscala2011 0601
Rpscala2011 0601Rpscala2011 0601
Rpscala2011 0601
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術
 
Phantom Type in Scala
Phantom Type in ScalaPhantom Type in Scala
Phantom Type in Scala
 
これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6これからのJavaScriptー関数型プログラミングとECMAScript6
これからのJavaScriptー関数型プログラミングとECMAScript6
 
Frege, What a Non-strict Language
Frege, What a Non-strict LanguageFrege, What a Non-strict Language
Frege, What a Non-strict Language
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
LINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XMLLINQ 概要 + 結構便利な LINQ to XML
LINQ 概要 + 結構便利な LINQ to XML
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/Prism
 
これから Haskell を書くにあたって
これから Haskell を書くにあたってこれから Haskell を書くにあたって
これから Haskell を書くにあたって
 
15分でざっくり分かるScala入門
15分でざっくり分かるScala入門15分でざっくり分かるScala入門
15分でざっくり分かるScala入門
 
197x 20090704 Scalaで並行プログラミング
197x 20090704 Scalaで並行プログラミング197x 20090704 Scalaで並行プログラミング
197x 20090704 Scalaで並行プログラミング
 
Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]Scalaで萌える関数型プログラミング[完全版]
Scalaで萌える関数型プログラミング[完全版]
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
 
【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API【java8 勉強会】 怖くない!ラムダ式, Stream API
【java8 勉強会】 怖くない!ラムダ式, Stream API
 

Similar to はてなブックマーク in Scala

Scalaプログラミング・マニアックス
Scalaプログラミング・マニアックスScalaプログラミング・マニアックス
Scalaプログラミング・マニアックスTomoharu ASAMI
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Ra Zon
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門masatora atarashi
 
Beginners Scala in FAN 20121009
Beginners Scala in FAN 20121009Beginners Scala in FAN 20121009
Beginners Scala in FAN 20121009Taisuke Shiratori
 
RubyとJavaScriptに見る第一級関数
RubyとJavaScriptに見る第一級関数RubyとJavaScriptに見る第一級関数
RubyとJavaScriptに見る第一級関数Altech Takeno
 
オブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional Programmingオブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional ProgrammingTomoharu ASAMI
 
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsShogo Sensui
 
Scala Daysに行ってみて
Scala Daysに行ってみてScala Daysに行ってみて
Scala Daysに行ってみてKota Mizushima
 
関数モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第8回】
関数モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第8回】関数モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第8回】
関数モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第8回】Tomoharu ASAMI
 
Scala による自然言語処理
Scala による自然言語処理Scala による自然言語処理
Scala による自然言語処理Hiroyoshi Komatsu
 
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章YOSHIKAWA Ryota
 
実務者のためのかんたんScalaz
実務者のためのかんたんScalaz実務者のためのかんたんScalaz
実務者のためのかんたんScalazTomoharu ASAMI
 
Ruby on Rails 入門
Ruby on Rails 入門Ruby on Rails 入門
Ruby on Rails 入門Yasuko Ohba
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!Shohei Okada
 
objc2swift 〜 Objective-C から Swift への「コード&パラダイム」シフト
objc2swift 〜 Objective-C から Swift への「コード&パラダイム」シフトobjc2swift 〜 Objective-C から Swift への「コード&パラダイム」シフト
objc2swift 〜 Objective-C から Swift への「コード&パラダイム」シフトTaketo Sano
 
Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Seiya Tokui
 

Similar to はてなブックマーク in Scala (20)

Scalaプログラミング・マニアックス
Scalaプログラミング・マニアックスScalaプログラミング・マニアックス
Scalaプログラミング・マニアックス
 
Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]Scalaで萌える関数型プログラミング[1.1.RC1]
Scalaで萌える関数型プログラミング[1.1.RC1]
 
関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
Beginners Scala in FAN 20121009
Beginners Scala in FAN 20121009Beginners Scala in FAN 20121009
Beginners Scala in FAN 20121009
 
ATN No.2 Scala事始め
ATN No.2 Scala事始めATN No.2 Scala事始め
ATN No.2 Scala事始め
 
RubyとJavaScriptに見る第一級関数
RubyとJavaScriptに見る第一級関数RubyとJavaScriptに見る第一級関数
RubyとJavaScriptに見る第一級関数
 
オブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional Programmingオブジェクト指向開発におけるObject-Functional Programming
オブジェクト指向開発におけるObject-Functional Programming
 
Functional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.jsFunctional JavaScript with Lo-Dash.js
Functional JavaScript with Lo-Dash.js
 
Scala Daysに行ってみて
Scala Daysに行ってみてScala Daysに行ってみて
Scala Daysに行ってみて
 
Trait in scala
Trait in scalaTrait in scala
Trait in scala
 
関数モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第8回】
関数モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第8回】関数モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第8回】
関数モデル 【クラウドアプリケーションのためのオブジェクト指向分析設計講座 第8回】
 
Scala による自然言語処理
Scala による自然言語処理Scala による自然言語処理
Scala による自然言語処理
 
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
【Topotal輪読会】JavaScript で学ぶ関数型プログラミング 2 章
 
MoteMote Compiler Plugin
MoteMote Compiler PluginMoteMote Compiler Plugin
MoteMote Compiler Plugin
 
実務者のためのかんたんScalaz
実務者のためのかんたんScalaz実務者のためのかんたんScalaz
実務者のためのかんたんScalaz
 
Ruby on Rails 入門
Ruby on Rails 入門Ruby on Rails 入門
Ruby on Rails 入門
 
Scala2.8への移行
Scala2.8への移行Scala2.8への移行
Scala2.8への移行
 
PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!PHP 2大 web フレームワークの徹底比較!
PHP 2大 web フレームワークの徹底比較!
 
objc2swift 〜 Objective-C から Swift への「コード&パラダイム」シフト
objc2swift 〜 Objective-C から Swift への「コード&パラダイム」シフトobjc2swift 〜 Objective-C から Swift への「コード&パラダイム」シフト
objc2swift 〜 Objective-C から Swift への「コード&パラダイム」シフト
 
Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用Chainerの使い方と自然言語処理への応用
Chainerの使い方と自然言語処理への応用
 

More from Lintaro Ina

Gradual Typing for Generics
Gradual Typing for GenericsGradual Typing for Generics
Gradual Typing for GenericsLintaro Ina
 
Emacs上のターミナルを最強に
Emacs上のターミナルを最強にEmacs上のターミナルを最強に
Emacs上のターミナルを最強にLintaro Ina
 
論理と計算のしくみ 5.3 型付きλ計算 (前半)
論理と計算のしくみ 5.3 型付きλ計算 (前半)論理と計算のしくみ 5.3 型付きλ計算 (前半)
論理と計算のしくみ 5.3 型付きλ計算 (前半)Lintaro Ina
 
HTMLからの本文抽出
HTMLからの本文抽出HTMLからの本文抽出
HTMLからの本文抽出Lintaro Ina
 
『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ 『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ Lintaro Ina
 
『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみLintaro Ina
 

More from Lintaro Ina (6)

Gradual Typing for Generics
Gradual Typing for GenericsGradual Typing for Generics
Gradual Typing for Generics
 
Emacs上のターミナルを最強に
Emacs上のターミナルを最強にEmacs上のターミナルを最強に
Emacs上のターミナルを最強に
 
論理と計算のしくみ 5.3 型付きλ計算 (前半)
論理と計算のしくみ 5.3 型付きλ計算 (前半)論理と計算のしくみ 5.3 型付きλ計算 (前半)
論理と計算のしくみ 5.3 型付きλ計算 (前半)
 
HTMLからの本文抽出
HTMLからの本文抽出HTMLからの本文抽出
HTMLからの本文抽出
 
『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ 『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ
 
『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ『BrandSafe はてな』のアドベリフィケーションのしくみ
『BrandSafe はてな』のアドベリフィケーションのしくみ
 

はてなブックマーク in Scala