functional-ruby 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -126
  3. data/lib/functional.rb +4 -1
  4. data/lib/functional/utilities.rb +46 -0
  5. data/lib/functional/version.rb +1 -1
  6. data/lib/functional_ruby.rb +1 -1
  7. data/md/utilities.md +2 -0
  8. data/spec/functional/behavior_spec.rb +2 -2
  9. data/spec/functional/pattern_matching_spec.rb +2 -2
  10. data/spec/functional/utilities_spec.rb +131 -43
  11. data/spec/spec_helper.rb +1 -3
  12. metadata +3 -40
  13. data/lib/functional/agent.rb +0 -130
  14. data/lib/functional/all.rb +0 -13
  15. data/lib/functional/cached_thread_pool.rb +0 -122
  16. data/lib/functional/concurrency.rb +0 -35
  17. data/lib/functional/core.rb +0 -2
  18. data/lib/functional/event.rb +0 -53
  19. data/lib/functional/event_machine_defer_proxy.rb +0 -23
  20. data/lib/functional/fixed_thread_pool.rb +0 -89
  21. data/lib/functional/future.rb +0 -42
  22. data/lib/functional/global_thread_pool.rb +0 -3
  23. data/lib/functional/obligation.rb +0 -121
  24. data/lib/functional/promise.rb +0 -194
  25. data/lib/functional/thread_pool.rb +0 -61
  26. data/md/concurrency.md +0 -465
  27. data/md/future.md +0 -32
  28. data/md/obligation.md +0 -32
  29. data/md/promise.md +0 -220
  30. data/spec/functional/agent_spec.rb +0 -405
  31. data/spec/functional/cached_thread_pool_spec.rb +0 -112
  32. data/spec/functional/concurrency_spec.rb +0 -55
  33. data/spec/functional/event_machine_defer_proxy_spec.rb +0 -246
  34. data/spec/functional/event_spec.rb +0 -114
  35. data/spec/functional/fixed_thread_pool_spec.rb +0 -84
  36. data/spec/functional/future_spec.rb +0 -115
  37. data/spec/functional/obligation_shared.rb +0 -121
  38. data/spec/functional/promise_spec.rb +0 -310
  39. data/spec/functional/thread_pool_shared.rb +0 -209
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c798e8848a4a1a3e47077fa48ac65c0595df304
4
- data.tar.gz: 0785957a5566c7fe58c753d8a2c09b040e11a17c
3
+ metadata.gz: 7ebc0dab7cc6ee079416729c8cc131bf239ca2bb
4
+ data.tar.gz: 24b3193d7e6fef20addd8688ab372c104163edae
5
5
  SHA512:
6
- metadata.gz: 7e2bd7f3b530d2c95134733f2a275ed2eb5ea16a68aac88ae9bbc9f50a9391a277afbf1608b9b15e7a25df193179523f5b6da920751e5e64f5255841823ebc6e
7
- data.tar.gz: 46a8e971f0c9e39f4287c3b743495678975a7fac5f22dbb607b9ec10321e5e2c27ee120bcf67a6d8adde48d4a7b95b910f65a7be0fe38931481153bf0b7afecf
6
+ metadata.gz: 65b487a457f8b8a4dcb3adfe98e8429ae0184656d3ddf6292c515c598f4cb6e610f8aca4185950626bf4e67cda95a77eb081031caf5f7ea95ccf3592df6c9d0a
7
+ data.tar.gz: bbe8b613ee9ac7a4aa4ed6626a36a2bfc148e4ddc42ef5fd2f5be5703f74567beb15dd772d0b4e63156f6ca46accae1425dfdeac0a36d75a34a09aa4bceafc45
data/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # Functional Ruby [![Build Status](https://secure.travis-ci.org/jdantonio/functional-ruby.png)](https://travis-ci.org/jdantonio/functional-ruby?branch=master) [![Dependency Status](https://gemnasium.com/jdantonio/functional-ruby.png)](https://gemnasium.com/jdantonio/functional-ruby)
2
2
 
3
- A gem for adding Erlang, Clojure, and Go inspired concurrency and functional programming tools to Ruby.
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/master/frames)
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, concurrent programming language.
33
+ a highly performant, functional programming language.
31
34
 
32
35
  ### Goals
33
36
 
34
- My history with high-performance, highly-concurrent programming goes back to my days with C/C++.
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, Co, Clojure, and JavaScript have been implemented this far:
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. Becuase this gem includes multiple features
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/behavior'
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
- If you want everything you can do that, too:
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
- ### Pattern Matching (Erlang)
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
- ### Behavior (Erlang)
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
- ### Goroutine (Go)
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
 
@@ -1 +1,4 @@
1
- require 'functional/all'
1
+ require 'functional/behavior'
2
+ require 'functional/pattern_matching'
3
+ require 'functional/utilities'
4
+ require 'functional/version'
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Functional
2
- VERSION = '0.6.0'
2
+ VERSION = '0.7.0'
3
3
  end
@@ -1 +1 @@
1
- require 'functional/all'
1
+ require 'functional'
@@ -21,6 +21,8 @@ pp_s [1,2,3,4] #=> "[1, 2, 3, 4]\n" props to Rha7
21
21
 
22
22
  delta(-1, 1) #=> 2
23
23
  delta({count: -1}, {count: 1}){|item| item[:count]} #=> 2
24
+
25
+ repeatedly(10, 1){|previous| previous * 2 } #=> [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
24
26
  ```
25
27
 
26
28
  ## Copyright
@@ -107,7 +107,7 @@ describe '-behavior' do
107
107
 
108
108
  lambda {
109
109
  clazz.new
110
- }.should_not raise_error(BehaviorError)
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(BehaviorError)
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 = '1.9.2'
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(NoMethodError)
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 '#repl?' do
6
+ context '#delta' do
7
7
 
8
- before(:each) do
9
- @dollar_zero = $0
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
- after(:each) do
13
- $0 = @dollar_zero
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
- def set_dollar_zero(val)
17
- $0 = val
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 'recognizes IRB' do
21
- set_dollar_zero('irb')
22
- repl?.should be_true
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 'recognizes Pry' do
26
- set_dollar_zero('pry')
27
- repl?.should be_true
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 'recognizes Rails Console' do
31
- set_dollar_zero('script/rails')
32
- repl?.should be_true
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
- it 'recognizes Bundle Console' do
36
- set_dollar_zero('bin/bundle')
37
- repl?.should be_true
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 false when not in a REPL' do
41
- set_dollar_zero(__FILE__)
42
- repl?.should be_false
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(SecurityError)
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 '#delta' do
198
+ context '#repl?' do
117
199
 
118
- it 'computes the delta of two positive values' do
119
- delta(10.5, 5.0).should be_within(0.01).of(5.5)
200
+ before(:each) do
201
+ @dollar_zero = $0
120
202
  end
121
203
 
122
- it 'computes the delta of two negative values' do
123
- delta(-10.5, -5.0).should be_within(0.01).of(5.5)
204
+ after(:each) do
205
+ $0 = @dollar_zero
124
206
  end
125
207
 
126
- it 'computes the delta of a positive and negative value' do
127
- delta(10.5, -5.0).should be_within(0.01).of(15.5)
208
+ def set_dollar_zero(val)
209
+ $0 = val
128
210
  end
129
211
 
130
- it 'computes the delta of two positive values with a block' do
131
- v1 = {:count => 10.5}
132
- v2 = {:count => 5.0}
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 'computes the delta of two negative values with a block' do
137
- v1 = {:count => -10.5}
138
- v2 = {:count => -5.0}
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 'computes the delta of a positive and negative value with a block' do
143
- v1 = {:count => 10.5}
144
- v2 = {:count => -5.0}
145
- delta(v1, v2){|x| x[:count]}.should be_within(0.01).of(15.5)
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