Scalaで自然文っぽくコードを書く

 Scalaで自然文っぽくコードを書く

223977120819323905c8e4e55a2365ed?s=128

Yohei TSUJI

May 23, 2019
Tweet

Transcript

  1. Scalaで⾃然⽂っぽく コードを書く 2019/05/23 Scala関⻄ × MixLeap

  2. ⾃⼰紹介 Yohei TSUJI(@crossroad0201) Scalaはエンジニア⼼をくすぐる⾔語です 2

  3. Scalaは DSL(※) を作成するための ⾔語仕様が豊富です ので… 3 ※DSL=Domain Specific Language

  4. あたかも⾃然⽂の⽂章のように コードを書けます 4

  5. 百聞は⼀⾒にしかず 5

  6. 例その1 Scala Testのアサート⽂ 6

  7. 7 "abc" should have length 3 false should not be

    true 引⽤:http://www.scalatest.org/user_guide/using_matchers
  8. 8 new File("test.txt") should be a 'file class Example {

    def isOrganization: Boolean = true } new Example() should be an 'organization 引⽤:http://www.scalatest.org/user_guide/using_matchers
  9. 9 Seq("apple", "orange") should contain ("apple") (Seq("A", "B", "C") should

    contain only ("a", "b", "c")) (after being lowerCased) 引⽤:http://www.scalatest.org/user_guide/using_matchers
  10. 10 case class Book(title: String, author: String) val book =

    Book( "Programming in Scala", "Martin Odersky” ) book should have( 'title ("Programming in Scala"), 'author ("Martin Odersky") ) 引⽤:http://www.scalatest.org/user_guide/using_matchers
  11. 例その2 RESTful APIのルーティング 11

  12. 12 object WebServer extends HttpApp { override def routes: Route

    = path("hello") { get { complete(HttpEntity( ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>” )) } } } class MinimalHttpApp extends HttpApp { @Override protected Route routes() { return path("hello", () -> get(() -> complete("<h1>Say hello to akka-http</h1>") ) ); } } Scala Java 引⽤: https://doc.akka.io/docs/akka-http/current/routing-dsl/index.html
  13. 例その3 ⽇本語でも 13

  14. 14 val 辻 = ユーザー("辻") val Scala関⻄MixLeap = イベント( タイトル

    = "Scala関⻄×MixLeap", 募集⼈数 = 60 ) 辻 は (Scala関⻄MixLeap に申し込む) match { case 参加できます(_受付票) => println(s"受付票は ${_受付票} です") case 補⽋です(_キャンセル待ち) if _キャンセル待ち.そんなに待てない => _キャンセル待ち をキャンセルする() println("キャンセル待ちが多いので、申込みをキャンセルしました") case 補⽋です(_キャンセル待ち) => println(s"${_キャンセル待ち.待ち⼈数}⼈待ちです") }
  15. DSL作成で知っておきたい Scalaの構⽂ 15

  16. 関数名に記号が使える Scalaでは関数の名前に記号が使えます。 16 class Path(path: String) { def /(child: String):

    Path = ??? } new Path("foo")./("bar")./("hoge")./("moge") new Path("foo") / "bar" / "hoge" / "moge"
  17. レシーバーとメソッドの区切りに 半⾓スペースが使える メソッドを呼び出す場合は、レシーバーとメソッド名の区切りに ピリオドだけでなく半⾓スペースも使えます。 17 class User(name: String) { def

    renameTo(newName: String) = ??? def bornIn(year:Int, month: Int, day:Int) = ??? } val user = new User("tsuji") user.renameTo("TSUJI") user renameTo "TSUJI" user.bornIn(2019, 5, 20) user bornIn (2019, 5, 20)
  18. パラメタ指定時の (…) を省略できる パラメタの数が1つだけメソッドは、パラメタ指定時の (…) を省 略できます。 18 class Greeter(name:

    String) { def say(greeting: String) = ??? } new Greeter("Tsuji").say("Hello") new Greeter("Tsuji") say "Hello"
  19. パラメタを名前指定できる 関数を呼び出す場合などに、 パラメタを パラメタ名=パラメタ値 形式で指定できます。 19 def address( postCode: Option[String]

    = None, country: String, state: Option[String] = None, prefecture: String, city: String, address: String, building: Option[String] = None ) = ??? address( postCode = Some("999-9999"), country = "Japan", prefecture = "Osaka", city = "Osaka", address = "1-1-1" )
  20. {…} でパラメタを渡せる Scalaでは関数にパラメタを渡すときに (…) だけでなく {…} も 使えます。 {…} を使うことであたかも⾔語仕様で⽤意されている構⽂のよ

    うに関数を使うことができます。 20 trait Transaction def transactional[RESULT](f: Transaction => RESULT): RESULT = ??? transactional(tx => /*処理*/) transactional { tx => // 処理 }
  21. 既存の型にメソッド追加できる 「Implicit conversion」と呼ばれる機能で、既存の型を修正する ことなくメソッドを追加(したかのように⾒せる)できます。 ※ただし乱⽤しないように!! 21 implicit class GreetableString(value: String)

    { def sayHello: String = s"Hello $value” } "World" sayHello
  22. まとめ • Scalaは⾔語仕様レベルでDSLが考慮されており、 ⾃然な表現のDSLを作成することができます。 • 業務アプリケーションでも、うまくDSLを作ることが 可読性の⾼いコードを記述する助けになるはずです。 • ドメイン駆動設計を採⽤している場合は、ドメイン モデルをDSLにすることで、ユースケースを⾃然⽂

    のように書けます。 22
  23. ご清聴ありがとうございました 23