mirror of
https://github.com/apachecn/eloquent-js-3e-zh.git
synced 2025-05-24 04:22:20 +00:00
7.
This commit is contained in:
parent
ccf4b74ed0
commit
ddcd1a7cc1
38
7.md
38
7.md
@ -4,7 +4,7 @@
|
|||||||
>
|
>
|
||||||
> <footer>Edsger Dijkstra, <cite>The Threats to Computing Science</cite></footer>
|
> <footer>Edsger Dijkstra, <cite>The Threats to Computing Science</cite></footer>
|
||||||
|
|
||||||
<figure class="chapter framed"></figure>
|

|
||||||
|
|
||||||
在“项目”章节中,我会在短时间内停止向你讲述新理论,相反我们会一起完成一个项目。 学习编程理论是必要的,但阅读和理解实际的计划同样重要。
|
在“项目”章节中,我会在短时间内停止向你讲述新理论,相反我们会一起完成一个项目。 学习编程理论是必要的,但阅读和理解实际的计划同样重要。
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ class VillageState {
|
|||||||
|
|
||||||
然后它创建一个新的状态,将目的地作为机器人的新地点。 但它也需要创建一套新的包裹 - 机器人携带的包裹(位于机器人当前位置)需要移动到新位置。 而要寄往新地点的包裹需要送达 - 也就是说,需要将它们从未送达的包裹中移除。 `'map'`的调用处理移动,并且`'filter'`的调用处理递送。
|
然后它创建一个新的状态,将目的地作为机器人的新地点。 但它也需要创建一套新的包裹 - 机器人携带的包裹(位于机器人当前位置)需要移动到新位置。 而要寄往新地点的包裹需要送达 - 也就是说,需要将它们从未送达的包裹中移除。 `'map'`的调用处理移动,并且`'filter'`的调用处理递送。
|
||||||
|
|
||||||
Parcel objects aren’t changed when they are moved, but recreated. The `move` method gives us a new village state, but leaves the old one entirely intact.
|
包裹对象在移动时不会更改,但会被重新创建。 `move`方法为我们提供新的村庄状态,但完全保留了原有的村庄状态。
|
||||||
|
|
||||||
```
|
```
|
||||||
let first = new VillageState(
|
let first = new VillageState(
|
||||||
@ -116,13 +116,13 @@ console.log(first.place);
|
|||||||
// → Post Office
|
// → Post Office
|
||||||
```
|
```
|
||||||
|
|
||||||
The move causes the parcel to be delivered, and this is reflected in the next state. But the initial state still describes the situation where the robot is at the post office and the parcel is undelivered.
|
`move`会使包裹被送达,并在下一个状态中反映出来。 但最初的状态仍然描述机器人在邮局并且包裹未送达的情况。
|
||||||
|
|
||||||
## Persistent data
|
## 持久性数据
|
||||||
|
|
||||||
Data structures that don’t change are called _immutable_ or _persistent_. They behave a lot like strings and numbers in that they are who they are, and stay that way, rather than containing different things at different times.
|
不会改变的数据结构称为不变的(immutable)或持久性的(persistent)。 他们的表现很像字符串和数字,因为他们就是他们自己,并保持这种状态,而不是在不同的时间包含不同的东西。
|
||||||
|
|
||||||
In JavaScript, just about everything _can_ be changed, so working with values that are supposed to be persistent requires some restraint. There is a function called `Object.freeze` that changes an object so that writing to its properties is ignored. You could use that to make sure your objects aren’t changed, if you want to be careful. Freezing does require the computer to do some extra work, and having updates ignored is just about as likely to confuse someone as having them do the wrong thing. So I usually prefer to just tell people that a given object shouldn’t be messed with, and hope they remember it.
|
在 JavaScript 中,几乎所有的东西都可以改变,所以使用应该持久性的值需要一些限制。 有一个叫做`Object.freeze`的函数,它可以改变一个对象,使其忽略它的属性的写入。 如果你想要小心,你可以使用它来确保你的对象没有改变。 `freeze`确实需要计算机做一些额外的工作,忽略更新可能会让一些人迷惑,让他们做错事。 所以我通常更喜欢告诉人们,不应该弄乱给定的对象,并希望他们记住它。
|
||||||
|
|
||||||
```
|
```
|
||||||
let object = Object.freeze({value: 5});
|
let object = Object.freeze({value: 5});
|
||||||
@ -131,19 +131,19 @@ console.log(object.value);
|
|||||||
// → 5
|
// → 5
|
||||||
```
|
```
|
||||||
|
|
||||||
Why am I going out of my way to not change objects when the language is obviously expecting me to?
|
当语言显然期待我这样做时,为什么我不想改变对象?
|
||||||
|
|
||||||
Because it helps me understand my programs. This is about complexity management again. When the objects in my system are fixed, stable things, I can consider operations on them in isolation—moving to Alice’s house from a given start state always produces the same new state. When objects change over time, that adds a whole new dimension of complexity to this kind of reasoning.
|
因为它帮助我理解我的程序。 这又是关于复杂性管理。 当我的系统中的对象是固定的,稳定的东西时,我可以孤立地考虑操作它们 - 从给定的起始状态移动到爱丽丝的房子,始终会产生相同的新状态。 当对象随着时间而改变时,这就给这种推理增加了全新的复杂性。
|
||||||
|
|
||||||
For a small system like the one we are building in this chapter, we could handle that bit of extra complexity. But the most important limit on what kind of systems we can build is how much we can understand. Anything that makes your code easier to understand makes it possible to build a more ambitious system.
|
对于小型系统,例如我们在本章中构建的东西,我们可以处理那些额外的复杂性。 但是我们可以建立什么样的系统,最重要的限制是我们能够理解多少。 任何让你的代码更容易理解的东西,都可以构建一个更加庞大的系统。
|
||||||
|
|
||||||
Unfortunately, although understanding a system built on persistent data structures is easier, _designing_ one, especially when your programming language isn’t helping, can be a little harder. We’ll look for opportunities to use persistent data structures in this book, but we’ll also be using changeable ones.
|
不幸的是,尽管理解构建在持久性数据结构上的系统比较容易,但设计一个,特别是当你的编程语言没有帮助时,可能会更难一些。 我们将在本书中寻找使用持久性数据结构的时机,但我们也将使用可变数据结构。
|
||||||
|
|
||||||
## Simulation
|
## 模拟
|
||||||
|
|
||||||
A delivery robot looks at the world and decides in which direction it wants to move. As such, we could say that a robot is a function that takes a `VillageState` object and returns the name of a nearby place.
|
递送机器人观察世界并决定它想要移动的方向。 因此,我们可以说机器人是一个函数,接受`VillageState`对象并返回附近地点的名称。
|
||||||
|
|
||||||
Because we want robots to be able to remember things, so that they can make and execute plans, we also pass them their memory and allow them to return a new memory. Thus, the thing a robot returns is an object containing both the direction it wants to move in and a memory value that will be given back to it the next time it is called.
|
因为我们希望机器人能够记住东西,以便他们可以制定和执行计划,我们也会传递他们的记忆,并让他们返回一个新的记忆。 因此,机器人返回的东西是一个对象,包含它想要移动的方向,以及下次调用时将返回给它的记忆值。
|
||||||
|
|
||||||
```
|
```
|
||||||
function runRobot(state, robot, memory) {
|
function runRobot(state, robot, memory) {
|
||||||
@ -160,11 +160,11 @@ function runRobot(state, robot, memory) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Consider what a robot has to do to “solve” a given state. It must pick up all parcels by visiting every location that has a parcel, and deliver them by visiting every location that a parcel is addressed to, but only after picking up the parcel.
|
考虑一下机器人必须做些什么来“解决”一个给定的状态。 它必须通过访问拥有包裹的每个位置来拾取所有包裹,并通过访问包裹寄往的每个位置来递送,但只能在拾取包裹之后。
|
||||||
|
|
||||||
What is the dumbest strategy that could possibly work? The robot could just walk in a random direction every turn. That means, with great likelihood, that it will eventually run into all parcels, and then also at some point reach the place where they should be delivered.
|
什么是可能有效的最愚蠢的策略? 机器人可以在每回合中,向随机方向行走。 这意味着很有可能它最终会碰到所有的包裹,然后也会在某个时候到达包裹应该送达的地方。
|
||||||
|
|
||||||
Here’s what that could look like:
|
以下是可能的样子:
|
||||||
|
|
||||||
```
|
```
|
||||||
function randomPick(array) {
|
function randomPick(array) {
|
||||||
@ -177,11 +177,11 @@ function randomRobot(state) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Remember that `Math.random()` returns a number between zero and one, but always below one. Multiplying such a number by the length of an array and then applying `Math.floor` to it gives us a random index for the array.
|
请记住,`Math.random()`返回 0 和 1 之间的数字,但总是小于 1。 将这样一个数乘以数组长度,然后将`Math.floor`应用于它,向我们提供数组的随机索引。
|
||||||
|
|
||||||
Since this robot does not need to remember anything, it ignores its second argument (remember that JavaScript functions can be called with extra arguments without ill effects) and omits the `memory` property in its returned object.
|
由于这个机器人不需要记住任何东西,所以它忽略了它的第二个参数(记住,可以使用额外的参数调用 JavaScript 函数而不会产生不良影响)并省略返回对象中的`memory`属性。
|
||||||
|
|
||||||
To put this sophisticated robot to work, we’ll first need a way to create a new state with some parcels. A static method (written here by directly adding a property to the constructor) is a good place to put that functionality.
|
为了使这个复杂的机器人工作,我们首先需要一种方法来创建一些包裹的新状态。 静态方法(通过直接向构造函数添加一个属性来编写)是放置该函数的好地方。
|
||||||
|
|
||||||
```
|
```
|
||||||
VillageState.random = function(parcelCount = 5) {
|
VillageState.random = function(parcelCount = 5) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user