Skip to content

Instantly share code, notes, and snippets.

@ryoco
Last active December 17, 2015 14:49
Show Gist options
  • Save ryoco/5626998 to your computer and use it in GitHub Desktop.
Save ryoco/5626998 to your computer and use it in GitHub Desktop.
rpscala 104回で質問させていただいた スライド 題名と質問したい事がズレているがそのまま
/**
* rpscala 104回 で tototoshi さんが書いてくださった sample code の記憶を頼りにして書いたもの。
* unapply は Boolean でもり値にできるよというのと、
* paramTOStatus のようなものを書きたいのであれば list に object 書けば、という話
* (であってます。。。?)
*/
sealed abstract class Status(val id: Int) {
def unapply(i: Int): Boolean = i == id
}
case object OK extends Status(1)
case object Error extends Status(2)
case object Unknown extends Status(99)
object Status {
val statuses = List(OK, Error)
def paramToStatus(param: Int): Status = {
statuses.find(_.id == param).getOrEles(Unknown)
}
}
!SLIDE
Scala で Enum 的な
==============
* 参考にしたページ
* http://xerial.org/scala-cookbook/recipes/2012/06/29/enumeration/
!SLIDE
なにがしたい?
--------------
* Web appli なので、parameter を数値などで引き継ぐ事が多いため、Intで場合分けが多い
* そうでなくとも DB の値とか
```scala
def paramToResult(param: Int): String = {
param match {
case 1 => {
... // 何か処理
"OK!"
}
case 2 => {
... // 何か処理
"ERROR!"
}
}}
```
マジックナンバーは使いたくありませんし
!SLIDE
Enumを使う
--------------
```scala
object Status extends Enumeration {
val OK = Value(1)
val Error = Value(2)
}
def paramToStatus(param: Int): Status.Value = {
param match {
case Status.OK.id => Status.OK
case Status.Error.id => Status.Error
}
}
```
* Status.Value が気持ちわるいし、Value を書くのを忘れる
!SLIDE
case object を使う
--------------
```scala
sealed abstract class Status(val id: Int)
object Status {
case object OK extends Status(1)
case object Error extends Status(2)
}
def paramToStatus(param: Int): Status = {
param match {
case Status.OK.id => Status.OK
case Status.Error.id => Status.Error
}
}
```
* 冗長な気がするが、Status.Value はなくなった。
!SLIDE
case object を更に拡張する
--------------
* Enum はたぶん、Valueの拡張もできないしあんまり使い勝手がよくないので case object を使う体で
```scala
sealed abstract class Status(val id: Int) {
def bonus: Double
}
```
case object を返す時に bonus の値を決めたいのだがどうすればよいのか
```scala
object Status {
case object OK extends Status(1) // bonus がないのでエラー
case object Error extends Status(2) // bonus がないのでエラー
}
def paramToStatus(param: Int): Status = {
val calcBonusPoint: Double = { ... }
param match {
case Status.OK.id => {
val bonus = calcBonusPoint
Status.OK // bonus もいっしょに返したい
}
case Status.Error.id => {
val bonus = calcBonusPoint
Status.Error // bonus もいっしょに返したい
}
}
}
```
!SLIDE
方法
--------------
* var を使って、getter, setter を定義
* var か…
* case class を作成して、 case object がそれを継承する
* けっこう冗長になる
* ラップする
* スライド書いてて思いついたけどこれがいちばんマシかも?
!SLIDE
var
--------------
```scala
sealed abstract class Status(val id: Int) {
var bonus: Double = 0.0
def bonus_(_bonus: Double) {
bonus = _bonus
}
}
object Status {
case object OK extends Status(1)
case object Error extends Status(2)
}
def paramToStatus(param: Int): Status = {
param match {
case Status.OK.id => {
val result = Status.OK
result.bonus = 0.11
result
}
case Status.Error.id => {
val result = Status.Error
result.bonus = 1.23
result
}
}
}
```
(動くか自信ないです)
!SLIDE
case class
--------------
```scala
sealed abstract class Status(val id: Int) {
def bonus: Double
}
case class OK(val bonus: Double) extends Status(1)
case class Error(val bonus: Double) extends Status(2)
object Status {
case object OK extends OK(0.0)
case object Error extends Error(0.0)
}
def paramToStatus(param: Int): Status = {
param match {
case Status.OK.id => {
new OK(0.11)
}
case Status.Error.id => {
new Status(1.23)
}
}
}
```
キモい
!SLIDE
ラッパー
--------------
```scala
sealed abstract class Status(val id: Int)
object Status {
case object OK extends Status(1)
case object Error extends Status(2)
}
class StatusWrap(s: Status, bonus: Double)
def paramToStatusWrap(param: Int): StatusWrap = {
param match {
case Status.OK.id => {
new StatusWrap(Status.OK, 0.11)
}
case Status.Error.id => {
new StatusWrap(Status.Error, 1.23)
}
}
}
```
Tuple でかけと言われた。
@ryoco
Copy link
Author

ryoco commented May 24, 2013

結論として unapply 使えば match とかかかなくて済むよね、という話と、bonus のようになんか計算して値を返したい場合はタプルにするなどして Status とは別ものとして扱うべき、というご指摘をいただきました。

takezoux2 さんが gist 書いてくださいました。
https://gist.github.com/takezoux2/5627080

@ryoco
Copy link
Author

ryoco commented May 24, 2013

間違ってたらご指摘いただけると幸いです。m(_ _)m

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment