Guest User

Untitled

a guest
Mar 5th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.56 KB | None | 0 0
  1. Index: kernel/core/02range.rb
  2. ===================================================================
  3. --- kernel/core/02range.rb (revision 1374)
  4. +++ kernel/core/02range.rb (working copy)
  5. @@ -1,256 +0,0 @@
  6. -# Ryan Davis and Eric Hodel wrote this. They rock.
  7. -#
  8. -class Range
  9. -
  10. - include Enumerable
  11. -
  12. - ##
  13. - # call-seq:
  14. - # Range.new(start, end, exclusive=false) => range
  15. - #
  16. - # Constructs a range using the given <em>start</em> and <em>end</em>.
  17. - # If the third parameter is omitted or is <tt>false</tt>, the
  18. - # <em>range</em> will include the end object; otherwise, it will be
  19. - # excluded.
  20. -
  21. - def initialize(first, last, exclude_end=false)
  22. - @first = first
  23. - @last = last
  24. - @exclude_end = exclude_end
  25. - end
  26. -
  27. - ##
  28. - # call-seq:
  29. - # rng == obj => true or false
  30. - #
  31. - # Returns <tt>true</tt> only if <em>obj</em> is a Range, has
  32. - # equivalent beginning and end items (by comparing them with
  33. - # <tt>==</tt>), and has the same #exclude_end? setting as <i>rng</t>.
  34. - #
  35. - # (0..2) == (0..2) #=> true
  36. - # (0..2) == Range.new(0,2) #=> true
  37. - # (0..2) == (0...2) #=> false
  38. -
  39. - def ==(other)
  40. - return false unless Range === other
  41. - return self.first == other.first && self.last == other.last && self.exclude_end? == other.exclude_end?
  42. - end
  43. -
  44. - ##
  45. - # call-seq:
  46. - # rng === obj => true or false
  47. - # rng.member?(val) => true or false
  48. - # rng.include?(val) => true or false
  49. - #
  50. - # Returns <tt>true</tt> if <em>obj</em> is an element of <em>rng</em>,
  51. - # <tt>false</tt> otherwise. Conveniently, <tt>===</tt> is the
  52. - # comparison operator used by <tt>case</tt> statements.
  53. - #
  54. - # case 79
  55. - # when 1..50 then print "low\n"
  56. - # when 51..75 then print "medium\n"
  57. - # when 76..100 then print "high\n"
  58. - # end
  59. - #
  60. - # <em>produces:</em>
  61. - #
  62. - # high
  63. -
  64. - def ===(value)
  65. - if @first <= value then
  66. - if self.exclude_end? then
  67. - return true if value < @last
  68. - else
  69. - return true if value <= @last
  70. - end
  71. - end
  72. - return false
  73. - rescue
  74. - return false
  75. - end
  76. - alias_method :member?, :===
  77. - alias_method :include?, :===
  78. -
  79. - ##
  80. - # call-seq:
  81. - # rng.each {| i | block } => rng
  82. - #
  83. - # Iterates over the elements <em>rng</em>, passing each in turn to the
  84. - # block. You can only iterate if the start object of the range
  85. - # supports the <tt>succ</tt> method (which means that you can't
  86. - # iterate over ranges of <tt>Float</tt> objects).
  87. - #
  88. - # (10..15).each do |n|
  89. - # print n, ' '
  90. - # end
  91. - #
  92. - # <em>produces:</em>
  93. - #
  94. - # 10 11 12 13 14 15
  95. -
  96. - def each
  97. - first = self.first # dup?
  98. - last = self.last
  99. -
  100. - if Fixnum === first && Fixnum === last then
  101. - last -= 1 if self.exclude_end?
  102. - first.upto(last) { |i| yield(i) }
  103. - elsif String === first then
  104. - first.upto(last) do |s|
  105. - next if @exclude_end && s == last
  106. - yield(s)
  107. - end
  108. - else
  109. - current = first
  110. - if @exclude_end then
  111. - loop do
  112. - break if current == last
  113. - yield(current)
  114. - current = current.succ
  115. - end
  116. - else
  117. - loop do
  118. - yield(current)
  119. - break if current == last
  120. - current = current.succ
  121. - end
  122. - end
  123. - end
  124. - return self
  125. - end
  126. -
  127. - ##
  128. - # call-seq:
  129. - # rng.eql?(obj) => true or false
  130. - #
  131. - # Returns <tt>true</tt> only if <em>obj</em> is a Range, has
  132. - # equivalent beginning and end items (by comparing them with #eql?),
  133. - # and has the same #exclude_end? setting as <em>rng</em>.
  134. - #
  135. - # (0..2) == (0..2) #=> true
  136. - # (0..2) == Range.new(0,2) #=> true
  137. - # (0..2) == (0...2) #=> false
  138. -
  139. - def eql?(other)
  140. - return false unless Range === other
  141. - return self.first.eql?(other.first) &&
  142. - self.last.eql?(other.last) &&
  143. - self.exclude_end? == other.exclude_end?
  144. - end
  145. -
  146. - ##
  147. - # call-seq:
  148. - # rng.exclude_end? => true or false
  149. - #
  150. - # Returns <tt>true</tt> if <em>rng</em> excludes its end value.
  151. -
  152. - def exclude_end?
  153. - @exclude_end
  154. - end
  155. -
  156. - ##
  157. - # call-seq:
  158. - # rng.first => obj
  159. - # rng.begin => obj
  160. - #
  161. - # Returns the first object in <em>rng</em>.
  162. -
  163. - def first
  164. - @first
  165. - end
  166. - alias_method :begin, :first
  167. -
  168. - ##
  169. - # call-seq:
  170. - # rng.hash => fixnum
  171. - #
  172. - # Generate a hash value such that two ranges with the same start and
  173. - # end points, and the same value for the "exclude end" flag, generate
  174. - # the same hash value.
  175. -
  176. - def hash
  177. - excl = @exclude_end ? 1 : 0
  178. - hash = excl
  179. - hash ^= @first.hash << 1
  180. - hash ^= @last.hash << 9
  181. - hash ^= excl << 24;
  182. - return hash
  183. - end
  184. -
  185. - ##
  186. - # call-seq:
  187. - # rng.inspect => string
  188. - #
  189. - # Convert this range object to a printable form (using
  190. - # <tt>inspect</tt> to convert the start and end objects).
  191. -
  192. - def inspect
  193. - joiner = @exclude_end ? "..." : ".."
  194. - return "#{@first.inspect}#{joiner}#{@last.inspect}"
  195. - end
  196. -
  197. - ##
  198. - # call-seq:
  199. - # rng.end => obj
  200. - # rng.last => obj
  201. - #
  202. - # Returns the object that defines the end of <em>rng</em>.
  203. - #
  204. - # (1..10).end #=> 10
  205. - # (1...10).end #=> 10
  206. -
  207. - def last
  208. - return @last
  209. - end
  210. - alias_method :end, :last
  211. -
  212. - ##
  213. - # call-seq:
  214. - # rng.step(n=1) {| obj | block } => rng
  215. - #
  216. - # Iterates over <em>rng</em>, passing each <em>n</em>th element to the
  217. - # block. If the range contains numbers or strings, natural ordering is
  218. - # used. Otherwise <tt>step</tt> invokes <tt>succ</tt> to iterate
  219. - # through range elements. The following code uses class <tt>Xs</tt>,
  220. - # which is defined in the class-level documentation.
  221. - #
  222. - # range = Xs.new(1)..Xs.new(10)
  223. - # range.step(2) {|x| puts x}
  224. - # range.step(3) {|x| puts x}
  225. - #
  226. - # <em>produces:</em>
  227. - #
  228. - # 1 x
  229. - # 3 xxx
  230. - # 5 xxxxx
  231. - # 7 xxxxxxx
  232. - # 9 xxxxxxxxx
  233. - # 1 x
  234. - # 4 xxxx
  235. - # 7 xxxxxxx
  236. - # 10 xxxxxxxxxx
  237. -
  238. - def step(n=1)
  239. - if n == 1 then
  240. - each { |o| yield(o) }
  241. - else
  242. - counter = 0
  243. - each do |o|
  244. - yield(o) if counter % n == 0
  245. - counter += 1
  246. - end
  247. - end
  248. - end
  249. -
  250. - ##
  251. - # call-seq:
  252. - # rng.to_s => string
  253. - #
  254. - # Convert this range object to a printable form.
  255. -
  256. - def to_s
  257. - joiner = @exclude_end ? "..." : ".."
  258. - return "#{@first}#{joiner}#{@last}"
  259. - end
  260. -end
  261. -
  262. Index: kernel/core/01range.rb
  263. ===================================================================
  264. --- kernel/core/01range.rb (revision 1374)
  265. +++ kernel/core/01range.rb (working copy)
  266. @@ -1,5 +1,55 @@
  267. -# Ryan Davis and Eric Hodel wrote this. They rock.
  268. +##
  269. +# Comments borrowed from MRI Implementation
  270. #
  271. +# A <code>Range</code> represents an interval---a set of values with a
  272. +# start and an end. Ranges may be constructed using the
  273. +# <em>s</em><code>..</code><em>e</em> and
  274. +# <em>s</em><code>...</code><em>e</em> literals, or with
  275. +# <code>Range::new</code>. Ranges constructed using <code>..</code>
  276. +# run from the start to the end inclusively. Those created using
  277. +# <code>...</code> exclude the end value. When used as an iterator,
  278. +# ranges return each value in the sequence.
  279. +#
  280. +# (-1..-5).to_a #=> []
  281. +# (-5..-1).to_a #=> [-5, -4, -3, -2, -1]
  282. +# ('a'..'e').to_a #=> ["a", "b", "c", "d", "e"]
  283. +# ('a'...'e').to_a #=> ["a", "b", "c", "d"]
  284. +#
  285. +# Ranges can be constructed using objects of any type, as long as the
  286. +# objects can be compared using their <code><=></code> operator and
  287. +# they support the <code>succ</code> method to return the next object
  288. +# in sequence.
  289. +#
  290. +# class Xs # represent a string of 'x's
  291. +# include Comparable
  292. +# attr :length
  293. +# def initialize(n)
  294. +# @length = n
  295. +# end
  296. +# def succ
  297. +# Xs.new(@length + 1)
  298. +# end
  299. +# def <=>(other)
  300. +# @length <=> other.length
  301. +# end
  302. +# def to_s
  303. +# sprintf "%2d #{inspect}", @length
  304. +# end
  305. +# def inspect
  306. +# 'x'# @length
  307. +# end
  308. +# end
  309. +#
  310. +# r = Xs.new(3)..Xs.new(6) #=> xxx..xxxxxx
  311. +# r.to_a #=> [xxx, xxxx, xxxxx, xxxxxx]
  312. +# r.member?(Xs.new(5)) #=> true
  313. +#
  314. +# In the previous code example, class <code>Xs</code> includes the
  315. +# <code>Comparable</code> module. This is because
  316. +# <code>Enumerable#member?</code> checks for equality using
  317. +# <code>==</code>. Including <code>Comparable</code> ensures that the
  318. +# <code>==</code> method is defined in terms of the <code><=></code>
  319. +# method implemented in <code>Xs</code>.
  320. class Range
  321.  
  322. include Enumerable
  323. @@ -91,6 +141,10 @@
  324. def each
  325. first = self.first # dup?
  326. last = self.last
  327. +
  328. + unless first.respond_to? :succ
  329. + raise TypeError.new("can't iterate from #{first.class}")
  330. + end
  331.  
  332. if Fixnum === first && Fixnum === last then
  333. last -= 1 if self.exclude_end?
  334. @@ -231,8 +285,28 @@
  335. # 10 xxxxxxxxxx
  336.  
  337. def step(n=1)
  338. - if n == 1 then
  339. + first = self.first
  340. + last = self.last
  341. + n = n.to_f #people might not pass numbers in. This stops them.
  342. +
  343. + if n < 0
  344. + raise ArgumentError.new("step can't be negative.")
  345. + elsif n == 0
  346. + raise ArgumentError.new("step can't be 0.")
  347. + elsif n == 1 then
  348. each { |o| yield(o) }
  349. + elsif Numeric === first
  350. + if self.exclude_end?
  351. + while (first < last)
  352. + yield(first)
  353. + first += n
  354. + end
  355. + else
  356. + while (first <= last)
  357. + yield(first)
  358. + first += n
  359. + end
  360. + end
  361. else
  362. counter = 0
  363. each do |o|
  364. Index: spec/core/range_spec.rb
  365. ===================================================================
  366. --- spec/core/range_spec.rb (revision 1374)
  367. +++ spec/core/range_spec.rb (working copy)
  368. @@ -207,4 +207,25 @@
  369. a.should == [0.5, 1, 1.5,2]
  370. end
  371.  
  372. + specify "step should not allow negative numbers in stepsize" do
  373. + should_raise(ArgumentError) do
  374. + a = []
  375. + (-5..5).step(-2) { |x| a << x }
  376. + end
  377. + end
  378. +
  379. + specify "step should not allow zero in stepsize" do
  380. +
  381. + should_raise(ArgumentError) do
  382. + a = []
  383. + (-5..5).step(0) { |x| a << x }
  384. + end
  385. +
  386. + should_raise(ArgumentError) do
  387. + a = []
  388. + (-5.5..5.7).step(0.0) { |x| a << x }
  389. + end
  390. +
  391. + end
  392. +
  393. end
Add Comment
Please, Sign In to add comment