복붙노트

[SCALA] 어떻게 형태 보증 된 열거 유형을 모델링하기 위해?

SCALA

어떻게 형태 보증 된 열거 유형을 모델링하기 위해?

자바는이 같은 스칼라 형태 보증 된 열거이 없습니다. 관련 상수의 집합을 감안할 때, 어떻게 그 상수를 대표하는 스칼라에서 가장 좋은 방법이 될 것입니다?

해결법

  1. ==============================

    1.http://www.scala-lang.org/docu/files/api/scala/Enumeration.html

    http://www.scala-lang.org/docu/files/api/scala/Enumeration.html

    사용 예

      object Main extends App {
    
        object WeekDay extends Enumeration {
          type WeekDay = Value
          val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
        }
        import WeekDay._
    
        def isWorkingDay(d: WeekDay) = ! (d == Sat || d == Sun)
    
        WeekDay.values filter isWorkingDay foreach println
      }
    
  2. ==============================

    2.나는 (당신은뿐만 아니라 경우에 객체를 사용할 수 있습니다) skaffman에 의해 스칼라 문서에서 복사 한 예는 위의 연습에 제한 유틸리티입니다라고해야합니다.

    나는 (당신은뿐만 아니라 경우에 객체를 사용할 수 있습니다) skaffman에 의해 스칼라 문서에서 복사 한 예는 위의 연습에 제한 유틸리티입니다라고해야합니다.

    자바 열거를 닮은 가장 가까운 무언가를 얻기 위해 (즉 재치있는 toString 및 위해 valueOf 방법과 - 아마도 당신이 데이터베이스에 열거 값을 지속하는) 당신은 그것을 조금 수정해야합니다. 당신은 skaffman의 코드를 사용했다면 :

    WeekDay.valueOf("Sun") //returns None
    WeekDay.Tue.toString   //returns Weekday(2)
    

    다음과 같은 선언을 사용하는 반면 :

    object WeekDay extends Enumeration {
      type WeekDay = Value
      val Mon = Value("Mon")
      val Tue = Value("Tue") 
      ... etc
    }
    

    좀 더 합리적인 결과를 얻을 수 있습니다 :

    WeekDay.valueOf("Sun") //returns Some(Sun)
    WeekDay.Tue.toString   //returns Tue
    
  3. ==============================

    3.일을 여러 가지 방법이 있습니다.

    일을 여러 가지 방법이 있습니다.

    1) 문자를 사용합니다. 그것은 상징이 예상되는 비 문자 수락하지 제외하고,하지만, 당신에게 모든 유형의 안전을 제공하지 않습니다. 난 단지 완성도를 위해 여기를 언급하고있다. 다음은 사용의 예입니다 :

    def update(what: Symbol, where: Int, newValue: Array[Int]): MatrixInt =
      what match {
        case 'row => replaceRow(where, newValue)
        case 'col | 'column => replaceCol(where, newValue)
        case _ => throw new IllegalArgumentException
      }
    
    // At REPL:   
    scala> val a = unitMatrixInt(3)
    a: teste7.MatrixInt =
    / 1 0 0 \
    | 0 1 0 |
    \ 0 0 1 /
    
    scala> a('row, 1) = a.row(0)
    res41: teste7.MatrixInt =
    / 1 0 0 \
    | 1 0 0 |
    \ 0 0 1 /
    
    scala> a('column, 2) = a.row(0)
    res42: teste7.MatrixInt =
    / 1 0 1 \
    | 0 1 0 |
    \ 0 0 0 /
    

    2) 클래스 열거를 사용 :

    object Dimension extends Enumeration {
      type Dimension = Value
      val Row, Column = Value
    }
    

    또는, 당신은 직렬화하거나 표시해야하는 경우 :

    object Dimension extends Enumeration("Row", "Column") {
      type Dimension = Value
      val Row, Column = Value
    }
    

    이것은 다음과 같이 사용할 수 있습니다 :

    def update(what: Dimension, where: Int, newValue: Array[Int]): MatrixInt =
      what match {
        case Row => replaceRow(where, newValue)
        case Column => replaceCol(where, newValue)
      }
    
    // At REPL:
    scala> a(Row, 2) = a.row(1)
    <console>:13: error: not found: value Row
           a(Row, 2) = a.row(1)
             ^
    
    scala> a(Dimension.Row, 2) = a.row(1)
    res1: teste.MatrixInt =
    / 1 0 0 \
    | 0 1 0 |
    \ 0 1 0 /
    
    scala> import Dimension._
    import Dimension._
    
    scala> a(Row, 2) = a.row(1)
    res2: teste.MatrixInt =
    / 1 0 0 \
    | 0 1 0 |
    \ 0 1 0 /
    

    불행하게도, 모든 경기가 차지되는 것을 보장하지 않습니다. 내가 경기를 행 또는 열을 넣어 잊어 버린 경우, 스칼라 컴파일러는 나에게 경고 않았을 것이다. 그래서 얻을 수 있지만만큼, 나에게 어떤 종류의 안전을 제공합니다.

    3) 케이스 제품 :

    sealed abstract class Dimension
    case object Row extends Dimension
    case object Column extends Dimension
    

    내가 경기에 케이스를두면 이제 컴파일러는 나에게 경고합니다 :

    MatrixInt.scala:70: warning: match is not exhaustive!
    missing combination         Column
    
        what match {
        ^
    one warning found
    

    그것은 거의 같은 방법으로 사용되는, 심지어 가져 오기를 필요로하지 않습니다

    scala> val a = unitMatrixInt(3)
    a: teste3.MatrixInt =
    / 1 0 0 \
    | 0 1 0 |
    \ 0 0 1 /
    
    scala> a(Row,2) = a.row(0)
    res15: teste3.MatrixInt =
    / 1 0 0 \
    | 0 1 0 |
    \ 1 0 0 /
    

    어느 경우 객체 대신에 열거를 사용하는 이유 당신은 다음, 궁금 할 것이다. 사실, 경우 객체는 장점에게 같은 여기에 많은 시간을 가지고 않습니다. 열거 클래스는, 비록 그러한 요소 반환 (스칼라 2.8 반복자), 반복자지도 flatMap, 필터링 등의 많은 수집 방법을 가지고

    이 답변은 본질적으로 내 블로그에이 문서에서 선택한 부분이다.

  4. ==============================

    4.이름이 열거 형을 선언하는 약간 덜 자세한 방법 :

    이름이 열거 형을 선언하는 약간 덜 자세한 방법 :

    object WeekDay extends Enumeration("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat") {
      type WeekDay = Value
      val Sun, Mon, Tue, Wed, Thu, Fri, Sat = Value
    }
    
    WeekDay.valueOf("Wed") // returns Some(Wed)
    WeekDay.Fri.toString   // returns Fri
    

    물론 여기에서 문제는 이름과 발을 같은 줄에 선언 된 경우 수행하는 것이 더 쉽습니다 동기화 이름과 발스의 순서를 유지해야한다는 것입니다.

  5. ==============================

    5.당신은 예를 들어, 대신 열거의 밀봉 추상 클래스를 사용할 수 있습니다 :

    당신은 예를 들어, 대신 열거의 밀봉 추상 클래스를 사용할 수 있습니다 :

    sealed abstract class Constraint(val name: String, val verifier: Int => Boolean)
    
    case object NotTooBig extends Constraint("NotTooBig", (_ < 1000))
    case object NonZero extends Constraint("NonZero", (_ != 0))
    case class NotEquals(x: Int) extends Constraint("NotEquals " + x, (_ != x))
    
    object Main {
    
      def eval(ctrs: Seq[Constraint])(x: Int): Boolean =
        (true /: ctrs){ case (accum, ctr) => accum && ctr.verifier(x) }
    
      def main(args: Array[String]) {
        val ctrs = NotTooBig :: NotEquals(5) :: Nil
        val evaluate = eval(ctrs) _
    
        println(evaluate(3000))
        println(evaluate(3))
        println(evaluate(5))
      }
    
    }
    
  6. ==============================

    6.단지 enumeratum을 발견했다. 그것은 꽤 놀라운과 더 잘 알려진 아니에요 똑같이 놀라운!

    단지 enumeratum을 발견했다. 그것은 꽤 놀라운과 더 잘 알려진 아니에요 똑같이 놀라운!

  7. ==============================

    7.주변의 모든 옵션에 대한 광범위한 연구를 수행 한 후 "열거는"스칼라에서, 나는 다른 StackOverflow의 스레드에서이 도메인의 훨씬 더 전체 개요를 기록했다. 그것은 내가 JVM 클래스 / 객체 초기화 순서 문제를 해결 한 "밀봉 특성 + 경우 개체"패턴에 대한 솔루션이 포함되어 있습니다.

    주변의 모든 옵션에 대한 광범위한 연구를 수행 한 후 "열거는"스칼라에서, 나는 다른 StackOverflow의 스레드에서이 도메인의 훨씬 더 전체 개요를 기록했다. 그것은 내가 JVM 클래스 / 객체 초기화 순서 문제를 해결 한 "밀봉 특성 + 경우 개체"패턴에 대한 솔루션이 포함되어 있습니다.

  8. ==============================

    8.도티 (스칼라 3) 지원 기본 열거있을 것이다. 여기와 여기에 확인하십시오.

    도티 (스칼라 3) 지원 기본 열거있을 것이다. 여기와 여기에 확인하십시오.

  9. ==============================

    9.스칼라에서 그것은 https://github.com/lloydmeta/enumeratum 매우 편안

    스칼라에서 그것은 https://github.com/lloydmeta/enumeratum 매우 편안

    프로젝트 예제와 문서와 정말 좋은

    그냥 자신의 문서에서이 예는해야 할 의향이 있습니다

    import enumeratum._
    
    sealed trait Greeting extends EnumEntry
    
    object Greeting extends Enum[Greeting] {
    
      /*
       `findValues` is a protected method that invokes a macro to find all `Greeting` object declarations inside an `Enum`
    
       You use it to implement the `val values` member
      */
      val values = findValues
    
      case object Hello   extends Greeting
      case object GoodBye extends Greeting
      case object Hi      extends Greeting
      case object Bye     extends Greeting
    
    }
    
    // Object Greeting has a `withName(name: String)` method
    Greeting.withName("Hello")
    // => res0: Greeting = Hello
    
    Greeting.withName("Haro")
    // => java.lang.IllegalArgumentException: Haro is not a member of Enum (Hello, GoodBye, Hi, Bye)
    
    // A safer alternative would be to use `withNameOption(name: String)` method which returns an Option[Greeting]
    Greeting.withNameOption("Hello")
    // => res1: Option[Greeting] = Some(Hello)
    
    Greeting.withNameOption("Haro")
    // => res2: Option[Greeting] = None
    
    // It is also possible to use strings case insensitively
    Greeting.withNameInsensitive("HeLLo")
    // => res3: Greeting = Hello
    
    Greeting.withNameInsensitiveOption("HeLLo")
    // => res4: Option[Greeting] = Some(Hello)
    
    // Uppercase-only strings may also be used
    Greeting.withNameUppercaseOnly("HELLO")
    // => res5: Greeting = Hello
    
    Greeting.withNameUppercaseOnlyOption("HeLLo")
    // => res6: Option[Greeting] = None
    
    // Similarly, lowercase-only strings may also be used
    Greeting.withNameLowercaseOnly("hello")
    // => res7: Greeting = Hello
    
    Greeting.withNameLowercaseOnlyOption("hello")
    // => res8: Option[Greeting] = Some(Hello)
    
  10. from https://stackoverflow.com/questions/1321745/how-to-model-type-safe-enum-types by cc-by-sa and MIT license