Scheme高阶函数之函数作为返回值暨currying/柯里化

1.4.1currying/柯里化

通常,编程的函数可以有一个参数列表,而λ表达式要求单参数。所以,currying/柯里化——多个参数的函数转化为只有一个参数的多个函数的连续调用,需要函数作为返回值。

有λ表达式,λx. λy. ( 2x+3y)

(define (F x y)(+ ( * 2 x) (* 3 y)));;;等价于下面的表示
(define F
   (lambda ( x y)
     (+ ( * 2 x) (* 3 y))
   )
)

(F 2 3)            → 13

函数F经过currying/柯里化,currying F具有单个参数。

(define curryingF
   (lambda ( x)
      (lambda ( y)
         (+ ( * 2 x) (* 3 y))
      )
   )
);;;或者
(define (curryingF x)
    (lambda ( y)
        (+ ( * 2 x) (* 3 y))
    )
)

函数应用时,必须按照顺序一次次的应用函数。

((curryingF 2) 3)          → 13

其计算过程如下:

((curryingF  2) 3) = (((+ ( * 2 x) (* 3 y)) 2)  3) ;;;展开curryingF

=( (+ ( * 2 2) (* 3 y))  3);;;按照一般的想象,先替换x

=( (+ 4 (* 3 y))  3);;;不管applicative-order evaluation还是标准序,结果一样

=( + 4 (* 3 3)) ;;替换y

=( + 4 9)

=13

匿名函数取名

从((curryingF 2) 3)函数应用中明显地可以看出,(curryingF 2)作为操作符,它表示一个匿名函数,该匿名函数应用于实参3。假设我们希望给(curryingF  2)这个匿名函数一个名字,这里发生了一个有趣的事情:x被定格在2上。

(define (Add_2 y)(( curryingF  2) y))

(Add_2 3) → 13

再比如说计算((curryingF  4) 3) → 17

而且假设也希望给(F 4)的匿名函数一个名字,则x被定格在4上。(define (Add_4 y)(( curryingF  4) y))

显然,yqj2065不愿意为每一个实参常数定义一个有名字的函数。所以一般地,

(define (Add_x y)(( curryingF x)  y));;;为curryingF的匿名函数取名

问题是:

  • 定义了curryingF,应用为((curryingF 2) 3)
  • 定义了(Add_2 y),应用为(Add_2
    3)
  • 定义(Add_x
    y)?x怎么办?

(define  x 2)

(Add_x 3)→ 13

比较另外两个的函数应用,这个(Add_x y)的函数应用需要一个前置语句!这是一种很有趣的函数应用方式——带有数据的行为,据说是另一个闭包(closure)说法的来源。再次应用:

(set! x 3)

(Add_x 3) → 15

((curryingF 3) 3);;;比较

Java中如何currying/柯里化

对于一个方法 public static int add(int x, int y) { return x + y;    }

修改称单参数的函数,需要用到函数接口

package higherOrderFunction;

/**
 *
 * @author yqj2065
 */
public class Currying {
    public static int add(int x, int y) {
        return x + y;
    }

    public static AddInterface add_x(int x) {
//        return new AddInterface(){
//            @Override public int add_y(int y){
//                return x + y;
//            }
//        };
        return (int y) -> x + y;//闭包
    }

    public interface AddInterface {
        int add_y(int y);
    }

    public static void main(String[] a) {
        System.out.println(add(2, 3));
        System.out.println(add_x(2).add_y(3));
    }
}

或者在包外测试:

package test;

import higherOrderFunction.Currying;
import static higherOrderFunction.Currying.add;
import static higherOrderFunction.Currying.add_x;

public class Test {
    public static void main(String[] a) {
        System.out.println(add(2, 3));
        Currying.AddInterface x2=add_x(2);
        System.out.println(x2.add_y(3));
        System.out.println(add_x(2).add_y(3));
    }
}

要习惯:

add_x(2).add_y(3)//Java

((add 2) 3);;;Scheme

时间: 2024-12-28 13:12:58

Scheme高阶函数之函数作为返回值暨currying/柯里化的相关文章

浅析 JavaScript 中的 函数 currying 柯里化

原文:浅析 JavaScript 中的 函数 currying 柯里化 何为Curry化/柯里化? curry化来源与数学家 Haskell Curry的名字 (编程语言 Haskell也是以他的名字命名). 柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果.因此柯里化的过程是逐步传参,逐步缩小函数的适用范围,逐步求解的过程. 柯里化一个求和函数 按照分步求值,我们看一个

javascript中的函数currying(柯里化) 的理解

首先简要说一下什么是curry化 :它是一种通过把多个参数填充到函数体中,实现将函数转换成一个新的经过简化的(使之接受的参数更少)函数技术.(摘自:精通JavaScrtpt图灵计算机科学丛书-21页) //写一个简单点的 function curry(fn/*function*/ , scope/*object?*/){ //取到除必须参数的其他参数,也就是第二个以后的所有参数,做一个缓存 var args = [].slice.call(arguments , 2); console.log(

currying 柯里化,返回函数

var currying = function(fn){var arg = [].slice.call(arguments,1);//获得除了fn之外的参数.return function(){//返回一个函数var newArgs = arg.concat([].slice.call(arguments));//把旧参数和新参数放在一起 .fn.apply(null,newArgs);//使用所有参数}}; var sayHi = function(){var args = [].slice.

Scala 系列(十)—— 函数 & 闭包 & 柯里化

一.函数 1.1 函数与方法 Scala 中函数与方法的区别非常小,如果函数作为某个对象的成员,这样的函数被称为方法,否则就是一个正常的函数. // 定义方法 def multi1(x:Int) = {x * x} // 定义函数 val multi2 = (x: Int) => {x * x} println(multi1(3)) //输出 9 println(multi2(3)) //输出 9 也可以使用 def 定义函数: def multi3 = (x: Int) => {x * x}

【前端学习笔记】函数柯里化(自网易云课堂)

1. 函数柯里化通常是指把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的并且返回一个接受余下的参数而且返回结果的新函数的技术. // 1. 最简单的柯里化 // sum函数接受三个参数,并返回求和结果 var sum = function(a,b,c) { return a+b+c; } // 最简单柯里化的sum函数 var sum_curry = function(a){ return function(b,c){ return a+b+c; } } 2. 更泛化的定义是

柯里化函数之Javascript

柯里化函数之Javascript 定义 根据定义来说,柯里化就是将一个接收"多个"参数的函数拆分成一个或者许多个接收"单一"参数的函数.定义看起来是比较抽象的,下面来举个例子: 代码 1 2 3 4 5 function concat(str1,str2){ return str1 + str2; } concat("forever","px") // "foreverpx" 不难理解,上面的代码中定义了一

【Scala】高阶函数和柯里化

高阶函数 在数学和计算机科学中,高阶函数是至少满足下列一个条件的函数: - 接受一个或多个函数作为输入 - 输出一个函数 在数学中它们也叫做算子(运算符)或泛函.微积分中的导数就是常见的例子,因为它映射一个函数到另一个函数. 高阶函数的例子 假设有一个函数对给定两个数区间中的所有整数求和: def sumInts(a: Int, b: Int): Int = if(a > b) 0 else a + sumInts(a + 1, b) 如果现在要求连续整数的平方和: def square(x:

理解运用JS的闭包、高阶函数、柯里化

一.闭包 1. 闭包的概念 闭包与执行上下文.环境.作用域息息相关 执行上下文 执行上下文是用于跟踪运行时代码求值的一个规范设备,从逻辑上讲,执行上下文是用执行上下文栈(栈.调用栈)来维护的. 代码有几种类型:全局代码.函数代码.eval代码和模块代码:每种代码都是在其执行上下文中求值. 当函数被调用时,就创建了一个新的执行上下文,并被压到栈中 - 此时,它变成一个活动的执行上下文.当函数返回时,此上下文被从栈中弹出 function recursive(flag) { // Exit cond

js高阶函数应用—函数柯里化和反柯里化

在Lambda演算(一套数理逻辑的形式系统,具体我也没深入研究过)中有个小技巧:假如一个函数只能收一个参数,那么这个函数怎么实现加法呢,因为高阶函数是可以当参数传递和返回值的,所以问题就简化为:写一个只有一个参数的函数,而这个函数返回一个带参数的函数,这样就实现了能写两个参数的函数了(具体参见下边代码)--这就是所谓的柯里化(Currying,以逻辑学家Hsakell Curry命名),也可以理解为一种在处理函数过程中的逻辑思维方式. 1 function add(a, b) { 2 retur