我正在准备关于Scala和函数式编程的演示文稿,我不确定两个概念。
我在演示期间使用了之前介绍的功能:
def safe_division(x: Int, y: Int) : Option[Double] = {
if(y != 0)
Some(x / y.toDouble)
else
None
}
我创建了一个咖喱版(如果我错了请纠正我!):
val curried_safe_division: (Int) => (Int) => Option[Double] = {
(x) =>
(y) =>
if(y != 0)
Some(x / y.toDouble)
else
None
}
所以我不确定的第一部分是“curried_safe_division被称为咖喱?”
然后我介绍一些代码来说明currying函数如何让程序员有效地重用函数:
val divideSix = curried_safe_division(6)
divideSix(3)
// prints: Some(2.0)
divideSix(6)
// prints: Some(1.0)
我是否正确地说divideSix
是封闭的?
curried_safe_division
也不是关闭吗?
我正在使用这个定义:
https://softwareengineering.stackexchange.com/a/40708 一个可以存储为变量的函数(称为“第一类函数”),它具有访问其创建范围本地的其他变量的特殊能力。
我在线阅读多个资源,维基百科页面和此stackoverflow问题:What is a 'Closure'?但它仍然不是 超级 清除
答案 0 :(得分:4)
值curried_safe_division
是一个函数。这与safe_division
不同,后者是一种方法。
此外,curried_safe_division
是 curried功能。当您使用safe_division
并将其转换为函数时,您通常会得到(Int, Int) => Option[Double]
。通过将其更改为Int => Int => Option[Double]
,您 curried 该功能。
函数divideSix
不是闭包。它是一个简单的函数,它接受一个整数并返回一个整数。然而,什么是闭包是curried_safe_division
中的内部函数:
val curried_safe_division: (Int) => (Int) => Option[Double] =
(x) =>
// function below is a closure
(y) =>
if(y != 0)
Some(x / y.toDouble)
else
None
// end of closure
}
您可以清楚地看到它取决于x
,但不会将其作为自己的参数;相反,它使用了外部范围的x
。它"关闭x"。当您说val divideSix = curried_safe_division(6)
时,您正在接受该闭包,为其提供六个作为参数x的值,并将其分配给divideSix
。但是divideSix
本身并不是一个闭包。它并不关闭任何东西。它只需要一个整数参数并将其除以6。
我已经看到有些人倾向于将结果函数值(在我们的例子中为divideSix
)引用为" closure"因为它是部分应用某个函数(在我们的例子中为curried_safe_division
)而产生的函数,并且导致了一个函数(在我们的例子中的注释之间标记),这是一个实际的闭包。我很好。只要您了解机制,就可以很容易地找到术语。
答案 1 :(得分:1)
Currying实际上比你的例子简单得多。您不需要同时引入方法/功能区分。
// a curried safe_division method
def safe_division(x: Int)(y: Int) : Option[Double] =
if (y != 0) Some(x / y.toDouble)
else None
您可以在此处介绍eta expansion,safe_division(2)_
,它会创建Int => Option[Double]
类型的函数。