1

正規表現パターンマッチングを行う次のコードがあります。

class UserAgent(val ua: String) {
  val iOS = """.*(iPad|iPhone|iPod).*OS ([0-9_]+).*""".r
  val Android = """.*Android ([0-9.]+).*""".r
  val WindowsPhone = """.*Windows Phone OS.*""".r
  val WebOS = """.*webOS.*""".r
  val BlackBerry = """.*BlackBerry.*""".r
  val WAPBrowser = """.*(MIDP|UP\.Browser|Obigo|Polaris|BREW|Brew|NetFront).*""".r

  var platform = "UnknownPlatform"
  var platformVersion = "UnknownVersion"

  ua match {
    case iOS(_, version) => {
      platform = "IOS"
      platformVersion = version.replace("_", ".")
    }
    case Android(version) => {
      platform = "Android"
      platformVersion = version
    }
    case WindowsPhone() => platform = "WindowsPhone"
    case WebOS() => platform = "WebOS"
    case BlackBerry() => platform = "BlackBerry"
    case WAPBrowser(p) => platform = "WAPBrowser"
  }
}

(簡略化された)コードでテストできるもの:

val tests = for (
    str <- List("Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7",
      "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
      "bla bla Windows Phone OS bla bla",
      "bla bla webOS bla bla",
      "bla bla BlackBerry bla bla",
      "LG-LX600 Polaris/6.0 MMP/2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1")
  ) yield new UserAgent(str)

tests foreach { ua => println(ua.platform + " " + ua.platformVersion) }

私のクラスUserAgentには変更可能な変数platformplatformVersion. 私が達成したいのは、不変性を持たせることです。そのため、 a のようなものtraitを定義platformし、platformVersion異なる値を返すサブクラスを定義します。私が見逃しているのは、そのようなサブクラスをインスタンス化して返すコンストラクターを作成する方法です。

4

2 に答える 2

4

使用できますTuple2

  val (platform, platformVersionOpt) = ua match {
    case iOS(_, version) => "IOS" -> Some(version.replace("_", "."))
    case Android(version) => "Android" -> Some(version)
    case WindowsPhone() => "WindowsPhone" -> None
    case WebOS() => "WebOS" -> None
    case BlackBerry() => "BlackBerry" -> None
    case WAPBrowser(p) => "WAPBrowser" -> None
  }

  val platformVersion = platformVersionOpt.getOrElse("UnknownPlatform")

Scalaの方法は、メソッドでオブジェクトを作成することunapplyです:

object UserAgent {
  val iOS = """.*(iPad|iPhone|iPod).*OS ([0-9_]+).*""".r
  val Android = """.*Android ([0-9.]+).*""".r
  val WindowsPhone = """.*Windows Phone OS.*""".r
  val WebOS = """.*webOS.*""".r
  val BlackBerry = """.*BlackBerry.*""".r
  val WAPBrowser = """.*(MIDP|UP\.Browser|Obigo|Polaris|BREW|Brew|NetFront).*""".r

  def unapply(ua: String): Option[(String, Option[String])] = ua match {
      case iOS(_, version) => Some("IOS" -> Some(version.replace("_", ".")))
      case Android(version) => Some("Android" -> Some(version))
      case WindowsPhone() => Some("WindowsPhone" -> None)
      case WebOS() => Some("WebOS" -> None)
      case BlackBerry() => Some("BlackBerry" -> None)
      case WAPBrowser(p) => Some("WAPBrowser" -> None)
      case _ => None
    }
}

使用法:

scala> val tests = List("Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7", "Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1", "bla bla Windows Phone OS bla bla", "bla bla webOS bla bla", "bla bla BlackBerry bla bla", "LG-LX600 Polaris/6.0 MMP/2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1")

scala> tests foreach {
     |   case UserAgent(p, v) => println(p + " " + v.getOrElse("UnknownVersion"))
     |   case _ => println("UnknownPlatform UnknownVersion")
     | }
IOS 4.0
Android 2.2
WindowsPhone UnknownVersion
WebOS UnknownVersion
BlackBerry UnknownVersion
WAPBrowser UnknownVersion
于 2012-11-19T17:50:52.973 に答える
1

バージョンにaTuple2と anを使用して、1 つの可能な答え。Option[String]また、正規表現をコンパニオン オブジェクトに移動しました。

object UserAgent {
  val iOS = """.*(iPad|iPhone|iPod).*OS ([0-9_]+).*""".r
  val Android = """.*Android ([0-9.]+).*""".r
  val WindowsPhone = """.*Windows Phone OS.*""".r
  val WebOS = """.*webOS.*""".r
  val BlackBerry = """.*BlackBerry.*""".r
  val WAPBrowser = """.*(MIDP|UP\.Browser|Obigo|Polaris|BREW|Brew|NetFront).*""".r
}

class UserAgent(val ua: String) {
  import UserAgent._

  val (platform, version): (String, Option[String]) = ua match {
    case iOS(_, version) =>
      ("IOS", Some(version.replace("_", ".")))
    case Android(version) =>
      ("Android", Some(version))
    case WindowsPhone() => 
      ("WindowsPhone", None)
    case WebOS() => 
      ("WebOS", None)
    case BlackBerry() => 
      ("BlackBerry", None)
    case WAPBrowser(p) => 
      ("WAPBrowser", None)
  }
}
于 2012-11-19T18:03:01.427 に答える