7

Java の冗長さにうんざりしているので、個人的なプロジェクトとして Scala を学んでいます。私が見ているものの多くは気に入っていますが、メソッドにいくつかの単純な契約を効率的に実装する方法があるかどうか疑問に思っています。私は(必ずしも)完全なDbCを求めているわけではありませんが、次の方法はありますか?

  1. パラメータまたはクラス フィールドが必須であることを示します。つまり、null にすることはできません。Option は、OPTIONAL 値が存在するかどうかを明確に示しているように見えますが、クラスの不変条件 (x が必要) を指定し、パラメーターが必要であることを簡潔に指定したいと考えています。ある種の例外をスローする「if」を実行できることはわかっていますが、この非常に一般的なユースケースの言語機能が必要です。私は自分のインターフェースがきついのが好きで、防御的なプログラミングは嫌いです。

  2. 「NonNegativeInt」などの簡潔で効率的な (ランタイム パフォーマンス) 範囲型を定義することは可能ですか? パラメーターが >= 0 であると言いたいです。または範囲内です。PASCALにはこれらのタイプがあり、意図を伝えるのに優れていることがわかりました。これは、C、C++、Java などの大きな欠点の 1 つです。簡潔と言うときは、この型の変数を通常の int と同じくらい簡単に宣言したいという意味です。ヒープ上のすべてのインスタンスを新しくする必要はありません。

4

3 に答える 3

8

ポイント(1)については、Option確かに十分なはずです。これは、scala は null 値をサポートしていますが、主に Java との互換性のためにサポートしているためです。Scala コードには null 値を含めるべきではなく、それを含む場所は非常にローカライズされた場所に制限し、できるだけ早くオプションに変換する必要があります (優れた scala コードでは null 値が伝播されることはありません)。そのため、慣用的な scala では、フィールドまたはパラメーターが型でないOption場合、これは実際にはそれが必須であることを意味します。

現在、(実験的であり、私が知る限り完全にはサポートされていません) というNotNull特性もあります。NotNullトレイトは 2.8 でどのように機能し、実際に使用している人はいますか?を参照してください。

ポイント (2) については、scala 2.10 ではvalue classesが導入されています。Intそれらを使用すると、実行時のオーバーヘッドなしでラップする独自のクラスを定義し、適切と思われる演算子を実装できます。実行時チェックを行う唯一の場所は、法線Intから独自のものに変換するときNonNegativeIntです (int が負の場合は例外をスローします)。このチェックは、新しい を作成するたびに実行されることに注意してください。つまりNonNegativeInt、操作を実行するたびに実行されるため、null 以外のランタイムへの影響があります。しかし、Pascal はまったく同じ状況 (範囲チェックは Pascal で実行時に実行される) にあったので、これで問題ないと思います。

UPDATENonNegativeInt : (ここでは名前を に変更UInt)の実装例を次に示します。

object UInt {
  def apply( i: Int ): UInt = {
    require( i >= 0 )
    new UInt( i )
  }
}
class UInt private ( val i: Int ) extends AnyVal {
  override def toString = i.toString
  def +( other: UInt ) = UInt( i + other.i)
  def -( other: UInt ) = UInt( i - other.i)
  def *( other: UInt ) = UInt( i * other.i)
  def /( other: UInt ) = UInt( i / other.i)
  def <( other: UInt ) = i < other.i
  // ... and so on
}

REPL での使用例:

scala> UInt(123)
res40: UInt = 123

scala> UInt(123) * UInt(2)
res41: UInt = 246

scala> UInt(5) - UInt(8)
java.lang.IllegalArgumentException: requirement failed
        at scala.Predef$.require(Predef.scala:221)
        at UInt$.apply(<console>:15)
        ...
于 2013-03-04T16:01:09.000 に答える