ambit 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +5 -1
- data/README.rdoc +25 -23
- data/README.txt +25 -23
- data/lib/ambit.rb +1 -1
- metadata +5 -5
data/History.txt
CHANGED
data/README.rdoc
CHANGED
@@ -10,7 +10,7 @@ License:: 2-clause BSD-Style (see LICENSE.txt)
|
|
10
10
|
|
11
11
|
This is an all-ruby implementation of choose/fail nondeterministic
|
12
12
|
programming with branch cut, as described in Chapter 22 of Paul Graham's
|
13
|
-
<em>On Lisp</em>[1],
|
13
|
+
<em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2].
|
14
14
|
|
15
15
|
Due to Ruby containing a true call/cc, this is a much straighter port of
|
16
16
|
Paul Graham's scheme version of this code than his Common Lisp or my C
|
@@ -41,17 +41,16 @@ and generate the RDoc.
|
|
41
41
|
|
42
42
|
=== What is Nondeterministic Programming?
|
43
43
|
|
44
|
-
Nondeterministic programming is a novel approach to problems where a
|
45
|
-
|
46
|
-
|
47
|
-
values,
|
48
|
-
|
49
|
-
in advance.
|
44
|
+
Nondeterministic programming is a novel approach to problems where a program
|
45
|
+
must find a working solution out of many possible choices. It greatly
|
46
|
+
simplifies problems such as graph searching, or testing combinations of
|
47
|
+
values, where there are many possible values to consider, often in some sort
|
48
|
+
of hierarchical order, but the right combination is not known in advance.
|
50
49
|
|
51
50
|
In such a situation, it can be useful to develop a program by pretending
|
52
51
|
our programming language includes knowledge of the future -- and is thus
|
53
52
|
able to _choose_ the right answer off the bat, and simply programming as
|
54
|
-
if this
|
53
|
+
if this were the case.
|
55
54
|
|
56
55
|
A language with support for nondeterministic programming (such as Ruby
|
57
56
|
with this gem) helps us keep up this pretense by saving the state of
|
@@ -66,7 +65,7 @@ _fails_, computation will be rewound to the previous choice point, and
|
|
66
65
|
will continue with the next possible choice from there.
|
67
66
|
|
68
67
|
Imagine, for instance, that we wish to test a combination lock with a
|
69
|
-
three-number combination, with each number between 1 and 10, inclusive
|
68
|
+
three-number combination, with each number between 1 and 10, inclusive.
|
70
69
|
Instead of writing code ourself to try every possible combination, we
|
71
70
|
simply proceed as if each choice was the correct one, failing if the lock
|
72
71
|
fails to open. In short:
|
@@ -88,7 +87,7 @@ but we can program as if it has chosen the right one on the first try!
|
|
88
87
|
To get started, include this gem using
|
89
88
|
|
90
89
|
require 'rubygems'
|
91
|
-
require 'ambit
|
90
|
+
require 'ambit'
|
92
91
|
|
93
92
|
This gem provides the Ambit module. This module provides several methods
|
94
93
|
which implement nondeterministic programming.
|
@@ -120,9 +119,12 @@ prints
|
|
120
119
|
2
|
121
120
|
(and only "2")
|
122
121
|
|
123
|
-
|
124
|
-
|
125
|
-
|
122
|
+
<em>This means that computation now proceeds as if that had been the value
|
123
|
+
returned by Ambit::choose all along.</em>
|
124
|
+
|
125
|
+
As an alternative, Ambit::assert can be used to fail unless a condition
|
126
|
+
holds. Ambit::assert will rewind to the previous invocation of
|
127
|
+
Ambit::choose if and only if it's (single) argument is false:
|
126
128
|
|
127
129
|
a = Ambit::choose([1, 2, 3])
|
128
130
|
Ambit::assert a.even?
|
@@ -163,10 +165,10 @@ we have performed since the choice point we are rewinding to has had side
|
|
163
165
|
effects (other than the choices made), those side effects will not
|
164
166
|
themselves be rewound. While some side effects (setting of variables) could
|
165
167
|
theoretically be tracked and undone, this would require very careful
|
166
|
-
semantics
|
167
|
-
complexity added to our language
|
168
|
+
semantics -- nd other side effects could not be undone by any level of
|
169
|
+
complexity added to our language. If we have printed output to the user,
|
168
170
|
for instance, no amount of rewinding will make the user forget what he has
|
169
|
-
seen
|
171
|
+
seen; while we simulate the ability to see the future and to change the
|
170
172
|
past, we can, in fact, do neither.
|
171
173
|
|
172
174
|
This can sometimes cause confusion. This code, for instance:
|
@@ -199,14 +201,14 @@ remains incremented even when we rewind computation).
|
|
199
201
|
==== More Than One Answer
|
200
202
|
|
201
203
|
Often, more than one combination of choices is interesting to consider -- it
|
202
|
-
may be useful, for instance, to see
|
204
|
+
may be useful, for instance, to see _all_ combinations which do not fail,
|
203
205
|
instead of only the first.
|
204
206
|
|
205
207
|
Since Ambit::fail! will always rewind to the previous choice point, getting
|
206
208
|
more possible combinations is as easy as calling Ambit::fail! in order to
|
207
|
-
try the next combination
|
209
|
+
try the next combination -- even though we have not, strictly, failed. When
|
208
210
|
no more successful combinations are available, this call to Ambit::fail!
|
209
|
-
will instead raise an exception of type Ambit::ChoicesExhausted
|
211
|
+
will instead raise an exception of type Ambit::ChoicesExhausted.
|
210
212
|
|
211
213
|
begin
|
212
214
|
a = Ambit::choose([1, 3, 5, 7, 9, 11, 13, 15])
|
@@ -242,7 +244,7 @@ computations, sometimes it is useful to abandon only one branch of a
|
|
242
244
|
computation, while still keeping the ability to rewind to the choice which
|
243
245
|
first took us down that branch.
|
244
246
|
|
245
|
-
Suppose, for instance, that we are trying to guess a word with
|
247
|
+
Suppose, for instance, that we are trying to guess a word with four letters:
|
246
248
|
|
247
249
|
a = Ambit::choose('a'..'z')
|
248
250
|
b = Ambit::choose('a'..'z')
|
@@ -286,7 +288,7 @@ the whole current branch of computation.
|
|
286
288
|
==== Private Generators
|
287
289
|
|
288
290
|
In addition to using methods of the Ambit module directly, another option is
|
289
|
-
to allocate
|
291
|
+
to allocate an Ambit::Generator object explicitly. All methods of the Ambit
|
290
292
|
module are also available as methods of Ambit::Generator (and in fact, the
|
291
293
|
module allocates a default Generator object to handle all calls made at the
|
292
294
|
module level).
|
@@ -310,7 +312,7 @@ unrelated set of nondeterministic computations.
|
|
310
312
|
|
311
313
|
For historical reasons, Ambit::amb and Ambit::Generator#amb are provided as
|
312
314
|
aliases for Ambit::choose and Ambit::Generator#choose. Likewise, for
|
313
|
-
historical reasons, calling Ambit::
|
315
|
+
historical reasons, calling Ambit::choose (and Ambit::Generator#choose) with
|
314
316
|
no arguments is equivalent to calling Ambit::fail! (or
|
315
317
|
Ambit::Generator#fail!).
|
316
318
|
|
@@ -318,7 +320,7 @@ For the same reason, Ambit::require and Ambit::Generator#require are
|
|
318
320
|
provided as aliases for Ambit::assert and Ambit::Generator#assert.
|
319
321
|
|
320
322
|
These aliases allow for a more direct translation of programs written with
|
321
|
-
the
|
323
|
+
the _amb_ operator discussed in _SICP_ and elsewhere.
|
322
324
|
|
323
325
|
==== Interaction with Threading
|
324
326
|
|
data/README.txt
CHANGED
@@ -10,7 +10,7 @@ License:: 2-clause BSD-Style (see LICENSE.txt)
|
|
10
10
|
|
11
11
|
This is an all-ruby implementation of choose/fail nondeterministic
|
12
12
|
programming with branch cut, as described in Chapter 22 of Paul Graham's
|
13
|
-
<em>On Lisp</em>[1],
|
13
|
+
<em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2].
|
14
14
|
|
15
15
|
Due to Ruby containing a true call/cc, this is a much straighter port of
|
16
16
|
Paul Graham's scheme version of this code than his Common Lisp or my C
|
@@ -41,17 +41,16 @@ and generate the RDoc.
|
|
41
41
|
|
42
42
|
=== What is Nondeterministic Programming?
|
43
43
|
|
44
|
-
Nondeterministic programming is a novel approach to problems where a
|
45
|
-
|
46
|
-
|
47
|
-
values,
|
48
|
-
|
49
|
-
in advance.
|
44
|
+
Nondeterministic programming is a novel approach to problems where a program
|
45
|
+
must find a working solution out of many possible choices. It greatly
|
46
|
+
simplifies problems such as graph searching, or testing combinations of
|
47
|
+
values, where there are many possible values to consider, often in some sort
|
48
|
+
of hierarchical order, but the right combination is not known in advance.
|
50
49
|
|
51
50
|
In such a situation, it can be useful to develop a program by pretending
|
52
51
|
our programming language includes knowledge of the future -- and is thus
|
53
52
|
able to _choose_ the right answer off the bat, and simply programming as
|
54
|
-
if this
|
53
|
+
if this were the case.
|
55
54
|
|
56
55
|
A language with support for nondeterministic programming (such as Ruby
|
57
56
|
with this gem) helps us keep up this pretense by saving the state of
|
@@ -66,7 +65,7 @@ _fails_, computation will be rewound to the previous choice point, and
|
|
66
65
|
will continue with the next possible choice from there.
|
67
66
|
|
68
67
|
Imagine, for instance, that we wish to test a combination lock with a
|
69
|
-
three-number combination, with each number between 1 and 10, inclusive
|
68
|
+
three-number combination, with each number between 1 and 10, inclusive.
|
70
69
|
Instead of writing code ourself to try every possible combination, we
|
71
70
|
simply proceed as if each choice was the correct one, failing if the lock
|
72
71
|
fails to open. In short:
|
@@ -88,7 +87,7 @@ but we can program as if it has chosen the right one on the first try!
|
|
88
87
|
To get started, include this gem using
|
89
88
|
|
90
89
|
require 'rubygems'
|
91
|
-
require 'ambit
|
90
|
+
require 'ambit'
|
92
91
|
|
93
92
|
This gem provides the Ambit module. This module provides several methods
|
94
93
|
which implement nondeterministic programming.
|
@@ -120,9 +119,12 @@ prints
|
|
120
119
|
2
|
121
120
|
(and only "2")
|
122
121
|
|
123
|
-
|
124
|
-
|
125
|
-
|
122
|
+
<em>This means that computation now proceeds as if that had been the value
|
123
|
+
returned by Ambit::choose all along.</em>
|
124
|
+
|
125
|
+
As an alternative, Ambit::assert can be used to fail unless a condition
|
126
|
+
holds. Ambit::assert will rewind to the previous invocation of
|
127
|
+
Ambit::choose if and only if it's (single) argument is false:
|
126
128
|
|
127
129
|
a = Ambit::choose([1, 2, 3])
|
128
130
|
Ambit::assert a.even?
|
@@ -163,10 +165,10 @@ we have performed since the choice point we are rewinding to has had side
|
|
163
165
|
effects (other than the choices made), those side effects will not
|
164
166
|
themselves be rewound. While some side effects (setting of variables) could
|
165
167
|
theoretically be tracked and undone, this would require very careful
|
166
|
-
semantics
|
167
|
-
complexity added to our language
|
168
|
+
semantics -- nd other side effects could not be undone by any level of
|
169
|
+
complexity added to our language. If we have printed output to the user,
|
168
170
|
for instance, no amount of rewinding will make the user forget what he has
|
169
|
-
seen
|
171
|
+
seen; while we simulate the ability to see the future and to change the
|
170
172
|
past, we can, in fact, do neither.
|
171
173
|
|
172
174
|
This can sometimes cause confusion. This code, for instance:
|
@@ -199,14 +201,14 @@ remains incremented even when we rewind computation).
|
|
199
201
|
==== More Than One Answer
|
200
202
|
|
201
203
|
Often, more than one combination of choices is interesting to consider -- it
|
202
|
-
may be useful, for instance, to see
|
204
|
+
may be useful, for instance, to see _all_ combinations which do not fail,
|
203
205
|
instead of only the first.
|
204
206
|
|
205
207
|
Since Ambit::fail! will always rewind to the previous choice point, getting
|
206
208
|
more possible combinations is as easy as calling Ambit::fail! in order to
|
207
|
-
try the next combination
|
209
|
+
try the next combination -- even though we have not, strictly, failed. When
|
208
210
|
no more successful combinations are available, this call to Ambit::fail!
|
209
|
-
will instead raise an exception of type Ambit::ChoicesExhausted
|
211
|
+
will instead raise an exception of type Ambit::ChoicesExhausted.
|
210
212
|
|
211
213
|
begin
|
212
214
|
a = Ambit::choose([1, 3, 5, 7, 9, 11, 13, 15])
|
@@ -242,7 +244,7 @@ computations, sometimes it is useful to abandon only one branch of a
|
|
242
244
|
computation, while still keeping the ability to rewind to the choice which
|
243
245
|
first took us down that branch.
|
244
246
|
|
245
|
-
Suppose, for instance, that we are trying to guess a word with
|
247
|
+
Suppose, for instance, that we are trying to guess a word with four letters:
|
246
248
|
|
247
249
|
a = Ambit::choose('a'..'z')
|
248
250
|
b = Ambit::choose('a'..'z')
|
@@ -286,7 +288,7 @@ the whole current branch of computation.
|
|
286
288
|
==== Private Generators
|
287
289
|
|
288
290
|
In addition to using methods of the Ambit module directly, another option is
|
289
|
-
to allocate
|
291
|
+
to allocate an Ambit::Generator object explicitly. All methods of the Ambit
|
290
292
|
module are also available as methods of Ambit::Generator (and in fact, the
|
291
293
|
module allocates a default Generator object to handle all calls made at the
|
292
294
|
module level).
|
@@ -310,7 +312,7 @@ unrelated set of nondeterministic computations.
|
|
310
312
|
|
311
313
|
For historical reasons, Ambit::amb and Ambit::Generator#amb are provided as
|
312
314
|
aliases for Ambit::choose and Ambit::Generator#choose. Likewise, for
|
313
|
-
historical reasons, calling Ambit::
|
315
|
+
historical reasons, calling Ambit::choose (and Ambit::Generator#choose) with
|
314
316
|
no arguments is equivalent to calling Ambit::fail! (or
|
315
317
|
Ambit::Generator#fail!).
|
316
318
|
|
@@ -318,7 +320,7 @@ For the same reason, Ambit::require and Ambit::Generator#require are
|
|
318
320
|
provided as aliases for Ambit::assert and Ambit::Generator#assert.
|
319
321
|
|
320
322
|
These aliases allow for a more direct translation of programs written with
|
321
|
-
the
|
323
|
+
the _amb_ operator discussed in _SICP_ and elsewhere.
|
322
324
|
|
323
325
|
==== Interaction with Threading
|
324
326
|
|
data/lib/ambit.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ambit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 57
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 1
|
10
|
+
version: 0.9.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jim Wise
|
@@ -36,7 +36,7 @@ dependencies:
|
|
36
36
|
description: |-
|
37
37
|
This is an all-ruby implementation of choose/fail nondeterministic
|
38
38
|
programming with branch cut, as described in Chapter 22 of Paul Graham's
|
39
|
-
<em>On Lisp</em>[1],
|
39
|
+
<em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2].
|
40
40
|
|
41
41
|
Due to Ruby containing a true call/cc, this is a much straighter port of
|
42
42
|
Paul Graham's scheme version of this code than his Common Lisp or my C
|
@@ -98,6 +98,6 @@ rubyforge_project: ambit
|
|
98
98
|
rubygems_version: 1.7.2
|
99
99
|
signing_key:
|
100
100
|
specification_version: 3
|
101
|
-
summary: This is an all-ruby implementation of choose/fail nondeterministic programming with branch cut, as described in Chapter 22 of Paul Graham's <em>On Lisp</em>[1],
|
101
|
+
summary: This is an all-ruby implementation of choose/fail nondeterministic programming with branch cut, as described in Chapter 22 of Paul Graham's <em>On Lisp</em>[1], or Section 4.3 of <em>SICP</em>[2]
|
102
102
|
test_files:
|
103
103
|
- test/test_ambit.rb
|