Java为函数调度添加功能和间接引用

局部套用 和部分应用 是来源于数学的语言技术(基于 20 世纪数学家 Haskell Curry 和其他人的工作成果)。这两种技术存在于各种类型的语言中,可以单独或同时存在于函数式语言中。局部套用和部分应用使您能够处理函数或方法的参数数量,通常的方法是为一些参数提供一个或多个默认值(称为修正 参数)。所有 Java 下一代语言都包括局部套用和部分应用,但以不同的方式实现它们。在本文中,我将介绍这两种技术的不同之处,并展示它们在 ">Scala、Groovy 和 Clojure 中的实现细节,以及实际应用。

定义和区别

对于业余人士来说,局部套用和部分应用具有相同的效果。使用这两种技术时,都可以创建一个一些参数具有预先提供值的函数版本:

局部套用是将多参数函数转换为一系列单参数函数。它描述了转换过程,而不是转换函数的调用。调用方可以确定应用了
多少参数,从而创建一个参数更少的导出函数。 部分应用将多参数函数转换为一个参数更少的多参数函数,其值为提
前提供的省略参数的值。本技术的名称非常恰当:它将一些参数部分应用到函数,并返回一个具有签名(由剩余参数组成)的函数。

使用局部套用和部分应用,可以提供参数值并返回一个可使用缺少参数调用的函数。但是,对函数应用局部套用会返回链中的下一个函数,而部分应用会将参数值绑到在运算期间提供的值上,生成一个具有更少 元数(参数的数量)的函数。当考虑具有两个以上元数的函数时,这一区别会更加明显。例如,process(x, y, z) 函数的完全套用版本是 process(x)(y)(z),其中 process(x) 和 process(x)(y) 都是接受一个参数的函数。如果只对第一个参数应用了局部套用,那么 process(x) 的返回值将是接受一个参数的函数,因此仅接受一个参数。与此相反,在使用部分应用时,会剩下一个具有更少元数的函数。对 process(x, y, z) 的一个参数使用部分应用会生成接受两个参数的函数:process(y, z)。

这两种技术的结果通常是相同的,但二者的区别也很重要,人们通常会对它们之间的区别产生误解。更复杂的是,Groovy 可以实现部分应用和局部套用,但都将它们称为 currying。而 Scala 具有偏应用函数(partially applied function)和 PartialFunction,尽管它们的名称类似,但它们却是两个不同的概念。

在 Scala 中

Scala 支持局部套用和部分应用,还支持特征(trait),特征可以定义约束函数(constrained function)。

局部套用

在 Scala 中,函数可以将多个参数列表定义为括号组。调用参数数量比其定义数量少的函数时,会返回一个将缺少参数列表作为其参数的函数。请考虑 Scala 文档的示例,如清单 1 所示。

清单 1. Scala 的参数局部套用

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)))

在清单 1 中,filter() 函数递归地应用传递的过滤条件。modN() 函数定义了两个参数列表。在我使用 filter() 调用 modN 时,我传递了一个参数。filter() 函数被作为函数的第二个参数,具有一个 Int 参数和一个 Boolean 返回值,这与我传递的局部套用函数的签名相匹配。

偏应用函数

在 Scala 中还可以部分应用函数,如清单 2 所示。

清单 2. Scala 中部分应用的函数

def price(product : String) : Double = product match { case "apples" => 140 case "oranges" => 223}def withTax(cost: Double, state: String) : Double = state match { case "NY" => cost * 2 case "FL" => cost * 3}val locallyTaxed = withTax(_: Double, "NY")val costOf
Apples = locallyTaxed(price("apples"))assert(Math.round(costOfApples) == 280)

在清单 2 中,我首先创建了一个 price 函数,它返回了产品和价格之间的映射。然后我创建了一个 withTax() 函数,其参数为 cost 和 state。但是,在特殊的源文件中,我知道要专门处理一个国家的税收。我没有对每次调用的额外参数应用局部套用,而是部分应用了 state 参数,并返回一个 state 值固定的函数。locallyTaxed 函数接受一个参数,即 cost。

时间: 2024-09-25 03:24:11

Java为函数调度添加功能和间接引用的相关文章

Java终止函数详解

Java终止函数是什么? 对于对象而言,Java 终止函数履行最后的确认工作.这与Java 结构函数是相反的,Java 结构函数创 建以及初始化了一个Java类实例.当一个对象不在被需要以及这些资源必须被用于其它对象的时候,在一 个类实例或者发行的系统资源,比如说文件描述符或者网络插孔连接上,Java 终止函数可以被用来清除 任务.你不需要证据或者为终止函数返回任何值.遗憾的是当一个类或者接口被载入的时候,目前的Java 语言的介绍中没有任何关于终止函数用于Java类或者接口的解释.让我们进一步

java问题-java实现验证发送邮箱功能(如何给指定邮箱发送验证信息)

问题描述 java实现验证发送邮箱功能(如何给指定邮箱发送验证信息) package org.ouyang.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import java.util.Properties; import javax.mail.Message; import javax.mail.MessagingException; import javax.m

在做一个游戏,想问java有没有类似图层功能

问题描述 在做一个游戏,想问java有没有类似图层功能 目前已知情报 1.好像有个叫JlayerdPane的 2.我的目标是顶层游戏主体用panel话,中层添加视频,底层添加图片 3.问题有两个: 一是用media只能放在frame上面?我想加在panel上,否则添加panel的时候就被覆盖掉了 二是把panel设置成背景透明的,通过 panel.setBackground(null); // 把背景设置为会 panel.setOpaque(false); // 设置为透明 不知道在一的条件下能

javaswing 定位-java swing 实现查找定位功能

问题描述 java swing 实现查找定位功能 我用jeditorpane显示java文件后我想定位到我想要的行,比如第2行怎么做?或者就像eclipse中错误定位一样会给错误的行添加背景颜色?谢谢各位了 解决方案 http://blog.sina.com.cn/s/blog_694448320100m9lu.html

Java案例之随机验证码功能实现

实现的功能比较简单,就是随机产生了四个字符然后输出.效果图如下,下面我会详细说一下实现这个功能用到了那些知识点,并且会把 这些知识点详细的介绍出来.哈哈 ,大神勿喷,对于初学Java的人帮助应该蛮大的.嘿嘿. 案例下载地址:http://download.csdn.net/detail/qq_34337272/9862639(免费,里面还有几个其他小程序) 先上效果图: 源代码: RandomGen.java(实现产生验证码功能的类) package verificationcode; impo

java怎么实现信息提示功能

问题描述 java怎么实现信息提示功能 我想做一个用java语言开发的信息提示功能,就是当数据库某一张表有新数据添加的时候,后台管理员知道有新数据添加,页面的右下角弹出一个小框,慢慢变淡,就像漂流瓶或qq一样 解决方案 这个不就是浏览器和服务器不断进行交互吗? ajax 进行服务器交互来获取数据是否添加,你这个需要不断调用服务器方法才行吧...自己见解 解决方案二: 问题涉及的面挺大的啊. DB--Server--Browser 以下是常规解决这个问题的办法 1.浏览器里面要找一个你所的右下角弹

常用Javascript函数与原型功能收藏(必看篇)_javascript技巧

如下所示: // 重复字符串 String.prototype.repeat = function(n) { return new Array(n+1).join(this); } // 替换全部 String.prototype.replaceAll = function(str1, str2) { return this.replace(new RegExp(str1, "gm"), str2); } // 清除空格 String.prototype.trim = function

再谈java回调函数_java

又遇到了回调函数,这次打算写下来分享一下. 所谓回调函数,或者在面向对象语言里叫回调方法,简单点讲,就是回头在某个时间(事件发生)被调用的函数. 再详细点:就是一个函数A,作为参数,传入了另一个函数B,然后被B在某个时间调用. 这里可以有疑问了,既然是一个函数调用另一个函数,可以在函数体里面调用啊,为什么还要把函数作为参数传到另一个函数里被调用?何况还有一些语言(比如java)不支持把函数作为参数. 对的,确实可以在函数体里调用另一个函数,功能上好像是没差别的,但是这里有一个问题,就是你要调用的

Java Web 实现QQ登录功能一个帐号同一时间只能一个人登录_java

对于一个帐号在同一时间只能一个人登录,可以通过下面的方法实现: 1 .在用户登录时,把用户添加到一个ArrayList中 2 .再次登录时查看ArrayList中有没有该用户,如果ArrayList中已经存在该用户,则阻止其登录 3 .当用户退出时,需要从该ArrayList中删除该用户,这又分为三种情况 ① 使用注销按钮正常退出 ② 点击浏览器关闭按钮或者用Alt+F4退出,可以用JavaScript捕捉该页面关闭事件, 执行一段Java方法删除ArrayList中的用户 ③ 非正常退出,比如