翻译—伤寒明理论 包含全部章节
Chapter 1
Introducing Karel the Robot
In the 1970s, a Stanford graduate student named Rich Pattis decided that it would be easier to teach the
fundamentals of programming if students could somehow learn the basic ideas in a simple environment
free from the complexities that characterize most programming languages. Drawing inspiration from the
success of Seymour Papert’s LOGO project at MIT, Rich designed an introductory programming
environment in which students teach a robot to solve simple problems. That robot was named Karel, after
the Czech playwright KarelCapek, whose 1923 play R.U.R. (Rossum’s Universal Robots) gave the word
robot to the English language.
第一章:
机器人卡雷尔简介
在二十世纪七十年代,一位名字叫 Rich Pattis 的斯坦福研究生觉得,在编程基础的教学中,如果
学生可以在某种简单的环境中,摆脱大多数编程语言复杂的特性,学习基本的编程思想,可以取
得更好的效果。麻省理工 Seymour Papert’s LOGO 计划的成功,启发了灵感,Rich 设计了一个入
门编程环境,(这个编程环境)让学生教一个机器人来解决简单的问题。这个机器人名字叫卡雷尔。
因为捷克剧作家 KarelCapek 在 1923 年公演了 R.U.R (Rossum’s Universal Robots)后,为英语带来了
机器人这个英语单词--Robot 。
Karel the Robot was quite a success. Karel was used in introductory computer science courses all across
the country, to the point that Rich’s textbook sold well over 100,000 copies. Many generations of CS106A
students learned how programming works by putting Karel through its paces. But nothing lasts forever. In
the middle of the 1990s, the simulator we had been using for Karel the Robot stopped working. We were,
however, soon able to get a version of Karel up and running in the Thetis interpreter we were using at the
time. But then, a year ago, CS106A switched to Java, and Karel again vanished from the scene. For the
last three quarters, the hole in the curriculum left by Karel’s departure has been competently filled by
Nick Parlante’s Binky world, but it seems about time to bring Karel back. The new implementation of
Karel is designed to be compatible with both Java and the Eclipse programming environment, which
means that you’ll get to practice using the Eclipse editor and debugger from the very beginning of the
course.
机器人卡雷尔相当成功。 卡雷尔被用于全国的计算机科学入门课程,到了 Rich 的教科书畅销超
过 10 万份的地步。许多学习 CS106A 的学生,通过设计卡雷尔的行为,学会了如何让程序工作。
在 20 世纪 90 年代中期,我们曾经使用的机器人卡雷尔模拟器停止工作了。但是,我们很快就得
到了一个 Thetis 编译的卡雷尔升级版供那时使用。但是,一年以前,CS106A 课程转向到 Java,
卡雷尔再次从课堂上消失了。虽然在过去的三个季度,由于卡雷尔的离去产生的空白,已经完全
被 Nick Parlante 的 Binky world 填补了。但现在是带卡雷尔回来的时候了。新完工的卡雷尔设计
得完全兼容 Java 和 Eclipse 编程环境,这就意味着,你将在这门课程的开始,就可以练习使用
Eclipse 的编辑器和调试器。
What is Karel?
Karel is a very simple robot living in a very simple world. By giving Karel a set of commands, you can
direct it to perform certain tasks within its world. The process of specifying those commands is called
programming. Initially, Karel understands only a very small number of predefined commands, but an
important part of the programming process is teaching Karel new commands that extend its capabilities.
卡雷尔是啥?
卡雷尔是一个生活在非常简单的世界中的非常简单的机器人。在它的世界中,你可以通过给卡雷
尔一组命令,直接让卡雷尔执行某些任务。指定这些命令的过程称为编程。最初,卡雷尔只明白
极少数预定义的命令,但编程(学习)过程的一个重要内容,就是教卡雷尔可以扩展它的能力的
新命令。
When you program Karel to perform a task, you must write out the necessary
commands in a very precise way so that the robot can correctly interpret what you have told it to do. In
particular, the programs you write must obey a set of syntactic rules that define what commands and
language forms are legal. Taken together, the predefined commands and syntactic rules define the Karel
programming language. The Karel programming language is designed to be as similar as possible to Java
so as to ease the transition to the language you will be using all quarter. Karel programs have much the
same structure and involve the same fundamental elements as Java programs do. The critical difference is
that Karel’s programming language is extremely small, in the sense that it has very few commands and
rules. It is easy, for example, to teach the entire Karel language in just a couple of hours, which is
precisely what we do in CS106A. At the end of that time, you will know everything that Karel can do and
how to specify those actions in a program. The details are easy to master. Even so, you will discover that
solving a problem can be extremely challenging. Problem solving is the essence of programming; the
rules are just a minor concern along the way.
当你谋划让卡雷尔执行某项任务的时候,你必需用非常精确的方式写出这些必需的命令,以便这
个机器人能够正确的理解你交待它做的事情。(另外)特别(注意的)是,你写的程序必须遵守
语法规则,它规定了什么样的命令和语言形式是合法的。二者合在一起,预定义的命令和语法规
则(一起)定义了卡雷尔编程语言。卡雷尔编程语言被设计的尽可能类似于 Java 语言,这样便于
顺利过渡到(Java)这门你将时刻使用的语言上。卡雷尔程序具有和 Java 程序相同的结构,也涉
及到相同的基本元素。最关键的区别是,卡雷尔的编程语言非常的小,从这个意义上讲,它只具
有非常少的命令和规则。它非常容易,例如,教授卡雷尔语言只需要几个小时,这也正是我们在
CS106A 中做的。在(课程)结束的时候,你将知道卡雷尔能做的一切事情,以及如何在一个程
序中实现它。这些细节是容易掌握的。即便如此,你会发现,(需要)解决的问题可能是极其具
挑战性的。解决问题是编程的本质;在这一学习过程中,对规则的关注是次要的。
In sophisticated languages like Java, there are so many details that learning these details often becomes
the focus of the course. When that happens, the much more critical issues of problem solving tend to get
lost in the shuffle. By starting with Karel, you can concentrate on solving problems from the very
beginning. And because Karel encourages imagination and creativity, you can have quite a lot of fun
along the way.
在复杂的语言里,如 Java,有许多的细节,这些细节往往成为学习的课程的重点。当这种情况发
生时,对解决问题的更关键的东西,往往会在得到一片混乱中失去。通过从卡雷尔入手开始学习,
你可以在一开始的时候,就把精力集中在解决问题上面。而且,卡雷尔的学习鼓励想象力和创造
力,在学习过程中,你会收获不少乐趣。(这段话的意思是,要把精力集中在比语法细节更重要
的--解决问题的能力上。译者注)
Karel’s world
Karel’s world is defined by streets running horizontally (east-west) and avenues running vertically (north-
south). The intersection of a street and an avenue is called a corner. Karel can only be positioned on
corners and must be facing one of the four standard compass directions (north, south, east, west). A
sample Karel world is shown below. Here Karel is located at the corner of 1st Street and 1st Avenue,
facing east.
卡雷尔的世界
卡雷尔的世界被定义为水平的街(东西方向),垂直的道(南北方向)。街和道的交点被称为街角。
卡雷尔只能定位在街角上,而且只能面对的四个标准罗盘方向(北,南,东,西)。一个简单的
卡雷尔世界显示如下。卡雷尔目前位于第一大街和第一大道相交的街角,面朝向东。
Several other components of Karel’s world can be seen in this example. The object in front of Karel is a
beeper. As described in Rich Pattis’s book, beepers are “plastic cones which emit a quiet beeping noise.”
Karel can only detect a beeper if it is on the same corner. The solid lines in the diagram are walls. Walls
serve as barriers within Karel’s world. Karel cannot walk through walls and must instead go around them.
Karel’s world is always bounded by walls along the edges, but the world may have dfferent dimensions
depending on the specific problem Karel needs to solve.
在这个例子中,卡雷尔世界的几个其它组件也可以看到。卡雷尔前面的物体是个蜂鸣器,在 Rich
Pattis’s 的书中描述,蜂鸣器是一个发出轻微的哔哔声的塑料筒。只有当卡雷尔和蜂鸣器位于同一
个街角上的时候,卡雷尔才能感知这个蜂鸣器。图中的实线是墙壁。墙是卡雷尔世界的屏障。卡
雷尔不能穿过墙壁,而只能在墙的周边行走。卡雷尔的世界总是被作为边界的墙包围起来,但是,
随着卡雷尔需要解决不同的具体问题,卡雷尔的世界也有不同的尺寸。
What can Karel do?
When Karel is shipped from the factory, it responds to a very small set of commands:
move() Asks Karel to move forward one block. Karel cannot respond to a
move() command if there is a wall blocking its way.
turnLeft() Asks Karel to rotate 90 degrees to the left (counterclockwise).
pickBeeper() Asks Karel to pick up one beeper from a corner and stores the beeper in its beeper bag,
which can hold an infinite number of beepers. Karel cannot respond to a pickBeeper() command unless
there is a beeper
on the current corner.
putBeeper() Asks Karel to take a beeper from its beeper bag and put it down on the current corner. Karel
cannot respond to a putBeeper() command
unless there are beepers in its beeper bag.
卡雷尔能干点啥?
当卡雷尔出厂的时候,它只能响应非常小的命令集:
move() 要求卡雷尔向前推进一步。当一堵墙挡在卡雷尔面前的时候,卡雷尔不能响应 move()
这个命令。
turnLeft() 要求卡雷尔向左转 90 度(逆时针转动)。
pickBeeper() 要求卡雷尔捡起街角上的蜂鸣器,把这个蜂鸣器放到它的蜂鸣器收藏包里,这个包
可容纳无限多的蜂鸣器。除非这个蜂鸣器恰好在卡雷尔所在的街角上,卡雷尔不能响应这个
pickBeeper()命令。
putBeeper() 要求卡雷尔从蜂鸣器收藏包里拿出一个蜂鸣器,放在卡雷尔所在的街角上。除非卡雷
尔的蜂鸣器收藏包里有蜂鸣器,卡雷尔不能响应这个 putBeeper()命令。
The empty pair of parentheses that appears in each of these commands is part of the common syntax
shared by Karel and Java and is used to specify the invocation of the command. Eventually, the programs
you write will include additional information in the space between the parentheses, but such information
is not part of the Karel’s primitive world. These parentheses will therefore be empty in standard Karel
programs, but you must remember to include them nonetheless.
出现在这些命令后面的一对空括号,是卡雷尔和 Java 相同语法的一部分,通过这个(一对空括
号),来指定命令的调用。最终的时候,在你写的(Java)程序里,空括号之间会包含一些额外
的内容,但是,这些额外的内容并不是卡雷尔原始世界的一部分。将这些括号之间留空,才是标准
的卡雷尔程序,虽然括号里什么也没有,但你一定要记着把它们写在命令里。
It is also important to recognize that several of these commands place restrictions on Karel’s activities. If
Karel tries to do something illegal, such as moving through a wall or picking up a nonexistent beeper, an
error condition occurs. At this point, Karel displays an error message and does not execute any remaining
commands.
需要特别注意的是,这几个命令对卡雷尔的行为进行了限制。如果卡雷尔试图做些非法的举动,
像穿墙或者捡起一个不存在的蜂鸣器,一个错误就发生了。在这时,卡雷尔会显示一条错误的信
息,同时拒绝执行剩余的命令。
Karel’s commands, however, cannot be executed on their own. Before Karel can respond to any of these
commands, you need to incorporate them into a Karel program.You will have a chance to see a few
simple Karel programs in Chapter 2, but before doing so, it is useful to make a few general remarks about
the programming philosophy that underlies this particular implementation of the Karel programming
language.
卡雷尔的这些命令,不能自己自动执行。在卡雷尔可以执行这些命令之前,你需要先把它们写在
一个卡雷尔程序里。在第二章,你将有机会看到一些简单的卡雷尔程序。但是,在运行这些程序
之前,作一些执行卡雷尔程序语言必要的基本编程哲学的提醒,还是非常有用的。
Karel and the object-oriented paradigm
When Karel was introduced in the 1970s, the prevailing approach to writing computer programs was the
procedural paradigm. To a large extent, procedural programming is the process of decomposing a large
programming problem into smaller, more manageable units called procedures that define the necessary
operations. Although the strategy of breaking programs down into smaller units remains a vital part of any
style of programming, modern languages like Java emphasize a different approach called the
object-oriented paradigm. In object-oriented programming, the programmer’s attention shifts away from
the procedural specification of operations and focuses instead on modeling the behavior of conceptually
integrated units called objects. Objects in a programming language sometimes correspond to physical
objects in the real world, but just as often represent more abstract concepts. The central feature of any
object—real or abstract—is that it must make sense as a unified whole.
卡雷尔和面向对象模式
在卡雷尔被引入的二十世纪七十年代,采用的计算机编程方法是过程模式。在很大程度上,过程
编程是把一个大规模的程序问题分解为小的过程,这些更易于管理的,定义了必要操作的单元称
为过程。这种把程序分割成小单元的谋划,是编程风格的重要组成部分,而现代语言例如 Java,强
调了不同的编程模式,叫面向对象模式。在面向对象模式下,程序员的注意力被从关注特定操作
的过程单元中转移出来,侧重到:为被称为对象的单元,抽象建模的行为上。在编程语言中,“对
象”有时和真实世界的物理对象相对应,但更多的时候是抽象的概念。是真实对象的核心特性或代
表(事物)整体的一种抽象。
One of the primary advantages of the object-oriented paradigm is that it encourages programmers to
recognize the fundamental relationship between the state of an object and its behavior. The state of an
object consists of a set of attributes that pertain to that object and might change over time. For example,
an object might be characterized by its location in space, its color, its name, and a host of other properties.
The behavior of an object refers to the ways in which that object responds to events in its world or
commands from other objects. In the language of object-oriented programming, the generic word for
anything that triggers a particular behavior in an object is called a message (although it generally seems
clearer to use the word command in the context of
Karel). The response to a message typically involves changing the state of an object. For example, if one
of the properties defining the state of an object is its color, then it would presumably respond to a
setColor(BLUE) message by changing its color to blue.
面向对象模式的主要优势之一是,它鼓励程序员认识到一个对象的状态和其行为的基本关系。一
个对象的状态,涉及到一组和该对象相关,并可能随时间而改变的特性。一个对象可以被它在空
间的位置,它的颜色,它的名字,其它一些主要特性来特别指定出来。一个对象的行为是指它在
它的世界中响应事件或响应来自其它对象的命令的方法。在面向对象编程的语言中,触发指定对
象的行为的通用词叫消息--message(虽然从卡雷尔的上下文上看,命令--command 这个词可能更
让人明白点)。对一个消息的响应,通常需要改变一个对象的状态。例如,如果定义一个对象状
态的特性的之一是它的颜色,它就可以通过响应 setColor(BLUE) 这条消息把它的颜色改变成蓝色。
In many ways, Karel represents an ideal environment for illustrating the object- oriented approach.
Although no one has actually built a mechanical implementation of Karel, it is nonetheless easy to
imagine Karel as a real-world object. Karel is, after all, a robot, and robots are real-world entities. The
properties that define Karel’s state are its location in the world, the direction it is facing, and the number
of beepers in its beeper
bag. Karel’s behavior is defined by the commands to which it responds:move(), turnLeft(), pickBeeper(),
and putBeeper(). The move() command changes Karel’s location, turnLeft() changes its direction, and the
remaining two affect both the number of beepers in Karel’s bag and the number of beepers on the current
corner.
在许多方面,卡雷尔代表了讲述“面向对象方法”的理想环境。虽然实际上没有人建立一个机器来
执行卡雷尔,但却非常容易把卡雷尔想象为一个真实世界的对象。卡雷尔毕竟是一个机器人,机
器人是真实世界存在的实体。定义卡雷尔状态的特性是它在它的世界中的位置,它面对的方向,
在它蜂鸣器收藏包里的蜂鸣器数目。定义卡雷尔行为的是它响应的 move(), turnLeft(),
pickBeeper(), 和 putBeeper()这些命令。move()命令可以改变卡雷尔的位置,turnLeft()命令可以改
变它面朝的方向,剩下的两个命令(指 pickBeeper()和 putBeeper()这两个命令--译者注),会同时
影响到收藏包里的蜂鸣器数量和当前街角上的蜂鸣器数量。
The Karel environment also provides a useful framework for defining one of the central concepts of
object-oriented programming. In both Karel and Java, it is essential to differentiate the notion of an object
from that of a class. The easiest way to understand the distinction is to think about a class as a pattern or
template for objects that share a common behavior and collection of state attributes. As you will see in the
next chapter, the word Karel in a Karel program represents the entire class of robots that know how to
respond to the move(), turnLeft(), pickBeeper(), and putBeeper() commands. Whenever you have an
actual robot in the world, that robot is an object that represents a specific instance of the Karel class.
Although you won’t have occasion to do so in CS 106A , it is possible to have more than one instance of
the Karel class running in the same world. Even when there is only a single robot, however, it is important
to remember that object and class are different concepts and to keep those ideas straight in your mind.
卡雷尔的环境还提供了面向对象编程的核心概念之一--一个有用的框架。无论卡雷尔还是 Java,一
个对象和一个类之间概念的区分是很有必要的。最容易理解这种分别的方法是把类认为是一些对
象(共同)的模式或模板,这些对象都有一个共同的行为和状态属性的集合。在你将看到的下一
章中,在卡雷尔程序里出现的 “karel"这个词,代表一个完整的机器人的类,这个类知道怎么去响
应 move(), turnLeft(), pickBeeper(), 和 putBeeper() 这些命令。但只要你在卡雷尔的世界里有了一个
实际的机器人,那么,这个机器人就是一个对象,这个机器人它代表了卡雷尔这个类的特定实例。
尽管在 CS106A 课程里,你将不会有机会去做这样一个类,但有一个以上的卡雷尔类的实例,运
行在同一个世界里,还是有可能的。即使只有一个单独机器人的时候,在你的脑海里,深刻记得
类和对象是不同的概念,还是很重要的。
The importance of practical experience
Programming is very much a learn-by-doing activity. As you will continually discover in your study of
computer science, reading about some programming concept is not the same thing as using that concept in
a program. Things that seem very clear on the page can be difficult to put into practice.
实际经验的重要性
编程是一项需要大量边学边干的活动。就像你将在你的计算机学习中不断发现的那样,读懂一些
编程概念和能在一个程序中使用这个概念不是同一回事。在纸面上看起来似乎很清楚的东西,具
体实施起来就变得非常的难。
Given the fact that writing programs on your own and getting them to run on the computer are essential to
learning about programming, it may seem surprising to discover that this book does not include much
discussion of the hands-on aspects of using Karel on your computer. The reason for that omission is that
the steps you need to run a Karel program depend on the environment you’re using. Running Karel
programs on a Macintosh is somewhat different from running it under Windows. Even though the
programming environment you use has a great deal of influence on the nitty-gritty details you need to run
programs, it has no influence whatsoever on the general concepts. This book describes the general
concepts; the details pertinent to each platform will be distributed as handouts during the course.
在编程学习中,你写出程序和让这些程序能在计算机上运行是同样重要的。你会惊讶的发现,这
本书没有包括多少手把手操作卡雷尔如何在你的计算机运行的讨论。遗漏这些部分的原因是,你
运行卡雷尔需要依靠你使用的计算机环境。在苹果机上运行卡雷尔程序和在 Windows 下是不一样
的。即使你使用的编程环境对你运行程序的基本细节有很大的影响,但他对常规的(编程)概念
没有任何影响。这本书介绍常规概念;(而)每个平台的相关细节,被包含在分发的课程讲义中。
The fact that this book omits the practical details, however, should in no sense be interpreted as
minimizing their importance. If you want to understand how programming works—even in an
environment as simple as that provided by Karel—it is essential to “get your hands dirty” and start using
the computer. Doing so is by far the most effective introduction into the world of programming and the
excitement that it holds.
实际上,这本书省略了些实际的细节,但无意减少这些细节的重要性。即使你要弄明白像卡雷尔
提供的,这么简单的编程环境下,如何开始编程工作,你也必需”弄脏你的手“--开始实际的计算机
操作。
这样做是进入编程世界,享受它带来的激情,目前最有效的方式。
Chapter 2
Programming Karel
第二章
卡雷尔程序设计
In its new object-oriented implementation, the simplest style of Karel program consists of a definition of a
new Karel class that specifies a sequence of built-in commands that should be executed when the program
is run. A very simple Karel program is shown in Figure 1.
在卡雷尔新的面向对象的实现中(这个新的,应该是和七十年代的卡雷尔实现程序相对而言--译
者注),最简单的卡雷尔程序包含一个定义的 karel 类,这个类指定了一系列在程序运行的时候,
可以被执行的内建命令。卡雷尔一个非常简单的程序如 Figure 1 所示。
Figure 1. Simple Karel example to pick up a single beeper
---------------------------------------------------------------------------------------
/*
* File: BeeperPickingKarel.java
* -----------------------------
* The BeeperPickingKarel class extends the basic Karel class
* by defining a "run" method with three commands. These
* commands cause Karel to move forward one block, pick up
* a beeper, and then move ahead to the next corner.
*/
import stanford.karel.*;
public class BeeperPickingKarel extends Karel {
public void run() {
move();
pickBeeper();
move();
}
}
-----------------------------------------------------------------------------------------
The program in Figure 1 is composed of several parts. The first part consists of the following lines:
Figure 1 中的程序是由几部分组成的。第一部分由下面的几行组成。
/*
* File: BeeperPickingKarel.java
* -----------------------------
* The BeeperPickingKarel class extends the basic Karel class
* by defining a "run" method with three commands. These
* commands cause Karel to move forward one block, pick up
* a beeper, and then move ahead to the next corner.
*/