4

コードにいくつかのブール述語が定義されているとします。

def pred1[A](x: A): Boolean = { ... }
def pred2[A](x: A): Boolean = { ... }
def pred3[A](x: A): Boolean = { ... }

pred1ここで、たとえばandの論理和である関数を作成できるようにしたいと考えていますpred3

したがって、次のようなものです:

def pred1Or3[A](x: A) = or(pred1, pred2)

さらに良いことに、独自の結合関数を提供できるように一般化できるとよいでしょう。したがって、代わりに論理 AND が必要な場合は、次のように呼び出します。

def pred1And3[A](x: A) = combine({_ && _}, pred1, pred2)

この方法で同じ基本的な効果を達成できます。

def pred1And3[A](x: A) = Seq(pred1, pred2) map { _(x) } reduce { _ && _ }

しかし、それは少し冗長に見え、意図を曇らせます。Scalaでこれを行う簡単な方法はありますか?

4

4 に答える 4

6

シンプルで、可変数のアイテムを同時に渡すことができるソリューションを次に示します。orケースとより一般的なcombineケースの両方を示しました。

def or[A](ps: (A => Boolean)*) = 
  (a: A) => ps.exists(_(a))

def combine[A](ps: (A => Boolean)*)(op: (Boolean, Boolean) => Boolean) = 
  (a: A) => ps.map(_(a)).reduce(op)

使用例を次に示します。

// "or" two functions
val pred1or3 = or(pred1, pred3)                
pred1or3("the")

// "or" three functions
val pred12or3 = or(pred1, pred2, pred3)        
pred12or3("the")

// apply a dijoined rule directly
or(pred1, pred2, pred3)("the")                 

// combine two functions with "and"
val pred12and3 = combine(pred1, pred3)(_ && _) 
pred12and3("the")

// apply a conjoined rule directly
combine(pred1, pred2, pred3)(_ && _)("the")    

// stack functions as desired (this is "(pred1 || pred3) && (pred1 || pred2)")
combine(or(pred1, pred3), or(pred1, pred2))(_ && _)("a") 
于 2013-01-14T21:56:47.633 に答える
4

過去に使用したソリューションは次のとおりです。

implicit def wrapPredicates[A](f: A => Boolean) = new {
  def <|>(g: A => Boolean) = (x: A) => f(x) || g(x)
  def <&>(g: A => Boolean) = (x: A) => f(x) && g(x)
}

次のように使用します。

val pred12or3 = pred1 <|> pred2 <|> pred3
于 2013-01-14T22:20:44.960 に答える
2

すぐに失敗するが、一般的ではない解決策の 1 つを次に示します。

def or[A](ps: (A => Boolean)*) = (a:A) => ps.exists(_(a))
def and[A](ps: (A => Boolean)*) = (a:A) => ps.forall(_(a))

サンプルセッション

scala> def or[A](ps: (A => Boolean)*) = (a:A) => ps.exists(_(a))
or: [A](ps: A => Boolean*)A => Boolean 
scala> or((x:Int) => {println("a");x > 5}, (x:Int) => {println("b");x < 2})
res6: Int => Boolean = <function1>    
scala> res6(1)
a
b
res7: Boolean = true    
scala> res6(6)
a
res8: Boolean = true
于 2013-01-14T23:02:39.753 に答える
1
def or[A](p: A => Boolean, q: A => Boolean) = (a: A) => p(a) || q(a)
def logic[A](p: A => Boolean, q: A => Boolean)(c: (Boolean, Boolean) => Boolean) = {
  (a: A) => c( p(a) , q(a) )
}

(a: A)関数を返す代わりに、これらのメソッドにパラメーターを追加できます。

def or2[A](a: A)(p: A => Boolean, q: A => Boolean) = p(a) || q(a)
于 2013-01-14T20:57:20.310 に答える