Scheme中lambda表达式与函数指针小例

来源:互联网 发布:淘宝卖的玛咖是真是假 编辑:程序博客网 时间:2024/06/06 00:08

SICP/Chapter2/Exercise-2.4

Lambda表达式语法

(lambda kw-formals body)

题目描述

用过程性表示方式重写序对的cons、car、cdr

Scheme代码

(define (cons-24 x y)  (lambda (m) (m x y)))(define (car-24 z)  (z (lambda (p q) p)))

这段代码只有4行,但是逻辑关系并不好理解。
原因在于函数式语言的自顶向下实现方式不符合一般的逻辑习惯。
lambda以类似函数指针的方式提供了通用的接口,实现了动态绑定的功能。


拆解

(按照自底向上的顺序)

1 - procedure_1 = (lambda (p q) p)

Scheme语义:

  • 参数格式:p,q
  • body部分:p,意义是返回p

C实现:

  • 没有更深层次的嵌套,为完整函数体。
  • p,q暂且定义为int类型
    int GetCar(int p,int q){return p;}

2 - (define (car-24 z) (z procedure_1))

Scheme语义:

  • car-24接受一个参数z
  • body部分:因为(z procedure_1), 可判断z为一个函数,其参数为procedure_1
  • 函数z的参数procedure_1为一个函数(见1)

C实现:

  • 首先应该定义一个procedure_1的函数框架(函数实例见1)
    typedef int (*procedure_1)(int,int)
  • 然后根据(z procedure_1)可以写出car-24的参数z的框架,返回值继承自M:
    typedef int (*ARG_Z)(procedure_1)
  • car-24 的参数为z,返回值继承自z。由此可写出car-24的函数框架:
int car-24(ARG_Z z){  return z(procedure_1);//只实现框架,并未绑定实例}
  • 因为procedure_1的实例已经在对car-24的define中,所以此时M已经拥有了一个函数实现,可绑定。car-24因此变成:
int car-24(ARG_Z z){  return z(GetCar);}

3 - procedure_2 = (lambda (m) (m x y))

Scheme语义:

  • 参数格式——接收一个m作为参数
  • 因为lambda中(m)的body部分为(m x y),可知m是一个过程,过程m需要两个参数,x和y。

C实现:

  • 仅有函数框架而没有具体实现,与函数指针相似。具体实现需要将抽象实例化,因此无法确定返回值。
  • 首先定义参数m的框架:
    typedef unknown (*m)(x,y);
  • 然后可写出procedure_2的框架:
    typedef unknown (*procedure_2)(m);
  • 二者返回值未知,取决于绑定类型。procedure_2的返回值继承自m

4 - (define (cons-24 x y) procedure_2)

Scheme语义:

  • 参数格式为x,y
  • body部分为之前分析的procedure_2,因此这个define生成的是一个过程,需要接受x y参数。

C实现:

目前内层函数未被绑定,只能给出框架。唯一确定的是返回值为procedure_2类型,即返回一个函数指针。
typedef procedure_2 (*cons-24)(x,y)

(拆解完毕)

绑定过程

实例

(define test (cons-24 1 2))(car-24 test)

过程

1 - 生成一个名为test的cons-24实例,该实例需要一个过程作为参数

2 - car-24的参数为test,car-24内置的GetCar函数作为其参数test的参数,实现功能为test(GetCar)。

3 - 逻辑理解的难点:

  • 框架和数据在cons-24中给定,却不做任何处理;而是将整个框架抽象成一个类型为过程的变量(或者说抽象成函数指针)。
  • 使用时需要car-24接收此函数指针,传递自身的内置函数给这个函数指针作为参数,形成一个嵌套的环节。
  • car-24仅仅是一个对内置函数封装,为内置函数加上一层壳
  • 两部分间的正常使用需要一个默认的规则:即car-24的参数必须为cons-24类型的过程。这在逻辑上并没有体现。
  • 如果从C的角度来看,函数间的层次关系并不清晰,相互依赖。
  • 但是仅从抽象接口的目的来看,提供了一个相当好的过程接口。若以C函数实现那么需要三层嵌套的定义。由此可见函数式语言与面向过程语言的不同之处。
0 0