Scala中为何该柯里化函数定义无法正常编译?
Let's break down your problems step by step—I've run into similar confusion when learning Scala currying too!
First: Why won't your sumOf definition compile?
Surprisingly, the code you wrote is actually valid Scala syntax and should compile just fine in both Scala 2 and Scala 3—assuming there are no typos or formatting issues. If you're seeing a compile error, here are the most likely culprits:
- Mismatched parentheses: Double-check that all curly braces and parentheses are properly closed, especially in the recursive call.
- Incorrect argument passing in recursion: If you accidentally wrote
sumOf(f, a + 1, b)instead ofsumOf(f)(a + 1, b), that'll throw an error—sumOfexpects two separate parameter lists, not one combined list. - REPL formatting issues: If you're testing this in the Scala REPL, multi-line function definitions can sometimes cause problems if you don't use the
:pastemode. Try pasting the entire function at once using:paste(then press Ctrl+D to execute).
Second: Why isn't sumOfDouble working?
This is where the currying nuance trips people up! Let's clarify:
- Your
sumOfis a curried function, but the second parameter list has two arguments grouped together (a: Int, b: Int). When you pass the first argumentx => x * 2tosumOf, you get back a function of type(Int, Int) => Int—a single-argument function that takes two Ints in one set of parentheses. - That means
sumOfDoubleis not a curried function. To call it correctly, you need to pass both Ints in the same parentheses:
If you tried calling it likesumOfDouble(1, 5) // This works! Returns 2 + 4 + 6 + 8 + 10 = 30sumOfDouble(1)(5), that'll fail becausesumOfDoubledoesn't expect a second parameter list.
Fix if you want curried behavior for sumOfDouble:
If you want sumOfDouble to be curried (so you can call it as sumOfDouble(1)(5)), just split the second parameter list in sumOf into two separate lists:
def sumOf(f: Int => Int)(a: Int)(b: Int): Int = { if (a > b) 0 else f(a) + sumOf(f)(a + 1)(b) }
Now sumOf(x => x * 2) returns a curried function of type Int => Int => Int, and sumOfDouble(1)(5) will work exactly as you expect.
A quick reminder about the currying equivalence you learned: def f(arg1)(arg2) = E is indeed equivalent to def f = (arg1 => (arg2 => E)), but this only applies when each parameter list has one argument. If a parameter list has multiple arguments (like (a: Int, b: Int)), it's equivalent to a function that takes a tuple: def f = (arg1 => ((a, b) => E)).
内容的提问来源于stack exchange,提问作者Wan ChengCheng

