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

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函数实现那么需要三层嵌套的定义。由此可见函数式语言与面向过程语言的不同之处。
时间: 2024-10-08 09:30:19

Scheme中lambda表达式与函数指针小例的相关文章

【C++】C++中的lambda表达式和函数对象

目录结构: contents structure [-] lambda表达式 lambda c++14新特性 lambda捕捉表达式 泛型lambda表达式 函数对象 函数适配器 绑定器(binder) std::mem_fn()适配器 lambda表达式是C++11中引入的一项新技术,利用lambda表达式可以编写内嵌的匿名函数,用以替换独立函数或者函数对象,并且使代码更可读.但是从本质上来讲,lambda表达式只是一种语法糖,因为所有其能完成的工作都可以用其它稍微复杂的代码来实现.但是它简便

java 8 中lambda表达式学习

转自 http://blog.csdn.net/renfufei/article/details/24600507 http://www.jdon.com/idea/java/10-example-of-lambda-expressions-in-java8.html Lambda表达式的语法基本语法:(parameters) -> expression或(parameters) ->{ statements; } 下面是Java lambda表达式的简单例子: // 1. 不需要参数,返回值

python中lambda表达式应用

对于简单的函数,也存在一种简便的表示方式,即:lambda表达式 #普通函数1 def func(a): 2 return a+1 3 print 'test1_func0:',func(1000)4#lambda表达式 5 func0 = lambda a:a+1 6 print 'test2_func0:',func0(1000) 上面这种方法,都实现了将1000+1的结果打印出来这个功能,但是用下面 lambda存在意义就是对简单函数的简洁表示. 说道lambda,这里再赠送一些可以给la

STL---对STL中的各类常用函数的小总结

STL = Standard Template Library,标准模板库,惠普实验室开发的一系列软件的统称.它是由Alexander Stepanov.Meng Lee和David R Musser在惠普实验室工作时所开发出来的.这可能是一个历史上最令人兴奋的工具的最无聊的术语.从根本上说,STL是一些"容器"的集合,这些"容器"有list,vector,set,map等,STL也是算法和其他一些组件的集合.这里的"容器"和算法的集合指的是世界

Java中Lambda表达式的使用

简介(译者注:虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能.本人建议不要乱用,因为这就和某些很高级的黑客写的代码一样,简洁,难懂,难以调试,维护人员想骂娘.)Lambda表达式是Java SE 8中一个重要的新特性.lambda表达式允许你通过表达式来代替功能接口. lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块

[二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口

函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type used to indicate that an interface * type declaration is intended to be a <i>functional interface</i> as * defined by the Java Language Specificat

Java中Lambda表达式的使用(转)

https://www.cnblogs.com/franson-2016/p/5593080.html 简介(译者注:虽然看着很先进,其实Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能.本人建议不要乱用,因为这就和某些很高级的黑客写的代码一样,简洁,难懂,难以调试,维护人员想骂娘.)Lambda表达式是Java SE 8中一个重要的新特性.lambda表达式允许你通过表达式来代替功能接口. lambda表达式

【示例】C语言中利用数组存放函数指针

C语言中利用数组存放函数指针,增加函数使用的灵活性.使用时只需提供数组索引,即可调用不同函数. 预备知识: 1.指向函数的指针 一个函数在编译时被分配一个入口地址,这个地址就被称为函数的指针. 例如: int max(int,int); // 声明函数,比较两数大小 int (*p)(); //声明指向函数的指针变量 p=max; //将函数max的入口地址赋给指针变量p int c=(*p)(a,b); //调用函数 2.函数指针作为函数参数 该例子中每次给process函数不同实参(函数名)

Java8 Collections.sort()及Arrays.sort()中Lambda表达式及增强版Comparator的使用

摘要:本文主要介绍Java8 中Arrays.sort()及Collections.sort()中Lambda表达式及增强版Comparator的使用. 不废话直接上代码 import com.google.common.collect.Lists; import org.junit.Assert; import org.junit.Test; import java.util.Arrays; import java.util.Collections; import java.util.Comp