1

以下のコードで、queryオブジェクトを配置する場所 (ループ内または外側) は重要ですか? 読みやすくするために、この最初のバージョンをお勧めします。

class MyClass {
  db withSession {
    names.foreach { name =>
      val query = MyEntity.createFinderBy(_.name)  <----------
      query.list(text).foreach(res =>
        doSomething
      }
    }
  }
}

しかし、この 2 番目のバージョンの方が優れているのではないでしょうか。

class MyClass {
  db withSession {
    val query = MyEntity.createFinderBy(_.name)  <----------
    names.foreach { name =>
      query.list(text).foreach(res =>
        doSomething
      }
    }
  }
}

あるいは?

class MyClass {
  val query = MyEntity.createFinderBy(_.name)  <----------
  db withSession {
    names.foreach { name =>
      query.list(text).foreach(res =>
        doSomething
      }
    }
  }
}

Java では、クラスの先頭にある static final フィールドに配置します...

4

2 に答える 2

2

いいえ、そうではありません。最初の例では、各要素に対してcreateFinderBy(および も) を呼び出すように具体的に指示したためです。listこれらのメソッドが毎回同じ値を返す (つまり、参照が透過的である) という保証はないため、値をメモ化したり、コードを 2 番目または 3 番目の例に合わせて最適化したりすることはできません。

メソッド自体に注釈を付けることができれば、またはコンパイラがそれを解決できるなら、それは素晴らしい機能ですが、現時点ではそうではありません。

余談ですが、メソッドを変更して、キャッシュにcreateFinderBy値を保存し、メソッドを使用して値を返すようにすることもできます。これにより、クエリが既にマップにある場合はキャッシュされた値が返されます。そうでない場合は、クエリを計算してキャッシュします。mutable.MapgetOrElseUpdate

于 2012-09-06T13:59:16.310 に答える
2

scalac は効果システムを使用しないため、コードを最適化しません (できません)。これにより、最適化によってコードが壊れる可能性があるかどうかを scalac が気にすることはほとんど不可能になります。たとえば、MyEntity.createFinderBy(_.name)純粋でない場合 (アクセス数をカウントするカウンターをインクリメントする可能性があります)、1 回または反復ごとに実行されると変更されます。

そのような場合、関数リテラルの位置を変更することを提案できます。

scala> 1 to 3 foreach {x => println("x"); println(x)}
x
1
x
2
x
3

scala> 1 to 3 foreach {println("x"); x => println(x)}
x
1
2
3

2 番目の例では、 foreach に渡された関数を返すブロックが (他の式を実行した後に) 作成されますが、前者の例では、ブロック全体が 1 つの関数です。

于 2012-09-06T13:59:41.563 に答える