functional-ruby 0.6.0 → 0.7.0
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.
- checksums.yaml +4 -4
- data/README.md +14 -126
- data/lib/functional.rb +4 -1
- data/lib/functional/utilities.rb +46 -0
- data/lib/functional/version.rb +1 -1
- data/lib/functional_ruby.rb +1 -1
- data/md/utilities.md +2 -0
- data/spec/functional/behavior_spec.rb +2 -2
- data/spec/functional/pattern_matching_spec.rb +2 -2
- data/spec/functional/utilities_spec.rb +131 -43
- data/spec/spec_helper.rb +1 -3
- metadata +3 -40
- data/lib/functional/agent.rb +0 -130
- data/lib/functional/all.rb +0 -13
- data/lib/functional/cached_thread_pool.rb +0 -122
- data/lib/functional/concurrency.rb +0 -35
- data/lib/functional/core.rb +0 -2
- data/lib/functional/event.rb +0 -53
- data/lib/functional/event_machine_defer_proxy.rb +0 -23
- data/lib/functional/fixed_thread_pool.rb +0 -89
- data/lib/functional/future.rb +0 -42
- data/lib/functional/global_thread_pool.rb +0 -3
- data/lib/functional/obligation.rb +0 -121
- data/lib/functional/promise.rb +0 -194
- data/lib/functional/thread_pool.rb +0 -61
- data/md/concurrency.md +0 -465
- data/md/future.md +0 -32
- data/md/obligation.md +0 -32
- data/md/promise.md +0 -220
- data/spec/functional/agent_spec.rb +0 -405
- data/spec/functional/cached_thread_pool_spec.rb +0 -112
- data/spec/functional/concurrency_spec.rb +0 -55
- data/spec/functional/event_machine_defer_proxy_spec.rb +0 -246
- data/spec/functional/event_spec.rb +0 -114
- data/spec/functional/fixed_thread_pool_spec.rb +0 -84
- data/spec/functional/future_spec.rb +0 -115
- data/spec/functional/obligation_shared.rb +0 -121
- data/spec/functional/promise_spec.rb +0 -310
- data/spec/functional/thread_pool_shared.rb +0 -209
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ebc0dab7cc6ee079416729c8cc131bf239ca2bb
|
4
|
+
data.tar.gz: 24b3193d7e6fef20addd8688ab372c104163edae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65b487a457f8b8a4dcb3adfe98e8429ae0184656d3ddf6292c515c598f4cb6e610f8aca4185950626bf4e67cda95a77eb081031caf5f7ea95ccf3592df6c9d0a
|
7
|
+
data.tar.gz: bbe8b613ee9ac7a4aa4ed6626a36a2bfc148e4ddc42ef5fd2f5be5703f74567beb15dd772d0b4e63156f6ca46accae1425dfdeac0a36d75a34a09aa4bceafc45
|
data/README.md
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# Functional Ruby [](https://travis-ci.org/jdantonio/functional-ruby?branch=master) [](https://gemnasium.com/jdantonio/functional-ruby)
|
2
2
|
|
3
|
-
A gem for adding Erlang, Clojure, and Go inspired
|
3
|
+
A gem for adding Erlang, Clojure, and Go inspired functional programming tools to Ruby.
|
4
|
+
|
5
|
+
*NOTE: As of version 0.7.0 the concurrency tools from this gem have been moved to the
|
6
|
+
[concurrent-ruby](https://github.com/jdantonio/concurrent-ruby) gem.*
|
4
7
|
|
5
8
|
The project is hosted on the following sites:
|
6
9
|
|
7
10
|
* [RubyGems project page](https://rubygems.org/gems/functional-ruby)
|
8
11
|
* [Source code on GitHub](https://github.com/jdantonio/functional-ruby)
|
9
|
-
* [YARD documentation on RubyDoc.info](http://rubydoc.info/github/jdantonio/functional-ruby/
|
12
|
+
* [YARD documentation on RubyDoc.info](http://rubydoc.info/github/jdantonio/functional-ruby/frames)
|
10
13
|
* [Continuous integration on Travis-CI](https://travis-ci.org/jdantonio/functional-ruby)
|
11
14
|
* [Dependency tracking on Gemnasium](https://gemnasium.com/jdantonio/functional-ruby)
|
12
15
|
* [Follow me on Twitter](https://twitter.com/jerrydantonio)
|
@@ -27,19 +30,11 @@ area. Ruby 2.0 is now a [relevant](https://blog.heroku.com/archives/2013/6/17/ru
|
|
27
30
|
platform for concurrent applications.
|
28
31
|
|
29
32
|
This gem is my small and humble attempt to help Ruby reach its full potential as
|
30
|
-
a highly performant, functional
|
33
|
+
a highly performant, functional programming language.
|
31
34
|
|
32
35
|
### Goals
|
33
36
|
|
34
|
-
My
|
35
|
-
I have the same scars as everyone else doing that kind of work with those languages.
|
36
|
-
I'm fascinated by modern concurrency patterns like [Actors](http://en.wikipedia.org/wiki/Actor_model),
|
37
|
-
[Agents](http://doc.akka.io/docs/akka/snapshot/java/agents.html), and
|
38
|
-
[Promises](http://promises-aplus.github.io/promises-spec/). I'm equally fascinated by languages
|
39
|
-
with strong concurrency support like [Erlang](http://www.erlang.org/doc/getting_started/conc_prog.html),
|
40
|
-
[Go](http://golang.org/doc/articles/concurrency_patterns.html), and
|
41
|
-
[Clojure](http://clojure.org/concurrent_programming) (I program with Erlang at work).
|
42
|
-
My goal is to implement those patterns in Ruby. Specifically:
|
37
|
+
My goal is to implement various functional programming patterns in Ruby. Specifically:
|
43
38
|
|
44
39
|
* Stay true to the spirit of the languages providing inspiration
|
45
40
|
* But implement in a way that makes sense for Ruby
|
@@ -51,12 +46,10 @@ My goal is to implement those patterns in Ruby. Specifically:
|
|
51
46
|
|
52
47
|
## Features (and Documentation)
|
53
48
|
|
54
|
-
Several features from Erlang,
|
49
|
+
Several features from Erlang, Go, and Clojure have been implemented thus far:
|
55
50
|
|
56
51
|
* Function overloading with Erlang-style [Pattern Matching](https://github.com/jdantonio/functional-ruby/blob/master/md/pattern_matching.md)
|
57
52
|
* Interface specifications with Erlang-style [Behavior](https://github.com/jdantonio/functional-ruby/blob/master/md/behavior.md)
|
58
|
-
* Chained asynchronous operations inspried by JavaScript [Promises](https://github.com/jdantonio/functional-ruby/blob/master/md/promise.md)
|
59
|
-
* Additional Clojure, Go, and Erlang inspired [Concurrency](https://github.com/jdantonio/functional-ruby/blob/master/md/concurrency.md)
|
60
53
|
* Several useful functional [Utilities](https://github.com/jdantonio/functional-ruby/blob/master/md/utilities.md)
|
61
54
|
|
62
55
|
### Is it any good?
|
@@ -85,30 +78,18 @@ gem 'functional-ruby'
|
|
85
78
|
|
86
79
|
and run `bundle install` from your shell.
|
87
80
|
|
88
|
-
Once you've installed the gem you must `require` it in your project
|
89
|
-
that not all users may want, several `require` options are available:
|
81
|
+
Once you've installed the gem you must `require` it in your project:
|
90
82
|
|
91
83
|
```ruby
|
92
|
-
require 'functional
|
93
|
-
require 'functional/behaviour' # alternate spelling
|
94
|
-
require 'functional/concurrency'
|
95
|
-
require 'functional/pattern_matching'
|
96
|
-
require 'functional/promise'
|
97
|
-
require 'functional/utilities'
|
84
|
+
require 'functional'
|
98
85
|
```
|
99
86
|
|
100
|
-
|
101
|
-
|
102
|
-
```ruby
|
103
|
-
require 'functional/all'
|
104
|
-
```
|
105
|
-
|
106
|
-
## Examples
|
87
|
+
### Examples
|
107
88
|
|
108
89
|
For complete examples, see the specific documentation linked above. Below are a
|
109
90
|
few examples to whet your appetite.
|
110
91
|
|
111
|
-
|
92
|
+
#### Pattern Matching (Erlang)
|
112
93
|
|
113
94
|
Documentation: [Pattern Matching](https://github.com/jdantonio/functional-ruby/blob/master/md/pattern_matching.md)
|
114
95
|
|
@@ -132,7 +113,7 @@ foo.greet(:male) #=> "Hello, sir!"
|
|
132
113
|
foo.greet(:female) #=> "Hello, ma'am!"
|
133
114
|
```
|
134
115
|
|
135
|
-
|
116
|
+
#### Behavior (Erlang)
|
136
117
|
|
137
118
|
Documentation: [Behavior](https://github.com/jdantonio/functional-ruby/blob/master/md/behavior.md)
|
138
119
|
|
@@ -160,100 +141,7 @@ foo.behaves_as?(:bogus) #=> false
|
|
160
141
|
'foo'.behaves_as? :gen_foo #=> false
|
161
142
|
```
|
162
143
|
|
163
|
-
|
164
|
-
|
165
|
-
```ruby
|
166
|
-
require 'functional/concurrency'
|
167
|
-
|
168
|
-
@expected = nil
|
169
|
-
go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
|
170
|
-
sleep(0.1)
|
171
|
-
@expected #=> [3, 2, 1]
|
172
|
-
```
|
173
|
-
|
174
|
-
### Agent (Clojure)
|
175
|
-
|
176
|
-
```ruby
|
177
|
-
require 'functional/agent'
|
178
|
-
# or
|
179
|
-
require 'functional/concurrency'
|
180
|
-
|
181
|
-
score = agent(10)
|
182
|
-
score.value #=> 10
|
183
|
-
|
184
|
-
score << proc{|current| current + 100 }
|
185
|
-
sleep(0.1)
|
186
|
-
score.value #=> 110
|
187
|
-
|
188
|
-
score << proc{|current| current * 2 }
|
189
|
-
sleep(0.1)
|
190
|
-
deref score #=> 220
|
191
|
-
|
192
|
-
score << proc{|current| current - 50 }
|
193
|
-
sleep(0.1)
|
194
|
-
score.value #=> 170
|
195
|
-
```
|
196
|
-
|
197
|
-
### Future (Clojure)
|
198
|
-
|
199
|
-
```ruby
|
200
|
-
require 'functional/future'
|
201
|
-
# or
|
202
|
-
require 'functional/concurrency'
|
203
|
-
|
204
|
-
count = future{ sleep(1); 10 }
|
205
|
-
count.state #=> :pending
|
206
|
-
# do stuff...
|
207
|
-
count.value #=> 10 (after blocking)
|
208
|
-
deref count #=> 10
|
209
|
-
```
|
210
|
-
|
211
|
-
### Promise (JavaScript)
|
212
|
-
|
213
|
-
* [Promises/A](http://wiki.commonjs.org/wiki/Promises/A)
|
214
|
-
* [Promises/A+](http://promises-aplus.github.io/promises-spec/)
|
215
|
-
|
216
|
-
```ruby
|
217
|
-
require 'functional/promise'
|
218
|
-
# or
|
219
|
-
require 'functional/concurrency'
|
220
|
-
|
221
|
-
p = promise("Jerry", "D'Antonio"){|a, b| "#{a} #{b}" }.
|
222
|
-
then{|result| "Hello #{result}." }.
|
223
|
-
rescue(StandardError){|ex| puts "Boom!" }.
|
224
|
-
then{|result| "#{result} Would you like to play a game?"}
|
225
|
-
sleep(1)
|
226
|
-
p.value #=> "Hello Jerry D'Antonio. Would you like to play a game?"
|
227
|
-
```
|
228
|
-
|
229
|
-
### Thread Pools
|
230
|
-
|
231
|
-
```ruby
|
232
|
-
require 'functional/fixed_thread_pool'
|
233
|
-
require 'functional/cached_thread_pool'
|
234
|
-
# or
|
235
|
-
require 'functional/concurrency'
|
236
|
-
|
237
|
-
pool = Functional::FixedThreadPool.new(10)
|
238
|
-
@expected = 0
|
239
|
-
pool.post{ sleep(0.5); @expected += 100 }
|
240
|
-
pool.post{ sleep(0.5); @expected += 100 }
|
241
|
-
pool.post{ sleep(0.5); @expected += 100 }
|
242
|
-
@expected #=> nil
|
243
|
-
sleep(1)
|
244
|
-
@expected #=> 300
|
245
|
-
|
246
|
-
pool = Functional::CachedThreadPool.new
|
247
|
-
@expected = 0
|
248
|
-
pool << proc{ sleep(0.5); @expected += 10 }
|
249
|
-
pool << proc{ sleep(0.5); @expected += 10 }
|
250
|
-
pool << proc{ sleep(0.5); @expected += 10 }
|
251
|
-
@expected #=> 0
|
252
|
-
sleep(1)
|
253
|
-
@expected #=> 30
|
254
|
-
```
|
255
|
-
|
256
|
-
### Utilities
|
144
|
+
#### Utilities
|
257
145
|
|
258
146
|
Documentation: [Utilities](https://github.com/jdantonio/functional-ruby/blob/master/md/utilities.md)
|
259
147
|
|
data/lib/functional.rb
CHANGED
data/lib/functional/utilities.rb
CHANGED
@@ -30,6 +30,52 @@ module Kernel
|
|
30
30
|
end
|
31
31
|
module_function :delta
|
32
32
|
|
33
|
+
# Perform an operation numerous times, passing the value of the
|
34
|
+
# previous iteration, and collecting the results into an array.
|
35
|
+
#
|
36
|
+
# @yield iterates over each element in the data set
|
37
|
+
# @yieldparam previous the initial value (or nil) for the first
|
38
|
+
# iteration then the value of the previous iteration for all
|
39
|
+
# subsequent iterations
|
40
|
+
#
|
41
|
+
# @param [Integer] count the number of times to perform the operation
|
42
|
+
# @param [Object] initial the initial value to pass to the first iteration
|
43
|
+
#
|
44
|
+
# @return [Array] the results of the iterations collected into an array
|
45
|
+
def repeatedly(count, initial = nil)
|
46
|
+
return [] if (count = count.to_i) == 0
|
47
|
+
return count.times.collect{ nil } unless block_given?
|
48
|
+
return count.times.collect do
|
49
|
+
initial = yield(initial)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
module_function :repeatedly
|
53
|
+
|
54
|
+
# Try an operation. If it fails (raises an exception), wait a second
|
55
|
+
# and try again. Try no more than the given number of times.
|
56
|
+
#
|
57
|
+
# @yield Tries the given block operation
|
58
|
+
#
|
59
|
+
# @param [Integer] tries The maximum number of times to attempt the operation.
|
60
|
+
# @param [Array] args Optional block arguments
|
61
|
+
#
|
62
|
+
# @return [Boolean] true if the operation succeeds on any attempt,
|
63
|
+
# false if none of the attempts are successful
|
64
|
+
def retro(tries, *args)
|
65
|
+
tries = tries.to_i
|
66
|
+
return false if tries == 0 || ! block_given?
|
67
|
+
yield(*args)
|
68
|
+
return true
|
69
|
+
rescue Exception
|
70
|
+
sleep(1)
|
71
|
+
if (tries = tries - 1) > 0
|
72
|
+
retry
|
73
|
+
else
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
module_function :retro
|
78
|
+
|
33
79
|
# Sandbox the given operation at a high $SAFE level.
|
34
80
|
#
|
35
81
|
# @param args [Array] zero or more arguments to pass to the block
|
data/lib/functional/version.rb
CHANGED
data/lib/functional_ruby.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'functional
|
1
|
+
require 'functional'
|
data/md/utilities.md
CHANGED
@@ -107,7 +107,7 @@ describe '-behavior' do
|
|
107
107
|
|
108
108
|
lambda {
|
109
109
|
clazz.new
|
110
|
-
}.should_not raise_error
|
110
|
+
}.should_not raise_error
|
111
111
|
end
|
112
112
|
|
113
113
|
it 'creates the object when function definitions match' do
|
@@ -120,7 +120,7 @@ describe '-behavior' do
|
|
120
120
|
|
121
121
|
lambda {
|
122
122
|
clazz.new
|
123
|
-
}.should_not raise_error
|
123
|
+
}.should_not raise_error
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
@@ -44,7 +44,7 @@ describe PatternMatching do
|
|
44
44
|
|
45
45
|
it 'can pattern match the constructor' do
|
46
46
|
|
47
|
-
unless RUBY_VERSION
|
47
|
+
unless RUBY_VERSION == '1.9.2'
|
48
48
|
subject.defn(:initialize, PatternMatching::UNBOUND, PatternMatching::UNBOUND, PatternMatching::UNBOUND) { 'three args' }
|
49
49
|
subject.defn(:initialize, PatternMatching::UNBOUND, PatternMatching::UNBOUND) { 'two args' }
|
50
50
|
subject.defn(:initialize, PatternMatching::UNBOUND) { 'one arg' }
|
@@ -152,7 +152,7 @@ describe PatternMatching do
|
|
152
152
|
|
153
153
|
lambda {
|
154
154
|
obj.foo
|
155
|
-
}.should_not raise_error
|
155
|
+
}.should_not raise_error
|
156
156
|
end
|
157
157
|
|
158
158
|
it 'does not accept any parameters' do
|
@@ -3,43 +3,125 @@ require 'fakefs/safe'
|
|
3
3
|
|
4
4
|
describe 'utilities' do
|
5
5
|
|
6
|
-
context '#
|
6
|
+
context '#delta' do
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
it 'computes the delta of two positive values' do
|
9
|
+
delta(10.5, 5.0).should be_within(0.01).of(5.5)
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
it 'computes the delta of two negative values' do
|
13
|
+
delta(-10.5, -5.0).should be_within(0.01).of(5.5)
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
it 'computes the delta of a positive and negative value' do
|
17
|
+
delta(10.5, -5.0).should be_within(0.01).of(15.5)
|
18
18
|
end
|
19
19
|
|
20
|
-
it '
|
21
|
-
|
22
|
-
|
20
|
+
it 'computes the delta of two positive values with a block' do
|
21
|
+
v1 = {:count => 10.5}
|
22
|
+
v2 = {:count => 5.0}
|
23
|
+
delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(5.5)
|
23
24
|
end
|
24
25
|
|
25
|
-
it '
|
26
|
-
|
27
|
-
|
26
|
+
it 'computes the delta of two negative values with a block' do
|
27
|
+
v1 = {:count => -10.5}
|
28
|
+
v2 = {:count => -5.0}
|
29
|
+
delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(5.5)
|
28
30
|
end
|
29
31
|
|
30
|
-
it '
|
31
|
-
|
32
|
-
|
32
|
+
it 'computes the delta of a positive and negative value with a block' do
|
33
|
+
v1 = {:count => 10.5}
|
34
|
+
v2 = {:count => -5.0}
|
35
|
+
delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(15.5)
|
33
36
|
end
|
37
|
+
end
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
|
39
|
+
context '#repeatedly' do
|
40
|
+
|
41
|
+
it 'returns an empty array when requested times is zero' do
|
42
|
+
expected = repeatedly(0){ 1 }
|
43
|
+
expected.should be_empty
|
38
44
|
end
|
39
45
|
|
40
|
-
it 'returns
|
41
|
-
|
42
|
-
|
46
|
+
it 'returns an array with all nil values when no block is given' do
|
47
|
+
expected = repeatedly(10)
|
48
|
+
expected.length.should eq 10
|
49
|
+
expected.each do |elem|
|
50
|
+
elem.should be_nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'iterates the requested number of times and puts the results into an array' do
|
55
|
+
expected = repeatedly(10){ 5 }
|
56
|
+
expected.length.should eq 10
|
57
|
+
expected.each do |elem|
|
58
|
+
elem.should eq 5
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'passes the initial value to the first iteration' do
|
63
|
+
@expected = nil
|
64
|
+
repeatedly(1,100){|previous| @expected = previous }
|
65
|
+
@expected.should eq 100
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'passes the result of each iteration to the next iteration' do
|
69
|
+
expected = repeatedly(10, 1){|previous| previous * 2 }
|
70
|
+
expected.should eq [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context '#retro' do
|
75
|
+
|
76
|
+
it 'does not run the block if requested times is zero' do
|
77
|
+
@expected = true
|
78
|
+
retro(0){ @expected = false }
|
79
|
+
@expected.should be_true
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'passes all arguments to the block' do
|
83
|
+
@expected = nil
|
84
|
+
retro(1, ?a, ?b, ?c){|*args| @expected = args }
|
85
|
+
@expected.should eq [?a, ?b, ?c]
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'calls the block once if the first pass is successful' do
|
89
|
+
@expected = 0
|
90
|
+
retro(5){ @expected += 1 }
|
91
|
+
@expected.should eq 1
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'calls the block more than once if the first pass fails' do
|
95
|
+
@expected = 0
|
96
|
+
retro(5) do
|
97
|
+
@expected += 1
|
98
|
+
raise StandardError if @expected < 3
|
99
|
+
end
|
100
|
+
@expected.should eq 3
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'calls the block no more than the requested number of times' do
|
104
|
+
@expected = 0
|
105
|
+
retro(5) do
|
106
|
+
@expected += 1
|
107
|
+
raise StandardError
|
108
|
+
end
|
109
|
+
@expected.should eq 5
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'returns true if any attempt succeeds' do
|
113
|
+
expected = retro(1){ nil }
|
114
|
+
expected.should be_true
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'returns false if all attempts fail' do
|
118
|
+
expected = retro(1){ raise StandardError }
|
119
|
+
expected.should be_false
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'returns false if no block is given' do
|
123
|
+
expected = retro(10)
|
124
|
+
expected.should eq false
|
43
125
|
end
|
44
126
|
end
|
45
127
|
|
@@ -48,7 +130,7 @@ describe 'utilities' do
|
|
48
130
|
it 'allows safe operations' do
|
49
131
|
lambda {
|
50
132
|
safe{ 1 + 1 }
|
51
|
-
}.should_not raise_error
|
133
|
+
}.should_not raise_error
|
52
134
|
end
|
53
135
|
|
54
136
|
it 'returns the value of the block when safe' do
|
@@ -113,37 +195,43 @@ describe 'utilities' do
|
|
113
195
|
end
|
114
196
|
end
|
115
197
|
|
116
|
-
context '#
|
198
|
+
context '#repl?' do
|
117
199
|
|
118
|
-
|
119
|
-
|
200
|
+
before(:each) do
|
201
|
+
@dollar_zero = $0
|
120
202
|
end
|
121
203
|
|
122
|
-
|
123
|
-
|
204
|
+
after(:each) do
|
205
|
+
$0 = @dollar_zero
|
124
206
|
end
|
125
207
|
|
126
|
-
|
127
|
-
|
208
|
+
def set_dollar_zero(val)
|
209
|
+
$0 = val
|
128
210
|
end
|
129
211
|
|
130
|
-
it '
|
131
|
-
|
132
|
-
|
133
|
-
delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(5.5)
|
212
|
+
it 'recognizes IRB' do
|
213
|
+
set_dollar_zero('irb')
|
214
|
+
repl?.should be_true
|
134
215
|
end
|
135
216
|
|
136
|
-
it '
|
137
|
-
|
138
|
-
|
139
|
-
delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(5.5)
|
217
|
+
it 'recognizes Pry' do
|
218
|
+
set_dollar_zero('pry')
|
219
|
+
repl?.should be_true
|
140
220
|
end
|
141
221
|
|
142
|
-
it '
|
143
|
-
|
144
|
-
|
145
|
-
|
222
|
+
it 'recognizes Rails Console' do
|
223
|
+
set_dollar_zero('script/rails')
|
224
|
+
repl?.should be_true
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'recognizes Bundle Console' do
|
228
|
+
set_dollar_zero('bin/bundle')
|
229
|
+
repl?.should be_true
|
146
230
|
end
|
147
|
-
end
|
148
231
|
|
232
|
+
it 'returns false when not in a REPL' do
|
233
|
+
set_dollar_zero(__FILE__)
|
234
|
+
repl?.should be_false
|
235
|
+
end
|
236
|
+
end
|
149
237
|
end
|