Scala - 柯里化和默认参数
我有一个带有两个参数列表的函数,我试图部分应用并与柯里化一起使用。第二个参数列表包含所有具有默认值(但不是隐式的)的参数。像这样的事情:
def test(a: Int)(b: Int = 2, c: Int = 3) { println(a + ", " + b + ", " + c); }
现在,以下都很好:
test(1)(2, 3);
test(1)(2);
test(1)(c=3);
test(1)();
现在如果我定义:
def partial = test(1) _;
那么可以完成以下操作:
partial(2, 3);
有人可以解释为什么我不能省略“部分”中的某些/所有参数,如下所示:
partial(2);
partial(c=3);
partial();
不应该写“部分” ” 的行为本质上与“test(1)”相同?有人可以帮我想出一种方法来实现这一目标吗?
请帮忙,我很绝望!
编辑 - 由于我无法在 24 小时内回答我自己的问题,我将在这里发布我自己的答案:
这是迄今为止我自己能做的最好的事情:
class Test2(val a: Int) {
def apply(b: Int = 2, c: Int = 3) { println(a + ", " + b + ", " + c); }
}
def test2(a: Int) = new Test2(a);
def partial2 = test2(1); // Note no underscore
test2(1)(2, 3);
test2(1)(2);
test2(1)(c=3);
test2(1)();
partial2(2, 3)
partial2(2);
partial2(c=3);
partial2();
这样就可以了......
I have a function with two parameter lists that I am trying to partially apply and use with currying. The second parameter list contains arguments that all have default values (but not implicit). Something like this:
def test(a: Int)(b: Int = 2, c: Int = 3) { println(a + ", " + b + ", " + c); }
Now, the following is all fine:
test(1)(2, 3);
test(1)(2);
test(1)(c=3);
test(1)();
Now if I define:
def partial = test(1) _;
Then the following can be done:
partial(2, 3);
Can someone explain why I can't omit some/all arguments in 'partial' as follows:
partial(2);
partial(c=3);
partial();
Shouldn't writing "partial" behave essentially the same way as "test(1)"? Can someone please help me figure out a way to achieve this?
Please help, I'm desperate!
EDIT - Since I can't answer my own question within 24 hours, I'll post my own answer here:
This is the best I could do myself so far:
class Test2(val a: Int) {
def apply(b: Int = 2, c: Int = 3) { println(a + ", " + b + ", " + c); }
}
def test2(a: Int) = new Test2(a);
def partial2 = test2(1); // Note no underscore
test2(1)(2, 3);
test2(1)(2);
test2(1)(c=3);
test2(1)();
partial2(2, 3)
partial2(2);
partial2(c=3);
partial2();
This way it works...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
类型推断引擎为
partial
提供接下来的类型;即 eta 扩展test(1) _
。例如,您可以在 REPL 中看到partial
的类型为(Int, Int) => Unit
,而test
的类型为(a: Int)(b: Int,c: Int)Unit
。 eta 扩展的结果是一个 Function 对象,它不带有任何参数名称(因为可以使用匿名参数定义 Function)。要解决此问题,您必须按如下方式定义
partial
:也许您需要分解出
test
和partial
都可以使用的默认值接触他们以确保他们保持平等。但我不知道有什么技巧可以避免重复参数名称而不引入额外的开销,例如创建新对象等。The type inference engine gives to
partial
the type of what comes next; i.e., the eta expansiontest(1) _
. You can see e.g. in the REPL thatpartial
has type(Int, Int) => Unit
, whereastest
has type(a: Int)(b: Int,c: Int)Unit
. The result of the eta expansion is aFunction
object, which does not carry any argument names with it (as it is possible to defineFunction
with anonymous parameters).To fix this, you have to define
partial
as follows:Maybe you'll want to factor out the default values where both
test
andpartial
can reach them to make sure they stay equal. But I know of no trick to avoid repeating the names of the parameters without introducing extra overhead like creating of new objects, etc.这是迄今为止我自己能做的最好的事情:
这样就可以了......
This is the best I could do myself so far:
This way it works...
根据您的评论,这里有一种更紧凑的编写方式:
这比您的提案更紧凑,但效率较低,因为对内部
apply
的任何调用都将通过反射进行,如下所示与结构类型。实际上,test
的返回类型是一个结构类型:Following up on your comment, here's a more compact way to write it:
This is a bit more compact than your proposal, but is less efficient, as any call to the inner
apply
will occur through reflection, as with structural types. Actually, the return type oftest
is a structural type: