scala中的部分应用函数和偏函数的区别

 我来答
网上充浪
2016-01-10 · TA获得超过341个赞
知道小有建树答主
回答量:145
采纳率:0%
帮助的人:97.9万
展开全部
  • 简单来说,部分应用函数和偏函数是无关的。

  • 前者只是在“已有函数”的基础上,提供部分默认参数,未提供默认参数的地方使用“_”替代,从而创建出一个“函数值”,在使用这个函数值(部分应用函数)的时候,只需提供“_”部分对应的参数即可。

  • 后者则是与函数定义域相关,仅对函数输入参数中的部分取值做出处理的函数就是偏函数。


-------------------------------------------------------------------------------


  这是我的学习笔记,有点多,不过赶脚总结的还可以,你阔以看看:


  • 部分应用函数:

  你还可以使用单个“_”替换整个参数列表。例如可以写成:

  List(1,2,3,4,5).foreach(println(_))

  或者更好的方法是你还可以写成:

  List(1,2,3,4,5).foreach(println _)

  以这种方式使用下划线时,你就正在写一个部分应用函数。部分应用函数是一种表达式,你不需要提供函数需要的所有参数,代之以仅提供部分,或不提供所需参数。如下先定义一个函数,然后创建一个部分应用函数,并保存于变量,然后该变量就可以作为函数使用:

  def sum(a: Int, b: Int, c: Int) = a + b + c

  val a = sum _

  println(a(1,2,3))

  实际发生的事情是这样的:名为a的变量指向一个函数值对象,这个函数值是由scala编译器依照部分应用函数表达式sum _,自动产生的类的一个实例。编译器产生的类有一个apply方法带有3个参数(之所以带3个参数是因为sum _表达式缺少的参数数量为3),然后scala编译器把表达式a(1,2,3)翻译成对函数值的apply方法的调用。你可以使用这种方式把成员函数和本地函数转换为函数值,进而在函数中使用它们。不过,你还可以通过提供某些但不是全部需要的参数表达一个部分应用函数。如下,此变量在使用的时候,可以仅提供一个参数:

  val b = sum(1, _: Int, 3)

  如果你正在写一个省略所有参数的部分应用函数表达式,如println _或sum _,而且在代码的那个地方正需要一个函数,你就可以省略掉下划线(不是需要函数的地方,你这样写,编译器可能会把它当作一个函数调用,因为在scala中,调用无副作用的函数时,默认不加括号)。如下代码就是:

  List(1,2,3,4,5).foreach(println)


  • 偏函数:

  偏函数和部分应用函数是无关的。偏函数是只对函数定义域的一个子集进行定义的函数。scala中用scala.PartialFunction[-T,+S]来表示。偏函数主要用于这样一种场景:对某些值现在还无法给出具体的操作(即需求还不明朗),也有可能存在几种处理方式(视乎具体的需求),我们可以先对需求明确的部分进行定义,以后可以再对定义域进行修改。PartialFunction中可以使用的方法如下:

  isDefinedAt:判断定义域是否包含指定的输入。

  orElse:补充对其他域的定义。

  compose:组合其他函数形成一个新的函数,假设有两个函数f和g,那么表达式f _ compose g _则会形成一个f(g(x))形式的新函数。你可以使用该方法对定义域进行一定的偏移。

  andThen:将两个相关的偏函数串接起来,调用顺序是先调用第一个函数,然后调用第二个,假设有两个函数f和g,那么表达式f _ andThen g _则会形成一个g(f(x))形式的新函数,刚好与compose相反。

SYX0209
2016-01-22 · TA获得超过1742个赞
知道大有可为答主
回答量:2724
采纳率:0%
帮助的人:562万
展开全部
部分应用函数和偏函数是无关的。经常把部分应用函数(Partial Applied Function)和偏函数(Partial Function) 搞混。
总结如下:
部分应用函数(Partial Applied Function)是缺少部分参数的函数,是一个逻辑上概念

偏函数是只对函数定义域的一个子集进行定义的函数。 scala中用scala.PartialFunction[-T, +S]类来表示
比如定义了一个函数:def sum(x: Int)(y: Int) = x + y, 当调用sum的时候,如果不提供所有的参数或某些参数还未知时,比如sum _ , sum(3)(_: Int), sum(_: Int)(3), 这样就生成了所谓的部分应用函数。部分应用函数只是逻辑上的一个表达,scala编译器会用Function1, Function2这些类来表示它.
下面这个变量signal引用了一个偏函数
val signal: PartialFunction[Int, Int] = {
case x if x > 1 => 1
case x if x < -1 => -1
}
这个signal所引用的函数除了0值外,对所有整数都定义了相应的操作。 signal(0) 会抛出异常,因此使用前最好先signal.isDefinedAt(0)判断一下。 偏函数主要用于这样一种场景:对某些值现在还无法给出具体的操作(即需求还不明朗),也有可能存在几种处理方式(视乎具体的需求);我们可以先对需求明确的部分进行定义,比如上述除了0外的所有整数域,然后根据具体情况补充对其他域的定义,比如 :
val composed_signal: PartialFunction[Int,Int] = signal.orElse{
case 0 => 0
}
composed_signal(0) // 返回 0
或者对定义域进行一定的偏移(假如需求做了变更, 1 为无效的点)
val new_signal: Function1[Int, Int] = signal.compose{
case x => x - 1
}
new_signal(1) // throw exception
new_signal(0) // 返回 -1
new_signal(2) // 返回 1
还可以用andThen将两个相关的偏函数串接起来
val another_signal: PartialFunction[Int, Int] = {
case 0 => 0
case x if x > 0 => x - 1
case x if x < 0 => x + 1
}
val then_signal = another_signal andThen signal
这里的then_signal 剔除了-1, 0, 1三个点的定义
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
匿名用户
2016-01-13
展开全部
  部分应用函数和偏函数是无关的。
  前者只是在“已有函数”的基础上,提供部分默认参数,未提供默认参数的地方使用“_”替代,从而创建出一个“函数值”,在使用这个函数值(部分应用函数)的时候,只需提供“_”部分对应的参数即可。
  后者则是与函数定义域相关,仅对函数输入参数中的部分取值做出处理的函数就是偏函数。

  部分应用函数:
  还可以使用单个“_”替换整个参数列表。例如可以写成:
  List(1,2,3,4,5).foreach(println(_))
  或者更好的方法还可以写成:
  List(1,2,3,4,5).foreach(println _)
  以这种方式使用下划线时,正在写一个部分应用函数。部分应用函数是一种表达式,不需要提供函数需要的所有参数,代之以仅提供部分,或不提供所需参数。如下先定义一个函数,然后创建一个部分应用函数,并保存于变量,然后该变量就可以作为函数使用:
  def sum(a: Int, b: Int, c: Int) = a + b + c
  val a = sum _
  println(a(1,2,3))
  实际发生的事情是这样的:名为a的变量指向一个函数值对象,这个函数值是由scala编译器依照部分应用函数表达式sum _,自动产生的类的一个实例。编译器产生的类有一个apply方法带有3个参数(之所以带3个参数是因为sum _表达式缺少的参数数量为3),然后scala编译器把表达式a(1,2,3)翻译成对函数值的apply方法的调用。可以使用这种方式把成员函数和本地函数转换为函数值,进而在函数中使用它们。不过,还可以通过提供某些但不是全部需要的参数表达一个部分应用函数。如下,此变量在使用的时候,可以仅提供一个参数:
  val b = sum(1, _: Int, 3)
  如果正在写一个省略所有参数的部分应用函数表达式,如println _或sum _,而且在代码的那个地方正需要一个函数,你就可以省略掉下划线(不是需要函数的地方,这样写,编译器可能会把它当作一个函数调用,因为在scala中,调用无副作用的函数时,默认不加括号)。如下代码就是:
  List(1,2,3,4,5).foreach(println)

  偏函数:
  偏函数和部分应用函数是无关的。偏函数是只对函数定义域的一个子集进行定义的函数。scala中用scala.PartialFunction[-T,+S]来表示。偏函数主要用于这样一种场景:对某些值现在还无法给出具体的操作(即需求还不明朗),也有可能存在几种处理方式(视乎具体的需求),可以先对需求明确的部分进行定义,以后可以再对定义域进行修改。PartialFunction中可以使用的方法如下:
  isDefinedAt:判断定义域是否包含指定的输入。
  orElse:补充对其他域的定义。
  compose:组合其他函数形成一个新的函数,假设有两个函数f和g,那么表达式f _ compose g _则会形成一个f(g(x))形式的新函数。可以使用该方法对定义域进行一定的偏移。
  andThen:将两个相关的偏函数串接起来,调用顺序是先调用第一个函数,然后调用第二个,假设有两个函数f和g,那么表达式f _ andThen g _则会形成一个g(f(x))形式的新函数,刚好与compose相反。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
槟侨
2016-01-15 · TA获得超过231个赞
知道答主
回答量:193
采纳率:50%
帮助的人:50.3万
展开全部
这是我的学习笔记,有点多,不过赶脚总结的还可以,你阔以看看:

部分应用函数:
  你还可以使用单个“_”替换整个参数列表。例如可以写成:
  List(1,2,3,4,5).foreach(println(_))
  或者更好的方法是你还可以写成:
  List(1,2,3,4,5).foreach(println _)
  以这种方式使用下划线时,你就正在写一个部分应用函数。部分应用函数是一种表达式,你不需要提供函数需要的所有参数,代之以仅提供部分,或不提供所需参数。如下先定义一个函数,然后创建一个部分应用函数,并保存于变量,然后该变量就可以作为函数使用:
  def sum(a: Int, b: Int, c: Int) = a + b + c
  val a = sum _
  println(a(1,2,3))
  实际发生的事情是这样的:名为a的变量指向一个函数值对象,这个函数值是由scala编译器依照部分应用函数表达式sum _,自动产生的类的一个实例。编译器产生的类有一个apply方法带有3个参数(之所以带3个参数是因为sum _表达式缺少的参数数量为3),然后scala编译器把表达式a(1,2,3)翻译成对函数值的apply方法的调用。你可以使用这种方式把成员函数和本地函数转换为函数值,进而在函数中使用它们。不过,你还可以通过提供某些但不是全部需要的参数表达一个部分应用函数。如下,此变量在使用的时候,可以仅提供一个参数:
  val b = sum(1, _: Int, 3)
  如果你正在写一个省略所有参数的部分应用函数表达式,如println _或sum _,而且在代码的那个地方正需要一个函数,你就可以省略掉下划线(不是需要函数的地方,你这样写,编译器可能会把它当作一个函数调用,因为在scala中,调用无副作用的函数时,默认不加括号)。如下代码就是:
  List(1,2,3,4,5).foreach(println)

偏函数:
  偏函数和部分应用函数是无关的。偏函数是只对函数定义域的一个子集进行定义的函数。scala中用scala.PartialFunction[-T,+S]来表示。偏函数主要用于这样一种场景:对某些值现在还无法给出具体的操作(即需求还不明朗),也有可能存在几种处理方式(视乎具体的需求),我们可以先对需求明确的部分进行定义,以后可以再对定义域进行修改。PartialFunction中可以使用的方法如下:
  isDefinedAt:判断定义域是否包含指定的输入。
  orElse:补充对其他域的定义。
  compose:组合其他函数形成一个新的函数,假设有两个函数f和g,那么表达式f _ compose g _则会形成一个f(g(x))形式的新函数。你可以使用该方法对定义域进行一定的偏移。
  andThen:将两个相关的偏函数串接起来,调用顺序是先调用第一个函数,然后调用第二个,假设有两个函数f和g,那么表达式f _ andThen g _则会形成一个g(f(x))形式的新函数,刚好与compose相反。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式