JSRUN 用代码说话

定义函数

编辑教程

定义函数

在前面的章节中,我已经讲解了:

如何安装MIT-Scheme;
Scheme解释器是如何对S-表达式求值;
基本的表操作;

在本章中,我会讲解如何自定义函数。由于Sheme是函数式编程语言,你需要通过编写小型函数来构造程序。

因此,明白如何构造并组合这些函数对掌握Scheme尤为关键。在前端定义函数非常不便,因此我们通常需要在文本编辑器中编辑好代码,并在解释器中加载它们。

如何定义简单函数并加载它们

你可以使用define来将一个符号与一个值绑定。你可以通过这个操作符定义例如数、字符、表、函数等任何类型的全局参数。

让我们使用任意一款编辑器(记事本亦可)来编辑代码片段1中展示的代码,并将它们存储为hello.scm,放置在类似于C:\doc\scheme\的文件夹下。如果可以的话,把这些文件放在你在第一章定义的MIT-Scheme默认文件夹下。

; Hello world as a variable
(define vhello "Hello world")     ;1

; Hello world as a function
(define fhello (lambda ()         ;2
         "Hello world"))

接下来,向Scheme解释器输入下面的命令:

(cd "C:\\doc\\scheme")
;Value 14: #[pathname 14 "c:\\doc\\scheme\\"]

(load "hello.scm")
;Loading "hello.scm" -- done
;Value: fhello

通过这些命令,hello.scm就被加载到解释器中。如果你的当前目录被设定在了脚本所在目录,那么你就不需要再输入第一行的命令了。然后,向解释器输入下面的命令:

vhello
;Value 15: "Hello world"

fhello
;Value 16: #[compound-procedure 16 fhello]

(fhello)
;Value 17: "Hello world"

操作符define用于声明变量,它接受两个参数。define运算符会使用第一个参数作为全局参数,并将其与第二个参数绑定起来。因此,代码片段1的第1行中,我们声明了一个全局参数vhello,并将其与"Hello,World"绑定起来。

紧接着,在第2行声明了一个返回“Hello World”的过程。

特殊形式lambda用于定义过程。lambda需要至少一个的参数,第一个参数是由定义的过程所需的参数组成的表。因为本例fhello没有参数,所以参数表是空表。

在解释器中输入vhello,解释器返回“Hello,World”。如果你在解释器中输入fhello,它也会返回像下面这样的值:#[compound-procedure 16 fhello],这说明了Scheme解释器把过程和常规数据类型用同样的方式对待。正如我们在前面章节中讲解的那样,Scheme解释器通过内存空间中的数据地址操作所有的数据,因此,所有存在于内存空间中的对象都以同样的方式处理。

如果把fhello当过程对待,你应该用括号括住这些符号,比如(fhello)。

然后解释器会按照第二章讲述的规则那样对它求值,并返回“Hello World”。

定义有参数的函数

可以通过在lambda后放一个参数表来定义有参数的函数。将代码片段2保存为farg.scm并放在同hello.scm一致的目录。

; hello with name
(define hello
  (lambda (name)
    (string-append "Hello " name "!")))

; sum of three numbers
(define sum3
  (lambda (a b c)
    (+ a b c)))

保存文件,并在解释器中载入此文件,然后调用我们定义的函数。

(load "farg.scm")
;Loading "farg.scm" -- done
;Value: sum3

(hello "Lucy")
;Value 20: "Hello Lucy!"

(sum3 10 20 30)
;Value: 60
Hello

函数hello有一个参数(name),并会把“Hello”、name的值、和"!"连结在一起并返回。

预定义函数string-append可以接受任意多个数的参数,并返回将这些参数连结在一起后的字符串。

sum3:此函数有三个参数并返回这三个参数的和。

一种函数定义的短形式

用lambda定义函数是一种规范的方法,但你也可以使用类似于代码片段3中展示的短形式。

; hello with name
(define (hello name)
  (string-append "Hello " name "!"))

; sum of three numbers
(define (sum3 a b c)
  (+ a b c))

在这种形式中,函数按照它们被调用的形式被定义。代码片段2和代码片段3都是相同的。有些人不喜欢这种短形式的函数定义,但是我在教程中使用这种形式,因为它可以使代码更短小。

练习1

按照下面的要求编写函数。这些都非常简单但实用。

将参数加1的函数。
将参数减1的函数。

练习2

让我们按照下面的步骤编写一个用于计算飞行距离的函数。

编写一个将角的单位由度转换为弧度的函数。180度即π弧度。π可以通过下面的式子定义: (define pi (* 4 (atan 1.0)))。|

编写一个用于计算按照一个常量速度(水平分速度)运动的物体,t秒内的位移的函数。

编写一个用于计算物体落地前的飞行时间的函数,参数是垂直分速度。忽略空气阻力并取重力加速度g为9.8m/s^2。提示:设落地时瞬时竖直分速度为-Vy,有如下关系。2 Vy = g t 
此处t为落地时的时间。

使用问题1-3中定义的函数编写一个用于计算一个以初速度v和角度theta掷出的小球的飞行距离。

计算一个初速度为40m/s、与水平方向呈30°的小球飞行距离。这个差不多就是一个臂力强劲的职业棒球手的投掷距离。

提示:首先,将角度的单位转换为弧度(假定转换后的角度为theta1)。初始水平、竖直分速度分别表示为:vcos(theta1)和vsin(theta1)。落地时间可以通过问题3中定义的函数计算。由于水平分速度不会改变, 因此可以利用问题2中的函数计算距离。

关于编辑器

这里,我会推荐一些能非常方便地编辑Scheme代码的编辑器。

Emacs

Emacs21的Windows版本可以从http://ftp.gnu.org/gnu/emacs/windows/找到,下载emacs-21.3-bin-i386.tar.gz并解压它。

你会在bin文件夹下发现一个叫runemacs.exe的可执行文件。双击这个程序来启动编辑器。

尽管键位布局和Windows的标准相当不同,但是因为有一个菜单栏和鼠标控制器而显得相当用户友好。

你也可以通过编辑名为.emacs的配置文件来实现自定义配置。编辑器提供了一种Scheme模式,此模式下能够编辑器能识别预定义单词,以及通过Ctri-i或TAB键来自动缩进。

除此之外,当一个输入一个右括号后,编辑器会自动显示与之匹配的左括号。

在Windows系统中,emacs不能够与MIT-Scheme进行交互。你只能手动地储存并加载源代码。

但从另一个方面来说,在UNIX和Linux系统下,emacs可以同MIT-Scheme进行交互式地调用,因此编辑代码也可以在交互中完成。

Edwin

Edwin是MIT-Scheme配备的编辑器。它有点像emacs18。但它没有菜单栏和鼠标控制,因此显得不太用户友好。

只有少数人用这个编辑器,因此网络上可用的说明也很少。虽然如此,你可以使用这个编辑器进行交互式的代码编辑。

我在Windows上使用这个编辑器编辑Scheme代码。

如何使用Edwin

双击Edwin的图标以启动Edwin。当Edwin启动后,一个叫Scheme的默认缓冲区出现在屏幕上,它对应于emacs中的scratch缓冲区。

你可以将scheme用作解释器前端。按下Ctrl-X Ctrl-e 就可以对S-表达式进行求值。

文件的打开与关闭,编辑器的关闭。按下Ctrl-X Ctrl-F来打开一个文件。如果你指定的文件并不存在,则会创建一个新文件。初始路径被设置为了‘C:\’,你在打开文件前应该修改这个路径。按下Ctrl-X Ctrl-S来保存文件,而按下Ctrl-x Ctrl-w则是文件另存为。退出编辑器请按下Ctrl-x Ctrl-c。

缩进。按下Ctrl-i或者TAB可以缩进。

剪切,复制和粘贴。我们无法使用鼠标,因此复制(剪切)、粘贴起来就会显得不太方便。但你可以像下面这样做:

首先,通过方向键将光标移动至待选区域的开头,然后按下Ctrl-SPACE。
然后移动至结束位置按下Ctrl-w来剪切区域,按下Alt-w来复制区域。
最后,移动至你想要复制的区域,按下Ctrl-y。
求值S-表达式
按键Alt-z用于求值以define开头的S-表达式。
按键Alt-:用于在一个小型的缓冲区中求值S-表达式。这个通常用在测试用Alt-z求值的函数。
按键Ctrl-x Ctrl-e用于求值整个scheme缓冲区中的S-表达式。
JSRUN闪电教程系统是国内最先开创的教程维护系统, 所有工程师都可以参与共同维护的闪电教程,让知识的积累变得统一完整、自成体系。 大家可以一起参与进共编,让零散的知识点帮助更多的人。
X
支付宝
9.99
无法付款,请点击这里
金额: 0
备注:
转账时请填写正确的金额和备注信息,到账由人工处理,可能需要较长时间
如有疑问请联系QQ:565830900
正在生成二维码, 此过程可能需要15秒钟