在Java语言学习中,通常不太关注求值规则。

(2+4*6)*(3+5+7)这样的组合式的求值规则。通常归结为优先级问题;

if、for等的求值规则通常归结为语义。

函数式编程语言的Scheme,将这些归结为求值规则。依照丘奇的λ演算的函数应用:A、B是λ表达式,则 (A B) 也是λ表达式。表示将实參B带入函数A中。

问题是:实參B带入函数A中时是否须要对实參B求值呢?

applicative-order Vs.normal-order

  • ''evaluate the arguments and then apply'',称为应用顺序求值(applicative-order evaluation)。严格求值 (Strict evaluation)、饥饿求值、
  • ''fully expand and then reduce'',称为normal-order evaluation(不知道为什么翻译成“正则序求值”,而后面3.5.4叫规范求值序)。

    短路计算、惰性求值。

因此。先定义primitive cases:
  • 数的值就是它们自己。

    =Java中的文字。

  • 内置操作符的值。是完毕对应操作的指令序列。
  • 其它名字的值,是环境中关联到该名字的对象。

于是,

表达式求值【1.1.3  Evaluating Combinations】

组合式求值是函数应用求值(的简单情况)

依照应用序求值(applicative-order evaluation),即饥饿求值。

  1. 求子表达式的值(包含求最左的操作符的值、求各实參的值).
  2. 将操作符应用于实參。

函数的求值规则也是如此,只是在阅读代码时,通常我们简单的用取代法理解。

(define (square x)(* x x))

(define (sum-of-square x y)(+ (square x) (square y)))

(define (f a)(sum-of-square (+ a 1) (* a 2)))

那么(f 5)=

(sum-of-square (+ 5 1) (* 5 2))=

(sum-of-square 6 10) =

(+ (square 6) (square 10) =

(+ (* 6 6) (* 10 10) =

(+ 36 100)

1.1.5介绍的取代模型,就是阅读代码的技巧。而实參怎样取代形參。则是參数传递问题,这些东西放在后面介绍。3.2环境模型。事实上Java中的栈-帧(stack frame)模型。

[frame翻译成框架,有点炒蛋]

特殊块(特殊形式)求值

每一种特殊块(特殊形式)都有其自己的求值规则,通常为短路计算/惰性求值。

函数与运行流程

这个问题有意思。在C的教学中。有些人画流程图作为编写代码的“前期”工作。

这一节。SICP说明“可以看清楚函数产生的后果的能力。对于成为程序设计专家是至关重要的”。

什么意思呢?我尽管不喜欢也不推荐学生画流程图,可是通过伪代码或源码,我们可以知道过程/函数的运行流程。甚至我觉得:可以看清楚函数产生的后果的能力。是一个基本能力。

可是,假设你解释器或编译器进行了优化,我须要知道函数的运行流程吗?假设须要,这就不是了解运行流程的问题,而是“深入Java虚拟机”的问题。

而在Scheme中,这一点(知道函数的运行流程)比較重要:由于递归。

假设你对递归不熟悉,事实上,那么不论什么语言中。你都须要学习它的运行流程。假设你对递归比較熟悉,那么你须要知道Scheme中强调这一点的目的:由于想把递归变成循环以提高效率——尾递归。

除了递归之外,“知道函数的运行流程”是显而易见的。

;over

以阶乘为例。递归代码例如以下。

(define (factorial n)

(if (= n 1)

1

(* n(factorial (- n 1)))))

其运行流程。 SICP中给出了一个图x。

可是其解释,我觉得欠考虑。“The substitution model reveals a shape of expansion followed by contraction,indicated by the arrow in figure x”,“递归计算过程”本质上就是“轻率地”觉得自己的较简单的情形是已知的。因而通过“展开和收缩”方式计算,在Java中(我们不考虑懒惰计算(lazy evaluation)时),这一解释是自然的。可是Scheme中,这里“展开和收缩”或“延迟计算”是递归带来的吗?不是。正如练习1.5所说明的,是採用正则序的if带来的。

假设将正则序作为讨论的默认条件(以下的迭代也使用if),尾递归使得“递归函数”依照迭代/循环的方式运行。因此,Scheme就不须要for、while等语法糖。

(练习1.9等)尾递归的一个特点,被替代的函数,作为递归表达式的第一个符号。

(define (factorial n)

  (fact-iter 1 1 n))

(define (fact-iter product counter max-count)

  (if (> counter max-count)

      product

      (fact-iter (* counter product)

                 (+ counter 1)

                 max-count)))

这里。函数fact-iter是一个递归函数,可是计算过程中由几个状态变量控制。We call this aniterative process.In general, an iterative process is one whose state can be summarized by afixed number of state variables, together
with afixed rule that describes how the state variables should be updated as theprocess moves from state to state and an (optional) end test that specifiesconditions under which the process should terminate.

当然,用for将state variables、rule of update和an (optional) end test集中起来。这个语法糖。挺好。

练习1.9 – 1.10

树形递归

Fibonacci number:

(define (fib n)

(cond ((= n0) 0)

((= n1) 1)

(else(+ (fib (- n 1))

(fib (- n 2))))))

这个代码解释了树形递归,可是从效率的角度,存在大量反复计算。怎样设计尾递归代码?

其它,跳过。高阶函数见3.

太多数学题了。

[SICP] 求值规则的更多相关文章

  1. 多项式求值问题(horner规则)——Python实现

    # 多项式求值(Horner规则) # 输入:A[a0,a1,a2...an],x的值 # 输出:给定的x下多项式的值p   # Horner迭代形式实现 1 # 在此修改初值 2 A = [2, 6 ...

  2. [C] 关于表达式求值

    结论是:在一个表达式中,如果两个相邻操作符的执行顺序由它们的优先级决定,如果它们的优先级相同,它们的执行顺序由它们的结合性决定.若出现前述规则描述之外的情形,编译器可以自由决定求值的顺序(只要不违反逗 ...

  3. 左求值表达式,堆栈,调试陷阱与ORM查询语言的设计

    1,表达式的求值顺序与堆栈结构 “表达式” 是程序语言一个很重要的术语,也是大家天天写的程序中很常见的东西,但是表达式的求值顺序一定是从左到右么? C/C++语言中没有明确规定表达式的运算顺序(从左到 ...

  4. 【算法】E.W.Dijkstra算术表达式求值

    算术表达式求值 我们要学习的一个栈的用例同时也是展示泛型的应用的一个经典例子,就是用来计算算术表达式的值,例如 ( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) ) 如果将4乘以5,把3 ...

  5. 从汇编看c++内联函数评估求值

    在c++中,一个inline函数实体,在整个class 声明未被完全看到之前,是不会被评估求值的,也就是说,对于类里面内联的成员函数本身的分析,要等到class的声明完全结束之后才开始.下面试c++源 ...

  6. C/C++ 语言中的表达式求值(原文作者:裘宗燕)

    经常可以在一些讨论组里看到下面的提问:“谁知道下面C语句给n赋什么值?”m = 1; n = m+++m++;最近有位不相识的朋友发email给我,问为什么在某个C++系统里,下面表达式打印出两个4, ...

  7. 中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)

    定义: 中缀表达式: 在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表达式 后缀表达式: 又叫逆波兰表达式 ,不包含括号,运算符放在两个运算对象的后面,所有的计算 ...

  8. 表达式求值(二叉树方法/C++语言描述)(二)

    表达式二叉树节点的数据可能是运算数或运算符,可以使用一个联合体进行存储:同时还需要一个变量来指示存储的是运算数还是运算符,可以采用和栈方法求值中一样的枚举类型TokenType: typedef en ...

  9. 表达式求值(栈方法/C++语言描述)(一)

    一个算数表达式(以下简称为表达式)由运算数.运算符.左括号和右括号组成,定义一个枚举类型TokenType表示为: typedef enum { BEGIN, NUMBER, OPERATOR, LE ...

随机推荐

  1. Gzip压缩优化网站

    网站常使用GZIP压缩算法对网页内容进行压缩,然后传给浏览器,以减小数据传输量,提高响应速度.浏览器接收到GZIP压缩数据后会自动解压并正确显示.GZIP加速常用于解决网速慢的瓶颈. 压缩Filter ...

  2. reactjs simple text editor

    import React, { Component } from 'react' import PubSub from 'pubsub' import GlobalVars from 'globalV ...

  3. C++实现位数组

    当我们遇到大量整数排序时候为了节省内存空间我们能够考虑使用bit数组来实现,缺点是其仅仅适用于正整数. 思想: 在32位系统一个int类型占4个字节,按位来计算一个int类型能够记录32个数.因此,採 ...

  4. hdoj--1272--小希的迷宫(并查集)

    小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  5. Oracle 11G R2 RAC中的scan ip 的用途和基本原理

    Oracle 11G R2 RAC增加了scan ip功能,在11.2之前,client链接数据库的时候要用vip,假如你的cluster有4个节点,那么客户端的tnsnames.ora中就对应有四个 ...

  6. Kylin基础教程(一)

    一.Kylin介绍 1.1 现状 Hadoop于2006年初步实现,改变了企业级的大数据存储(基于HDFS)和批处理(主要基于MR)问题,10几年过去了,数据量随着互联网的发展井喷式增长,如何高速.低 ...

  7. 从零开始学习SVG

    1 什么是SVG? MDN中的定义是:SVG即可缩放矢量图形(Scalable Vector Graphics,SVG),是一种用来描述二维矢量图形的 XML 标记语言. 简单地说,SVG 面向图形, ...

  8. P2740 [USACO4.2]草地排水Drainage Ditches

    题目背景 在农夫约翰的农场上,每逢下雨,贝茜最喜欢的三叶草地就积聚了一潭水.这意味着草地被水淹没了,并且小草要继续生长还要花相当长一段时间.因此,农夫约翰修建了一套排水系统来使贝茜的草地免除被大水淹没 ...

  9. Spring meven 配置

    使用maven的仓库化管理,可以更方便有效的控制文件. 在官网下载maven. 官网的地址:http://maven.apache.org/download.cgi  请选择最新的版本下载, 这里我用 ...

  10. 快速搭建golden gate环境

    准备操作系统用户和文件系统 准备安装和运行用户(操作系统用户) 建议使用Oracle用户 也可使用新建用户,但需做以下配置 该用户必须加入到oinstall组 该用户使用与oracle相同的profi ...