2017-09-21 6 views
0

私はスカラを学ぼうとしていますが、部分的に適用された関数よりもカリング関数を使うのは混乱します。スカラーの関数のカレント化と部分的に適用された関数のベストユースケース

私はこれらの概念が重複していないことは確かですが、異なるアプローチの真の目的を見ることはできません。私はこのコードを試した

object CurryTest extends App { 

    def filter(xs: List[Int], p: Int => Boolean): List[Int] = 
    if (xs.isEmpty) xs 
    else if (p(xs.head)) xs.head :: filter(xs.tail, p) 
    else filter(xs.tail, p) 

    def modN(n: Int)(x: Int) = ((x % n) == 0) 

    val nums = List(1, 2, 3, 4, 5, 6, 7, 8) 

    println(filter(nums, modN(2))) 
    println(filter(nums, modN(3))) 
} 

ソリューションは、部分的に印加関数を使用:

List(2, 4, 6, 8) 
List(3, 6) 

object PartialFunctionTest extends App { 

    def filter(xs: List[Int], p: Int => Boolean): List[Int] = 
    if (xs.isEmpty) xs 
    else if (p(xs.head)) xs.head :: filter(xs.tail, p) 
    else filter(xs.tail, p) 

    def modN(n: Int, x: Int) = ((x % n) == 0) 

    val nums = List(1, 2, 3, 4, 5, 6, 7, 8) 

    println(filter(nums, modN(2,_))) 
    println(filter(nums, modN(3,_))) 
} 

両方が同じ結果を与える

ソリューションカリー化使用します

これらの異なるアプローチは同等ですか?

誰かが私を啓発することができますか、それぞれに最適なユースケースは何ですか?

+2

用語ニックネーム: 'modN(2、_)'は部分的な関数ではありません。これは、部分的に適用された関数*です。類似の名前にもかかわらず、同じものではありません。 http://sandrasi-sw.blogspot.com/2012/03/understanding-scalas-partially-applied.html –

答えて

1

これは主に文体の選択です。あなたの場合、それは実際の違いはありませんが、私は複数のパラメータリストを持つ最初の選択肢がよりよく見えると主張します。

スタイルに関して言えば、方法がカレー化された方法で使用されることを意図している場合は、カリー機能を使用してください。あなたのために設計されていない機能をカレーする必要があるときは、部分的なアプリケーションを使用してください。

ただし、もう一方を使用する必要がある場合もあります。たとえば、複数のパラメータリストを使用すると、ジェネリック型を持っている場合は、これらのタイプは、次の

def ex2[A](input: A)(func: A => A): A = func(input) 
ex2(1)(x => "Hello " + x) //compile error, A is Int from first parameter list 

def ex2a[A](input: A, func: A => A): A = func(input) 
ex2a(1, x => "Hello " + x) //compiles and returns "Hello 1", A is Any because all parameters in the same list are used to determine it's type 

に1つのリストから流れることができる

def ex1(ints: Int*)(strings: String*) 

カップルの例がありますが、両方のリストにVARの引数を使用することができます部分的なアプリケーションを使用する必要があるかもしれません。たとえば、caseクラスのコンストラクタでは、カレーしようとすると、最初のパラメータリストだけがcaseクラスフィールドの一部になります。

case class ex3(a: Int, b:Int) 
ex3(1, 2) == ex3(1,3) //false 

val y: Int => ex3 = ex3(1,_) 

y(2) == y(2) //true 
y(2) == y(3) //false 

case class ex3a(a: Int)(b:Int) 

ex3a(1)(2) == ex3a(1)(3) //true 

val x: Int => ex3a = ex3a(1) 

x(1) == x(1) //true 
x(1) == x(2) //true 
+1

curryingと部分的に適用された関数は同じものではなく、スタイルの選択だけではありません。カリー化された関数は、N個のアリティがN * 1個のアリティ関数を生成する関数であり、これは1つの引数を取る関数を意味し、1個の追加関数を生成する。部分的に適用された関数は、n - m個の引数の数を持つ1つの新しい関数を生成します。 –

関連する問題