takayuki_tk's diary

本当はScalaとかHaskellを使いたい

抽出子の復習

久しぶりにscala触っててなんで抽出子がパターンマッチで使えるのかわからなくなったので遊んでみた。

object Sample1 {
  def unapply(v: Int): Option[String] = if (v == 1) Some("ok1") else None
}
object Sample2 {
  def unapply(v: Int): Option[String] = if (v == 2) Some("ok2") else None
}
def hoge(v: Int) : String = v match {
  case Sample1(n) => n
  case Sample2(n) => n
  case _ => "ng"
}

println(hoge(1)) // ok1
println(hoge(2)) // ok2
println(hoge(3)) // ng

ようするにこれと同じことかな。

def hoge(v: Int) : String = {
  if (Sample1.unapply(v).isDefined) {
    return Sample1.unapply(v).get
  } else if (Sample2.unapply(v).isDefined) {
    return Sample2.unapply(v).get
  } else {
    "ng"
  }
}

経済は世界史から学べ!

経済の移り変わりを歴史背景を踏まえて教えてくれる。
経済力と軍事力は密接に関係していることが納得できる。

読んでて思わずへーと思う話が多くてなかなか面白い。
歴史で習ったなんとかの改革(享保とか天保とか)って実は失敗だったんだ、とか。
ユダヤ人が金貸しになった理由とか、アメリカが1次大戦に参戦した理由とか。

ただTPPに関してはなぜか経済的観点ばかりで軍事的な考察に触れていないのが気になる。
対米関係が悪化すると日本の安全に支障をきたすから

日本は円高で不利益を得ることが分かっていながらプラザ合意を受け入れた

といっておきながらTPPに関しては

国益に反する条項は拒否する」、と強気の交渉を行えばよいのです。

とまで述べている。
アメリカが主導するTPPを受け入れない場合の日本の安全保障について述べてほしかった。

開眼!JavaScript

プロトタイプチェーンとスコープチェーンの説明が良かった。

オブジェクトとプリミティブについてこれほど詳しい説明はほかにない。

newつけるとオブジェクトを返すけどnewつけないとプリミティブになるとか、思わず手元で試したくなるtips的な要素は事欠かない。

でも、そんなこと知らなくても別に困らないしなぁ。。。

仕事でjQuery使うくらいなら別に知らなくてもいいことばかり。

JavaScritpに深入りしたいなら読めば良いと思う。

ビジネスが分かるエンジニアなんてなりたくない

「新しいことをやると学習コストがかかる」
「サポートが終了したからってビジネス上問題があるのか?」

とかいっていまだにstruts1系を使うことに抵抗を感じないエンジニアになるくらいならビジネスなんて理解しなくていいや。

awesome! Spring-Boot

Spring-Bootがすごいので宣伝です。

僕はXML地獄といわれた頃からSpringをつかっています。

Spring1.x + Struts1.x + ibatis、、とかいう構成。

何かあってもXMLを変更するだけです! コードを修正する必要はありません!

なんて言葉が(確か)は流行っていた。 そりゃあれだけXML書けばXMLで何でもできるでしょ、ってくらいXMLばかりでした。

それに比べれば最近のSpring3.xはだいぶ楽ですが、それでも0から作るのは結構しんどいです。

おそらくほとんどの人が前回作った設定ファイルをコピーしているのではないでしょうか? (少なくとも僕はコピーしてます。。)

Spring-Bootを使えばHello Worldを0から5分でできました。

http://spring.io/guides/gs/spring-boot/#scratch

ここからは上ブログからの抜粋なので英語読める方は上を見てください。
忙しい人はこれだけやれば動きます。

  1. ディレクトリの作成 $mkdir -p src/main/java/hello

2.build.graldeの作成 プロジェクトのルートに作成します。

buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-snapshot" }
        mavenLocal()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:0.5.0.M4")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'gs-spring-boot'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
    maven { url "http://repo.spring.io/libs-snapshot" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:0.5.0.M4") {
        exclude module: "spring-boot-starter-tomcat"
    }
    compile("org.springframework.boot:spring-boot-starter-jetty:0.5.0.M4")
    testCompile("junit:junit:4.11")
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.8'
}

3.controllerの作成 src/main/java/hello/HelloController.java

package hello;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }

}

4.applicationファイルの作成 src/main/java/hello/Application.java

package hello;

import java.util.Arrays;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);

        System.out.println("Let's inspect the beans provided by Spring Boot:");

        String[] beanNames = ctx.getBeanDefinitionNames();
        Arrays.sort(beanNames);
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }
    }

}

あとは

gradle wrapper
./gradlew build && java -jar build/libs/gs-spring-boot-0.1.0.jar

これで http://localhost:8080/ にアクセスできます。

、、、まあここからDBの設定したり、viewの設定したりと茨の道が待ってそうですが。。 きっとその辺もそのうちなんとかなると信じています。

MongoDBとScala -ScalaでMongo

  • コレクションの取得
MongoConnection("localhost")("test")("collections")
  • insert
collection.save(Map("name" -> "takayuki", "work" -> "engineer"))

or

collection += (Map("name" -> "takayuki", "work" -> "engineer"))

or

collection.save(MongoDBObject("name" -> "test3", "work" -> "engineer"))
  • Query DSLを使ったinsert
val doc = MongoDBObject()
doc += "name" -> "hoge"
doc += "work" -> "enginner"
collections += doc

ちなみに += ではなく ++ にするとIterableがかえってきます。(保存はされない。)

おなじIDでもう一度saveすると上書き保存されます。

scala> collection.find().foreach { collection.remove(_) }
scala> collection.save(Map("_id" -> 1, "name" -> "test1"))
res56: com.mongodb.WriteResult = { "serverUsed" : "localhost/127.0.0.1:27017" , "updatedExisting" : false , "n" : 1 , "connectionId" : 1 , "err" :  null  , "ok" : 1.0}
scala> collection.save(Map("_id" -> 1, "name" -> "test1"))
res57: com.mongodb.WriteResult = { "serverUsed" : "localhost/127.0.0.1:27017" , "updatedExisting" : true , "n" : 1 , "connectionId" : 1 , "err" :  null  , "ok" : 1.0}
scala> collection.find().foreach { println }
{ "_id" : 1 , "name" : "test1"}

insertにすると同じIDの場合例外が発生します。

scala> collection.insert(Map("_id" -> 1, "name" -> "test1"))
com.mongodb.MongoException$DuplicateKey: { "serverUsed" : "localhost/127.0.0.1:27017" , "err" : "E11000 duplicate key error index: test.collections.$_id_  dup key: { : 1 }" , "code" : 11000 , "n" : 0 , "connectionId" : 1 , "ok" : 1.0}
at com.mongodb.CommandResult.getException(CommandResult.java:74)

MongoDBとScala

日本語でMongoもだいぶ終わりに近づいたのでScalaで復習してみます。
Mongoのオンライン講義はこちら

https://education.10gen.com/courses/10gen/M101P/2013_September/about

WEEK1はMongoの特徴とか

コンセプト
  • 限りなくRDB並みの機能を追求しつつkey valu store並みのスケーラビリティを目指す。
特徴
  • ドキュメント思考DB。JSON形式でデータを保存できる。
    (Mongo内部ではBSONと呼ばれるJSONを拡張した形式で保存されている。)

  • schema less コレクション内部のドキュメントが同じ形式である必要はない。

RDBとの違い
  • joinをサポートしない。

  • transactionをサポートしない。

JSONは構造を持つ事ができるのでjoinが必要なケースは少ないはず。
またドキュメント単位でアトミックに処理できるのでtransactionにつても問題になるケースはすくない。

インストール

 省略

触ってみる

Biuld.scala

import sbt._
import sbt.Keys._

object MongoScalaBuild extends Build {

  lazy val root = Project(
    id = "mongo-scsala",
    base = file("."),
    settings = Project.defaultSettings ++ Seq(
      name := "mongo-scala",
      organization := "com.github.taka-",
      version := "1.0.0-SNAPSHOT",
      scalaVersion := "2.10.2",
      scalacOptions ++= Seq("-deprecation", "-language:_"),
      libraryDependencies ++= Seq(
        "org.mongodb" %% "casbah" % "2.6.3"
      ),
      initialCommands += """
        import com.mongodb.casbah.Imports._
        import com.mongodb.casbah.query.Imports._
        import com.mongodb.casbah.gridfs.Imports._
"""
    )
  )
}

sbtを立ち上げてconsoleを起動。

  • ローカルで起動したmongoに接続する。

scala> val uri = MongoClientURI("mongodb://localhost:27017/")
uri: com.mongodb.casbah.MongoClientURI = mongodb://localhost:27017/

scala> val mongoClient = MongoClient(uri)
mongoClient: com.mongodb.casbah.MongoClient = com.mongodb.casbah.MongoClient@b1f3c4e

  • testという名前のDBに接続

    scala> val db = mongoClient("test")
    db: com.mongodb.casbah.MongoDB = test

  • collectionsという名前のcollectionを作成

    scala> val collection = db("collections")
    collection: com.mongodb.casbah.MongoCollection = collections

  • とりあえず1件保存

    scala> collection.save(Map("name" -> "takayuki", "work" -> "engineer"))
    res: com.mongodb.WriteResult = { "serverUsed" : "localhost/127.0.0.1:27017" , "n" : 0 , "connectionId" : 1 , "err" : null , "ok" : 1.0}

  • 保存された事を確認

    scala> collection.findOne()
    res: Option[collection.T] = Some({ "_id" : { "$oid" : "52638419b67876df1eb5f9eb"} , "name" : "takayuki" , "work" : "engineer"})