序章:如何编写程序
1.序幕
本书使用的是编辑器DrRacket,使用的是其中的选择语言——教学语言——程序设计初级,选择之后重新点击运行即可。
该编辑器的下半屏幕是交互区,上半屏幕是定义区,编辑文件以后,可以保存以后,点击运行,从而在下方的交互区看到输出结果。比如,在定义区输入:
(+ 1 1)
你会看到底部交互区呈现的结果是:
2
这样,你就可以输入下面这几个表达式,看看交互区会得到什么结果:
(+ 2 2)
(* 3 3)
(- 4 2)
(/ 6 2)
结果应该是4 9 2 3
,就好像你期待的一样。下面,是不得不进行的术语定义时间。
术语
- 程序由表达式构成。你可能有看到一些数学上的表达式,但是,一个表达式可以是一个数字或者其他被括号
()
包围的东西——成对的括号及其内容物会被DrRacket用阴影覆盖。 - 当你点击运行的时候,编辑器会对定义区的表达式求值,病将其返回值输出到交互区的顶部,然后等待你的下一条命令;得到你的命令(输入的表达式)后,其会对表达式求值,返回结果,再次进入等待状态。看下面这几条交互区的实例:
> (+ 2 2)
4
> (sqr 3)
9
> (sin 0)
0
> (cos pi)
#i-1.0
- 最后一个表达式里面添加了前缀
#i
,表示这是一个不精确的数字(inexact number)。
介绍了足够的术语后,下面继续。我们可以发现,这里的DrRacket
可以加总两个以上的数字,还可以嵌套!
> > (+ 2 (+ 2 3))
7
> (+ 2 3 2)
7
第一个是所谓的嵌套算数,正如在学校里面学到的。而第二个则是火箭算数,且它看起来是自然的,如果你总是将操作符和操作数用括号包围起来的话。在教学语言——HtDP——BSL中,你可以任意使用嵌套表达式,其中表达式的左端是操作符,右端是操作数,嵌套层级则随你使用:
> (+ 2 (+ (* 3 3) 4))
15
> (+ 2 (+ (* 3 (/ 12 4)) 4))
15
> (+ (* 5 5) (+ (* 3 (/ 12 4)) 4))
38
但是,要注意:括号必须是成对的,既不能多,也不能少。比如下面这个表达式,在作业中是没有问题的:
> (+ (1) 2)
function call: expected a function after the open parenthesis, but found a number
结果会报错……
P.S. 你可以将光标移动到操作符的附近,按下<kbd>F1</kbd>,然后你就可以获取所需要的帮助文档了。
如果你不知道一个操作符有什么用,就在交互区输出示例,然后查看结果。这也是之后阅读代码所需要的技能。
2. 数字之外的内容
如果程序只能处理数字,会跟mathematics一样无聊(虽然看这个的人可能已经在使用或者之后需要使用它)。但幸运的是,这里可以处理数字以外的东西,比如:文本、布尔值、图片等等。
下面是文本处理的示例程序:
(string-append "hello" "world")
(string-append "hello" " " "world")
(string-append "hel" "lo world")
当你输入病运行上述代码的时候,下面的交互区会显示:
"helloworld"
"hello world"
"hello world"
为了理解发生了什么,你需要知道:在BSL中,文本是用双引号包围起来的字符。当DrRacket
对字符串求值的时候,会返回字符本身。所以HelloWorld
在这里特别简单,只需要输入"Hello world!"
即可。
而string-append
本身则是操作符之一,作用是将多个字符串从左到右顺序连接起来,只是连接了字面值,而没有加入换行符之类的内容。如果想知道更多与字符串相关的操作符,可以按下<kbd>F1</kbd>,然后搜索Begin
,点击Beginning Student
。
如果你已经做了上面所述的工作,你应该能看到这些内置(或者说预定义)的,与字符串相关的操作符了。然后,就可进行相关的操作,如下:
> (+ (string-length "Hello world!") 20)
32
然后,DrRacket会对表达式进行求值,打印结果。这意味着,你的输入可以不只是数字,输入和输出的类型可以不同,比如下面展示的类型转换函数:
> (number->string 42)
"42"
> (string->number "42")
42
恩……如果你希望能得到四二
之类的答案,可能要大失所望了——这并不是一个字符串操作符能做到的事情……
而这第二个操作符会使人产生疑惑:如果输入的不是一个数字字符串,二是其他东西,会怎么样呢:
> (string->number "Hello")
#false
得到了一个布尔值的错误。在DrRacket中,布尔值由两个值表示:#true/#false
。自然,其也能够支持逻辑运算符and
、or
和not
。虽然把数字转换为布尔值不可行,但是可以将两个以上的数字“转换”为布尔值:
(> 10 9)
(< -1 0)
(= 42 42)
(= 3 4)
; 返回值
#true
#true
#true
#false
你可以开始尝试下面这几个表达式(>= 10 10)
、(<= 3 4)
和(string=? "design" "tkinter")
。虽然最后一个长得有点奇怪,但是要相信自己:你可以的~
在进入真正的编程之前,会展示一种额外的数据:图片。如果需要将图片插入交互区,你只需要将下面这张图:
image.png插入交互区,就可以看到DrRacket
返回图片本身了。
P.S. 你可以使用插入菜单,并点击插入图片来完成这个壮举。
这里,BSL可以理解图片,如同理解数字和字符串一般。除此之外,该语言还支持一个包,。这些包可以像扩展你的词典一般,为你的程序词典添加新的内置函数。我们在教学中会使用这些包,并称其为教学包。
现在,我们可以使用包2htdp/image
,其支持对图片的计算:
输入如图所示的程序以后,你可以得到一个返回值:1176,因为这个图的面积为28 X 42 像素。当然,你还可以使用一些函数来进行画图,如circle
函数和rectangle
函数:
(circle 10 "solid" "red")
(rectangle 30 20 "outline" "blue")
除此之外,DrRacket
还支持图像之间的组合,如下:
(overlay (circle 5 "solid" "red")
(rectangle 20 20 "solid" "blue"))
将两张图片的构造函数换个顺序,你会发现结果有所不同:
(overlay (rectangle 20 20 "solid" "blue")
(circle 5 "solid" "red"))
在这里,你可以将overlay
视作string-append
,其像后者一样,操作数的先后会影响结果,与此同时,你还可以对其使用前面的求宽度操作符:
(image-width (square 10 "solid" "red"))
(image-width
(overlay (rectangle 20 20 "solid" "blue")
(circle 5 "solid" "red")))
; 结果
10
20
除了这些,你还应该知道另外两个操作符:empty-scene
和place-image
。前者创建一个场景,属于特殊的矩形;后者则将一张图放置到这样的场景中。
(place-image (circle 5 "solid" "green")
50 80
(empty-scene 100 100))
你看,结果如下:
empty-scene实例.png其中,这幅场景的原点(0, 0)位于左上角,y值向下递增;x值向左递增。所以你看到的坐标(50, 80)是在那里。
现在总结一下这节的内容:
我们不再只是处理数字,而且可以处理字符串,布尔值以及图片。计算现在依旧意味着:给表达式传入特定的值,如字符串,数字,布尔值或者图片。但是,你下次就可以让这个火箭“飞起来”了。
网友评论