lazylist 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +6 -2
- data/GPL +7 -7
- data/Rakefile +48 -39
- data/VERSION +1 -1
- data/examples/examples.rb +18 -13
- data/examples/hamming.rb +9 -9
- data/examples/pi.rb +20 -17
- data/examples/sieve.rb +12 -11
- data/lib/lazylist.rb +112 -51
- data/tests/runner.rb +18 -0
- data/tests/test.rb +242 -220
- metadata +17 -13
data/CHANGES
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
2005-09-26 * 0.1.3 * Fixed some Ruby 1.9 incompatibilities.
|
2
|
+
* Added default arguments for drop&take.
|
3
|
+
* I've decided to pollute the Kernel module with the #list
|
4
|
+
method. Sorry, if you don't like it. ;)
|
1
5
|
2004-09-30 * 0.1.2 * Added combine method.
|
2
6
|
* The ref method now uses a hash to cache return values.
|
3
|
-
|
7
|
+
This is not what I would still call a list datastructure.
|
4
8
|
It increases memory consumption (as if that would matter
|
5
|
-
|
9
|
+
anymore), too. But it speeds up things a great deal, if
|
6
10
|
you persist on using indexes into a list.
|
7
11
|
* Rakefile added
|
8
12
|
* Supports Rubygems now
|
data/GPL
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
GNU GENERAL PUBLIC LICENSE
|
2
|
+
Version 2, June 1991
|
3
3
|
|
4
4
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
5
5
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
6
6
|
Everyone is permitted to copy and distribute verbatim copies
|
7
7
|
of this license document, but changing it is not allowed.
|
8
8
|
|
9
|
-
|
9
|
+
Preamble
|
10
10
|
|
11
11
|
The licenses for most software are designed to take away your
|
12
12
|
freedom to share and change it. By contrast, the GNU General Public
|
@@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all.
|
|
56
56
|
The precise terms and conditions for copying, distribution and
|
57
57
|
modification follow.
|
58
58
|
|
59
|
-
|
59
|
+
GNU GENERAL PUBLIC LICENSE
|
60
60
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
61
61
|
|
62
62
|
0. This License applies to any program or other work which contains
|
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
|
255
255
|
of preserving the free status of all derivatives of our free software and
|
256
256
|
of promoting the sharing and reuse of software generally.
|
257
257
|
|
258
|
-
|
258
|
+
NO WARRANTY
|
259
259
|
|
260
260
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
261
261
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
|
277
277
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
278
278
|
POSSIBILITY OF SUCH DAMAGES.
|
279
279
|
|
280
|
-
|
280
|
+
END OF TERMS AND CONDITIONS
|
281
281
|
|
282
|
-
|
282
|
+
How to Apply These Terms to Your New Programs
|
283
283
|
|
284
284
|
If you develop a new program, and you want it to be of the greatest
|
285
285
|
possible use to the public, the best way to achieve this is to make it
|
data/Rakefile
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# Rakefile for File::Tail -*- ruby -*-
|
2
|
-
|
3
1
|
require 'rake/gempackagetask'
|
4
2
|
require 'rbconfig'
|
5
3
|
|
@@ -8,64 +6,75 @@ include Config
|
|
8
6
|
PKG_NAME = 'lazylist'
|
9
7
|
PKG_VERSION = File.read('VERSION').chomp
|
10
8
|
PKG_FILES = Dir.glob("**/*").delete_if { |item|
|
11
|
-
|
9
|
+
item.include?("CVS") or item.include?("pkg")
|
12
10
|
}
|
13
11
|
|
12
|
+
desc "Run unit tests"
|
13
|
+
task(:test) do
|
14
|
+
cd 'tests' do
|
15
|
+
ruby %{-I../ext runner.rb}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
14
19
|
desc "Installing library"
|
15
20
|
task :install do
|
16
|
-
|
17
|
-
|
21
|
+
libdir = CONFIG["sitelibdir"]
|
22
|
+
install('lib/lazylist.rb', libdir)
|
18
23
|
end
|
19
24
|
|
20
|
-
|
25
|
+
desc "Creating documentation"
|
26
|
+
task :doc do
|
27
|
+
ruby 'make_doc.rb'
|
28
|
+
end
|
21
29
|
|
22
|
-
|
30
|
+
spec = Gem::Specification.new do |s|
|
31
|
+
#### Basic information.
|
23
32
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
33
|
+
s.name = 'lazylist'
|
34
|
+
s.version = PKG_VERSION
|
35
|
+
s.summary = "Implementation of lazy lists for Ruby"
|
36
|
+
s.description = ""
|
28
37
|
|
29
|
-
|
38
|
+
#### Dependencies and requirements.
|
30
39
|
|
31
|
-
|
32
|
-
|
40
|
+
#s.add_dependency('log4r', '> 1.0.4')
|
41
|
+
#s.requirements << ""
|
33
42
|
|
34
|
-
|
43
|
+
s.files = PKG_FILES
|
35
44
|
|
36
|
-
|
45
|
+
#### C code extensions.
|
37
46
|
|
38
|
-
|
47
|
+
#s.extensions << "ext/extconf.rb"
|
39
48
|
|
40
|
-
|
49
|
+
#### Load-time details: library and application (you will need one or both).
|
41
50
|
|
42
|
-
|
43
|
-
|
51
|
+
s.require_path = 'lib' # Use these for libraries.
|
52
|
+
s.autorequire = 'lazylist'
|
44
53
|
|
45
|
-
|
46
|
-
|
47
|
-
|
54
|
+
#s.bindir = "bin" # Use these for applications.
|
55
|
+
#s.executables = ["bla.rb"]
|
56
|
+
#s.default_executable = "bla.rb"
|
48
57
|
|
49
|
-
|
58
|
+
#### Documentation and testing.
|
50
59
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
60
|
+
s.has_rdoc = true
|
61
|
+
#s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
|
62
|
+
#s.rdoc_options <<
|
63
|
+
# '--title' << 'Rake -- Ruby Make' <<
|
64
|
+
# '--main' << 'README' <<
|
65
|
+
# '--line-numbers'
|
66
|
+
s.test_files << 'tests/test.rb'
|
58
67
|
|
59
|
-
|
68
|
+
#### Author and project details.
|
60
69
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
70
|
+
s.author = "Florian Frank"
|
71
|
+
s.email = "flori@ping.de"
|
72
|
+
s.homepage = "http://lazylist.rubyforge.org"
|
73
|
+
s.rubyforge_project = "lazylist"
|
65
74
|
end
|
66
75
|
|
67
76
|
Rake::GemPackageTask.new(spec) do |pkg|
|
68
|
-
|
69
|
-
|
77
|
+
pkg.need_tar = true
|
78
|
+
pkg.package_files += PKG_FILES
|
70
79
|
end
|
71
|
-
|
80
|
+
# vim: set et sw=2 ts=2:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.3
|
data/examples/examples.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
require 'lazylist'
|
2
2
|
|
3
|
-
puts "Random number lazy list"
|
4
|
-
rand
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
puts "Random number lazy list (infinite)"
|
4
|
+
def rand(s = 666)
|
5
|
+
current = ((s * 1103515245 + 12345) / 65536) % 32768
|
6
|
+
list(current) { rand(current) }
|
7
|
+
end
|
8
|
+
r = rand(666)
|
8
9
|
r.each(10) { |x| print x, " " } ; puts
|
10
|
+
dice = rand(666).mapper { |x| 1 + x % 6 }
|
11
|
+
dice.each(10) { |x| print x, " " } ; puts
|
12
|
+
coin = rand(666).mapper { |x| x % 2 == 0 ? :head : :tail }
|
13
|
+
coin.each(10) { |x| print x, " " } ; puts
|
9
14
|
|
10
|
-
puts "Prime number lazy list with filter"
|
15
|
+
puts "Prime number lazy list with filter (10000..1000000)"
|
11
16
|
prime = LazyList[10000..1000000].filter do |x|
|
12
|
-
|
17
|
+
not (2..Math.sqrt(x).to_i).find { |d| x % d == 0 }
|
13
18
|
end
|
14
19
|
prime.each(10) { |x| print x, " " } ; puts
|
15
20
|
p prime[1]
|
@@ -26,8 +31,8 @@ hailstone = LazyList.iterate(7) { |x| x % 2 == 0 ? x / 2 : 3 * x + 1 }
|
|
26
31
|
hailstone.each(20) { |x| print x, " " } ; puts
|
27
32
|
terras = LazyList.iterate(7) { |x| x % 2 == 0 ? x / 2 : (3 * x + 1) / 2 }
|
28
33
|
terras.each(20) { |x| print x, " " } ; puts
|
29
|
-
wolfram = LazyList.iterate(
|
30
|
-
|
34
|
+
wolfram = LazyList.iterate(1) do |x|
|
35
|
+
((3.0 / 2) * (x % 2 == 0 ? x : x + 1)).to_i
|
31
36
|
end
|
32
37
|
wolfram.each(15) { |x| print x, " " } ; puts
|
33
38
|
puts
|
@@ -42,7 +47,7 @@ puts "Sum up odd numbers lazylist to get a squares stream"
|
|
42
47
|
odd = LazyList.tabulate(1) { |x| 2 * x - 1 }
|
43
48
|
puts odd
|
44
49
|
squares = LazyList.tabulate(0) do |x|
|
45
|
-
|
50
|
+
(0..x).inject(0) { |s, i| s + odd[i] }
|
46
51
|
end
|
47
52
|
puts squares
|
48
53
|
squares.each(10) { |x| print x, " " } ; puts
|
@@ -53,12 +58,12 @@ puts
|
|
53
58
|
puts "Lazy lists from io objects"
|
54
59
|
me = LazyList.io(File.new($0)) { |io| io.readline }
|
55
60
|
me.each(6) { |line| puts line }
|
56
|
-
p me[
|
61
|
+
p me[60]
|
57
62
|
puts me.length
|
58
63
|
puts
|
59
64
|
|
60
65
|
me = LazyList[File.new($0)]
|
61
66
|
me.each(6) { |line| puts line }
|
62
|
-
p me[
|
67
|
+
p me[66]
|
63
68
|
puts me.length
|
64
|
-
|
69
|
+
# vim: set et sw=2 ts=2:
|
data/examples/hamming.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
require 'lazylist'
|
2
2
|
|
3
|
-
# Computes the hamming sequence: that is the sequence of natural numbers that
|
4
|
-
# are
|
5
|
-
hamming =
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
# Computes the hamming sequence: that is the sequence of natural numbers, that
|
4
|
+
# are multiples of 2, 3, and 5.
|
5
|
+
hamming = list(1) do
|
6
|
+
hamming.mapper { |x| 2 * x }.merge(
|
7
|
+
hamming.mapper { |x| 3 * x }.merge(
|
8
|
+
hamming.mapper { |x| 5 * x }))
|
9
9
|
end
|
10
10
|
|
11
11
|
max = (ARGV.shift || 100).to_i
|
12
12
|
hamming.each(max) do |x|
|
13
|
-
|
14
|
-
|
13
|
+
print x, " "
|
14
|
+
STDOUT.flush
|
15
15
|
end
|
16
16
|
puts
|
17
17
|
print hamming[1000], ", ", hamming[1001], "\n"
|
18
|
-
|
18
|
+
# vim: set et sw=2 ts=2:
|
data/examples/pi.rb
CHANGED
@@ -9,24 +9,27 @@ require 'lazylist'
|
|
9
9
|
#
|
10
10
|
|
11
11
|
def f(q,r,t, k)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
n = (3 * q + r) / t
|
13
|
+
if n == (4 * q + r) / t
|
14
|
+
list(n) { f(10 * q, 10 * (r - n * t), t, k) }
|
15
|
+
else
|
16
|
+
f(q * k, q * (4 * k + 2) + r * (2 * k + 1), t * (2 * k + 1), k + 1)
|
17
|
+
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
pi = f(1, 0, 1, 1) # Setup my lazy list
|
22
|
-
sum = pi[0, 1000].inject(0) do |s, i| s += i end
|
23
|
-
puts "Sum of the first 1000 digitis of pi: #{sum}"
|
24
|
-
puts "500th digit using memoized computation: #{pi[499]}"
|
20
|
+
PI = f(1, 0, 1, 1) # Setup my lazy list
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
if $0 == __FILE__
|
23
|
+
max = ARGV.empty? ? nil : ARGV.shift.to_i
|
24
|
+
sum = PI[0, 1000].inject(0) do |s, i| s += i end
|
25
|
+
puts "Sum of the first 1000 digitis of pi: #{sum}"
|
26
|
+
puts "500th digit using memoized computation: #{PI[499]}"
|
27
|
+
|
28
|
+
puts "Printing #{max ? "the first #{max}" : "all the "} digits of pi:"
|
29
|
+
PI.each!(max) do |x|
|
30
|
+
STDOUT.print x
|
31
|
+
STDOUT.flush
|
32
|
+
end
|
33
|
+
puts
|
30
34
|
end
|
31
|
-
|
32
|
-
# vim: set noet sw=4 ts=4:
|
35
|
+
# vim: set et sw=2 ts=2:
|
data/examples/sieve.rb
CHANGED
@@ -3,20 +3,21 @@ require 'lazylist'
|
|
3
3
|
# Sieve or Eratosthenes with filters on Lazy Lists. It has a very nice
|
4
4
|
# notation, but is a real memory and cpu hog. Enjoy!
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
LazyList.new(head) do
|
10
|
-
tail.filter { |x| x % head != 0 }.prime_filter
|
11
|
-
end
|
12
|
-
end
|
6
|
+
def from(n = 0)
|
7
|
+
list(n) { from(n + 1) }
|
8
|
+
end
|
13
9
|
|
10
|
+
def primes(l = from(2))
|
11
|
+
current, rest = l.head, l.tail
|
12
|
+
list(current) do
|
13
|
+
primes rest.filter { |x| (x % current) != 0 }
|
14
|
+
end
|
14
15
|
end
|
15
16
|
|
16
17
|
max = (ARGV.shift || 100).to_i
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
primes.each(max) do |x|
|
19
|
+
print x, " "
|
20
|
+
STDOUT.flush
|
20
21
|
end
|
21
22
|
puts
|
22
|
-
|
23
|
+
# vim: set et sw=2 ts=2:
|
data/lib/lazylist.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
# = lazylist.rb - Implementation of lazy lists for Ruby
|
2
2
|
#
|
3
|
-
# == Author
|
4
|
-
#
|
5
|
-
# Florian Frank mailto:flori@ping.de
|
6
|
-
#
|
7
3
|
# == Description
|
8
4
|
#
|
9
5
|
# This class implements lazy lists (or streams) for Ruby. Such lists avoid the
|
@@ -12,6 +8,26 @@
|
|
12
8
|
# that hasn't been used yet is calculated on the fly and saved into the list.
|
13
9
|
# A value which is used for a second time is computed only once and just read
|
14
10
|
# out of memory for the second usage.
|
11
|
+
#
|
12
|
+
# == Author
|
13
|
+
#
|
14
|
+
# Florian Frank mailto:flori@ping.de
|
15
|
+
#
|
16
|
+
# == License
|
17
|
+
#
|
18
|
+
# This is free software; you can redistribute it and/or modify it under the
|
19
|
+
# terms of the GNU General Public License Version 2 as published by the Free
|
20
|
+
# Software Foundation: www.gnu.org/copyleft/gpl.html
|
21
|
+
#
|
22
|
+
# == Download
|
23
|
+
#
|
24
|
+
# The latest version of this library can be downloaded at
|
25
|
+
#
|
26
|
+
# * http://rubyforge.org/frs?group_id=394
|
27
|
+
#
|
28
|
+
# Online Documentation should be located at
|
29
|
+
#
|
30
|
+
# * http://lazylist.rubyforge.org
|
15
31
|
#
|
16
32
|
# == Example
|
17
33
|
#
|
@@ -30,7 +46,7 @@
|
|
30
46
|
#
|
31
47
|
# sq.each { |x| puts x }
|
32
48
|
#
|
33
|
-
# Notice that calls to each will not return if applied to infinite
|
49
|
+
# Notice that calls to each will not return if applied to infinite lazy lists.
|
34
50
|
#
|
35
51
|
# You can also use indices on lazy lists to get the values at a certain range:
|
36
52
|
#
|
@@ -82,11 +98,19 @@ class LazyList
|
|
82
98
|
# #pop and #empty? methods. It's used as a wrapper to encapsulate
|
83
99
|
# enumerables in LazyLists.
|
84
100
|
class ReadQueue
|
85
|
-
|
86
101
|
# Creates an ReadQueue object from an enumerable.
|
87
102
|
def initialize(enumerable)
|
88
103
|
@enumerable = enumerable
|
89
|
-
|
104
|
+
@break = proc {}
|
105
|
+
@enumerable.each do |x|
|
106
|
+
@current = x
|
107
|
+
callcc do |@continue|
|
108
|
+
@break.call
|
109
|
+
return
|
110
|
+
end
|
111
|
+
end
|
112
|
+
@continue = false
|
113
|
+
@break.call
|
90
114
|
end
|
91
115
|
|
92
116
|
# Extracts the top element from the queue or nil if the queue is
|
@@ -101,42 +125,45 @@ class LazyList
|
|
101
125
|
def empty?
|
102
126
|
@continue == false
|
103
127
|
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def prepare
|
108
|
-
@break = lambda {}
|
109
|
-
@enumerable.each do |x|
|
110
|
-
@current = x
|
111
|
-
callcc do |@continue|
|
112
|
-
@break.call
|
113
|
-
return
|
114
|
-
end
|
115
|
-
end
|
116
|
-
@continue = false
|
117
|
-
@break.call
|
118
|
-
end
|
119
|
-
|
120
128
|
end
|
121
129
|
|
122
|
-
include Enumerable
|
130
|
+
include Enumerable
|
123
131
|
|
124
132
|
# Exceptions raised by the LazyList implementation.
|
125
133
|
class Exception < ::Exception; end
|
126
134
|
|
135
|
+
# Returns a new LazyList, unless head and tail are nil. In the latter case
|
136
|
+
# LazyList::Empty is returned.
|
137
|
+
def self.new(head, tail = nil, &promise)
|
138
|
+
if head.nil? and tail.nil?
|
139
|
+
if LazyList.const_defined?(:Empty)
|
140
|
+
Empty
|
141
|
+
else
|
142
|
+
super
|
143
|
+
end
|
144
|
+
else
|
145
|
+
super
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
127
149
|
# Creates a new LazyList element. The tail can be given either as
|
128
150
|
# second argument or as block.
|
129
|
-
def initialize(head, tail = nil, &
|
151
|
+
def initialize(head, tail = nil, &promise)
|
130
152
|
@ref_cache = {}
|
131
153
|
if tail
|
132
|
-
|
133
|
-
|
154
|
+
promise and
|
155
|
+
raise LazyList::Exception,
|
156
|
+
"Use block xor second argument for constructor"
|
134
157
|
@head, @tail = head, tail
|
135
|
-
elsif
|
136
|
-
@head, @tail = head,
|
158
|
+
elsif promise
|
159
|
+
@head, @tail = head, promise
|
137
160
|
end
|
138
161
|
end
|
139
162
|
|
163
|
+
# Denotes the empty LazyList which is a guard at the end of finite
|
164
|
+
# LazyLists.
|
165
|
+
Empty = new(nil, nil)
|
166
|
+
|
140
167
|
# Returns the value of this element.
|
141
168
|
attr_accessor :head
|
142
169
|
protected :head=
|
@@ -148,25 +175,21 @@ class LazyList
|
|
148
175
|
# Returns the next element by computing its value if necessary.
|
149
176
|
def tail
|
150
177
|
if @tail.is_a? Proc
|
151
|
-
@tail = @tail[@head]
|
178
|
+
@tail = @tail[@head] || Empty
|
152
179
|
end
|
153
180
|
@tail
|
154
181
|
end
|
155
182
|
|
156
|
-
# Returns the tail of this list without
|
183
|
+
# Returns the tail of this list without evaluating.
|
157
184
|
def peek_tail
|
158
185
|
@tail
|
159
186
|
end
|
160
187
|
protected :peek_tail
|
161
188
|
|
162
|
-
# Denotes the empty LazyList which is a guard at the end of finite
|
163
|
-
# LazyLists.
|
164
|
-
Empty = new(nil, nil)
|
165
|
-
|
166
189
|
# Identity lambda expression, mostly used as a default.
|
167
190
|
Identity = lambda { |x| x }
|
168
191
|
|
169
|
-
# Returns a
|
192
|
+
# Returns a LazyList which is generated by LazyList.from_enum or
|
170
193
|
# LazyList.span. (See below.)
|
171
194
|
def self.[](a, n = nil)
|
172
195
|
if n
|
@@ -176,12 +199,12 @@ class LazyList
|
|
176
199
|
end
|
177
200
|
end
|
178
201
|
|
179
|
-
# Generates a
|
202
|
+
# Generates a LazyList from any data structure e which
|
180
203
|
# responds to the #each method.
|
181
204
|
def self.from_enum(e)
|
182
205
|
oq = ReadQueue.new(e)
|
183
206
|
return Empty if oq.empty?
|
184
|
-
next_top =
|
207
|
+
next_top = proc do
|
185
208
|
if oq.empty?
|
186
209
|
Empty
|
187
210
|
else
|
@@ -192,7 +215,7 @@ class LazyList
|
|
192
215
|
end
|
193
216
|
|
194
217
|
# Generates a finite LazyList beginning with element a and spanning
|
195
|
-
# n elements. The
|
218
|
+
# n elements. The data structure members have to support the
|
196
219
|
# successor method succ.
|
197
220
|
def self.span(a, n)
|
198
221
|
if n > 0
|
@@ -205,14 +228,14 @@ class LazyList
|
|
205
228
|
# Generates a LazyList which tabulates every element beginning with n
|
206
229
|
# and succeding with succ by calling the Proc object f or the given block.
|
207
230
|
# If none is given the identity function is computed instead.
|
208
|
-
def self.tabulate(n, &f)
|
231
|
+
def self.tabulate(n = 0, &f)
|
209
232
|
f = Identity unless f
|
210
233
|
new(f[n]) { tabulate(n.succ, &f) }
|
211
234
|
end
|
212
235
|
|
213
236
|
# Generates a LazyList which iterates over its previous values
|
214
237
|
# computing something like: f(i), f(f(i)), f(f(f(i))), ...
|
215
|
-
def self.iterate(i, &f)
|
238
|
+
def self.iterate(i = 0, &f)
|
216
239
|
new(i) { iterate(f[i], &f) }
|
217
240
|
end
|
218
241
|
|
@@ -330,7 +353,7 @@ class LazyList
|
|
330
353
|
end
|
331
354
|
|
332
355
|
# Takes the next n elements and returns them as an array.
|
333
|
-
def take(n)
|
356
|
+
def take(n = 1)
|
334
357
|
result = []
|
335
358
|
each(n) { |x| result << x }
|
336
359
|
result
|
@@ -338,7 +361,7 @@ class LazyList
|
|
338
361
|
|
339
362
|
# Takes the next n elements and returns them as an array. It destroys these
|
340
363
|
# elements in the LazyList.
|
341
|
-
def take!(n)
|
364
|
+
def take!(n = 1)
|
342
365
|
result = []
|
343
366
|
each!(n) { |x| result << x }
|
344
367
|
result
|
@@ -346,13 +369,13 @@ class LazyList
|
|
346
369
|
|
347
370
|
# Drops the next n elements and returns the rest of this LazyList. n
|
348
371
|
# defaults to 1.
|
349
|
-
def drop(n)
|
372
|
+
def drop(n = 1)
|
350
373
|
each(n) { }
|
351
374
|
end
|
352
375
|
|
353
376
|
# Drops the next n elements, destroys them in the LazyList and
|
354
377
|
# returns the rest of this LazyList.
|
355
|
-
def drop!(n)
|
378
|
+
def drop!(n = 1)
|
356
379
|
each!(n) { }
|
357
380
|
end
|
358
381
|
|
@@ -366,31 +389,69 @@ class LazyList
|
|
366
389
|
|
367
390
|
# Returns true if this is the empty LazyList.
|
368
391
|
def empty?
|
369
|
-
self
|
392
|
+
self.equal? Empty
|
370
393
|
end
|
371
394
|
|
395
|
+
# Returns true, if this lazy list and the other lazy list consist of only
|
396
|
+
# equal elements. This is only sensible, if the lazy lists are finite and you
|
397
|
+
# can spare the memory.
|
398
|
+
def eql?(other)
|
399
|
+
other.is_a? self.class or return false
|
400
|
+
size == other.size or return false
|
401
|
+
zip(other) { |x,y| x == y or return false }
|
402
|
+
true
|
403
|
+
end
|
404
|
+
alias == eql?
|
405
|
+
|
372
406
|
# Inspects the list as far as it has been computed by returning
|
373
407
|
# a string of the form [1, 2, 3,... ].
|
374
408
|
def inspect
|
375
409
|
result = "["
|
376
410
|
s = self
|
377
411
|
until s.empty?
|
378
|
-
|
379
|
-
|
412
|
+
pt = s.peek_tail
|
413
|
+
case
|
414
|
+
when pt.equal?(Empty) # to avoid calling == on pt
|
380
415
|
result << s.head.inspect
|
381
416
|
break
|
382
|
-
when Proc
|
417
|
+
when Proc === pt
|
383
418
|
result << s.head.inspect << ",... "
|
384
419
|
break
|
385
420
|
else
|
386
|
-
|
387
|
-
|
421
|
+
t = s.tail
|
422
|
+
if t.equal? self
|
423
|
+
result << s.head.inspect << ",... "
|
424
|
+
break
|
425
|
+
else
|
426
|
+
result << s.head.inspect << ", "
|
427
|
+
s = t
|
428
|
+
end
|
388
429
|
end
|
389
430
|
end
|
390
431
|
result << "]"
|
391
432
|
end
|
392
433
|
|
393
434
|
alias to_s inspect
|
435
|
+
end
|
394
436
|
|
437
|
+
module Kernel
|
438
|
+
# A method to improve the user friendliness for creating new lazy lists, that
|
439
|
+
# cannot be described well with LazyList#iterate or LazyList#tabulate.
|
440
|
+
#
|
441
|
+
# - list without any arguments, returns the empty lazy list LazyList::Empty.
|
442
|
+
# - list(x) returns the lazy list with only the element x as a member.
|
443
|
+
# - list(x) { l } returns the lazy list with the element x as a head
|
444
|
+
# element, and that is continued with the lazy list l as tail. To define an
|
445
|
+
# infinite lazy list of 1s you can do: ones = list(1) { ones }.
|
446
|
+
def list(value = LazyList::Empty, &promise)
|
447
|
+
if block_given?
|
448
|
+
LazyList.new(value, &promise)
|
449
|
+
elsif value.equal? LazyList::Empty
|
450
|
+
value
|
451
|
+
else
|
452
|
+
LazyList.new(value) { LazyList::Empty }
|
453
|
+
end
|
454
|
+
end
|
395
455
|
end
|
456
|
+
|
396
457
|
# vim: set et sw=2 ts=2:
|
data/tests/runner.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit/ui/console/testrunner'
|
4
|
+
require 'test/unit/testsuite'
|
5
|
+
$:.unshift File.expand_path(File.dirname($0))
|
6
|
+
$:.unshift 'lib'
|
7
|
+
$:.unshift '../lib'
|
8
|
+
#require 'coverage'
|
9
|
+
require 'test'
|
10
|
+
|
11
|
+
class TS_AllTests
|
12
|
+
def self.suite
|
13
|
+
suite = Test::Unit::TestSuite.new
|
14
|
+
suite << TC_LazyList.suite
|
15
|
+
end
|
16
|
+
end
|
17
|
+
Test::Unit::UI::Console::TestRunner.run(TS_AllTests)
|
18
|
+
# vim: set et sw=2 ts=2:
|
data/tests/test.rb
CHANGED
@@ -5,231 +5,253 @@ require 'lazylist'
|
|
5
5
|
require 'tempfile'
|
6
6
|
|
7
7
|
class MyEnum
|
8
|
+
include Enumerable
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@n = n
|
13
|
-
end
|
14
|
-
|
15
|
-
def each(&block) (1..@n).each(&block) end
|
10
|
+
def initialize(n)
|
11
|
+
@n = n
|
12
|
+
end
|
16
13
|
|
14
|
+
def each(&block)
|
15
|
+
(1..@n).each(&block)
|
16
|
+
end
|
17
17
|
end
|
18
18
|
|
19
19
|
class TC_LazyList < Test::Unit::TestCase
|
20
|
+
def setup
|
21
|
+
@strings = LazyList.tabulate("a")
|
22
|
+
@natural = LazyList.tabulate(1)
|
23
|
+
@ones = LazyList.iterate(1) { 1 }
|
24
|
+
@oddp = lambda { |x| x % 2 == 1 }
|
25
|
+
@odd = @natural.filter(&@oddp)
|
26
|
+
@evenp = lambda { |x| x % 2 == 0 }
|
27
|
+
@boolean = @natural.mapper { |x| x % 2 == 0}
|
28
|
+
@even = @natural.filter(&@evenp)
|
29
|
+
@finite_inner0 = MyEnum.new(0)
|
30
|
+
@finite0 = LazyList[@finite_inner0]
|
31
|
+
@finite_inner1 = MyEnum.new(1)
|
32
|
+
@finite1 = LazyList[@finite_inner1]
|
33
|
+
@finite_inner10 = MyEnum.new(10)
|
34
|
+
@finite10 = LazyList[@finite_inner10]
|
35
|
+
@finite_span = LazyList.span("A", 10)
|
36
|
+
@finite_span_generated = ("A".."J").to_a
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_constructor
|
40
|
+
ll1 = LazyList.new(:foo, LazyList::Empty)
|
41
|
+
assert(!ll1.empty?)
|
42
|
+
ll2 = LazyList.new(:foo) { Empty }
|
43
|
+
assert(!ll2.empty?)
|
44
|
+
assert_raises(LazyList::Exception) do
|
45
|
+
ll3 = LazyList.new(:foo, :argh) { Empty }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_read_queue
|
50
|
+
@read_queue0 = LazyList::ReadQueue.new(1..0)
|
51
|
+
@read_queue1 = LazyList::ReadQueue.new(1..1)
|
52
|
+
@read_queue10 = LazyList::ReadQueue.new(1..10)
|
53
|
+
assert(@read_queue0.empty?)
|
54
|
+
assert_equal(nil, @read_queue0.pop)
|
55
|
+
assert(!@read_queue1.empty?)
|
56
|
+
assert_equal(1, @read_queue1.pop)
|
57
|
+
assert(!@read_queue10.empty?)
|
58
|
+
for i in 1..10 do
|
59
|
+
assert_equal(i, @read_queue10.pop)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_finite
|
64
|
+
assert_equal(@finite_inner0.to_a, @finite0.to_a)
|
65
|
+
assert_equal(@finite_inner1.to_a, @finite1.to_a)
|
66
|
+
assert_equal(@finite_inner10.to_a, @finite10.to_a)
|
67
|
+
assert_equal(@finite_span_generated, @finite_span.to_a)
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_size
|
71
|
+
assert_equal(0, @finite0.size)
|
72
|
+
assert_equal(1, @finite1.size)
|
73
|
+
assert_equal(10, @finite10.size)
|
74
|
+
assert_equal(10, @finite_span.size)
|
75
|
+
assert_equal(0, @finite0.length)
|
76
|
+
assert_equal(1, @finite1.length)
|
77
|
+
assert_equal(10, @finite10.length)
|
78
|
+
assert_equal(10, @finite_span.length)
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_filter
|
82
|
+
assert_equal(1, @odd[0])
|
83
|
+
assert_equal(3, @odd[1])
|
84
|
+
assert_equal(5, @odd[2])
|
85
|
+
assert_equal((1..19).select(&@oddp), @odd[0, 10])
|
86
|
+
assert_equal((1..10).to_a, @natural[0, 10])
|
87
|
+
assert_equal([ 1 ] * 10, @ones[0, 10].to_a)
|
88
|
+
ends_with_a = @strings.filter { |x| x[-1] == ?a }
|
89
|
+
assert(ends_with_a[0, 27] ==
|
90
|
+
[ "a", ("a".."z").map { |x| x + "a" } ].flatten)
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_map
|
94
|
+
id = @natural.mapper
|
95
|
+
assert_equal(1, id[0])
|
96
|
+
assert_equal(2, id[1])
|
97
|
+
assert_equal(3, id[2])
|
98
|
+
assert_equal((1..10).to_a, id[0, 10])
|
99
|
+
assert_equal((1..10).to_a, @natural[0, 10])
|
100
|
+
squaredf = lambda { |x| x ** 2 }
|
101
|
+
squared = @natural.mapper(&squaredf)
|
102
|
+
assert_equal(1, squared[0])
|
103
|
+
assert_equal(4, squared[1])
|
104
|
+
assert_equal(9, squared[2])
|
105
|
+
assert_equal((1..10).map(&squaredf), squared[0, 10])
|
106
|
+
assert_equal((1..10).to_a, @natural[0, 10])
|
107
|
+
strangef = lambda { |x| x * (x[0] - ?a + 1) }
|
108
|
+
strange = @strings.mapper(&strangef)
|
109
|
+
assert_equal("a", strange[0])
|
110
|
+
assert_equal("bb", strange[1])
|
111
|
+
assert_equal("ccc", strange[2])
|
112
|
+
assert_equal(("a".."z").map(&strangef), strange[0, 26])
|
113
|
+
assert_equal(("a".."z").to_a, @strings[0, 26])
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_index
|
117
|
+
assert_equal(nil, @natural[-1])
|
118
|
+
assert_equal(1, @natural[0])
|
119
|
+
assert_equal(2, @natural[1])
|
120
|
+
assert_equal(nil, @natural[-1, 10])
|
121
|
+
assert_equal((1..10).to_a, @natural[0, 10])
|
122
|
+
assert_equal((6..15).to_a, @natural[5, 10])
|
123
|
+
assert_equal((1..1).to_a, @natural[0..0])
|
124
|
+
assert_equal((1..0).to_a, @natural[0..-1])
|
125
|
+
assert_equal((1...1).to_a, @natural[0...0])
|
126
|
+
assert_equal((1...0).to_a, @natural[0...-1])
|
127
|
+
assert_equal((1..10).to_a, @natural[0..9])
|
128
|
+
assert_equal((6..15).to_a, @natural[5..14])
|
129
|
+
assert_equal((1..10).to_a, @natural[0...10])
|
130
|
+
assert_equal((6..15).to_a, @natural[5...15])
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_merge
|
134
|
+
natural = @even.merge(@odd)
|
135
|
+
assert_equal(@natural[0, 10].to_a, natural[0, 10].to_a)
|
136
|
+
natural = @odd.merge(@even)
|
137
|
+
assert_equal(@natural[0, 10].to_a, natural[0, 10].to_a)
|
138
|
+
double_list = @natural.merge(@natural) { |a,b| a <= b }
|
139
|
+
assert(double_list[0, 10].to_a, (1..5).map { |x| [x, x] }.flatten)
|
140
|
+
odd2 = @natural.filter(&@oddp).drop(1)
|
141
|
+
some = @even.merge(odd2)
|
142
|
+
assert_equal(@natural[1, 9].to_a, some[0, 9].to_a)
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_take_drop
|
146
|
+
assert_equal([ ], @odd.take(0))
|
147
|
+
assert_equal([ 1, 3, 5 ], @odd.take(3))
|
148
|
+
assert_equal([ 1, 3, 5 ], @odd.take(3))
|
149
|
+
assert_equal([ ], @odd.take!(0))
|
150
|
+
assert_equal([ 1 ], @odd.take(1))
|
151
|
+
assert_equal([ 1 ], @odd.take!(1))
|
152
|
+
assert_equal([ 3, 5, 7 ], @odd.take(3))
|
153
|
+
assert_equal([ 3, 5 ], @odd.take!(2))
|
154
|
+
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
155
|
+
assert_equal([ 7, 9, 11 ], @odd.drop(0).take(3))
|
156
|
+
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
157
|
+
assert_equal([ 9, 11, 13 ], @odd.drop(1).take(3))
|
158
|
+
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
159
|
+
assert_equal([ 11, 13, 15 ], @odd.drop(2).take(3))
|
160
|
+
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
161
|
+
@odd.drop!(0)
|
162
|
+
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
163
|
+
@odd.drop!(1)
|
164
|
+
assert_equal([ 9, 11, 13 ], @odd.take(3))
|
165
|
+
@odd.drop!(2)
|
166
|
+
assert_equal([ 13, 15, 17 ], @odd.take(3))
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_io
|
170
|
+
@tempfile0 = Tempfile.new("test")
|
171
|
+
1.upto(0) do |i|
|
172
|
+
@tempfile0.puts i
|
173
|
+
end
|
174
|
+
@tempfile0.close
|
175
|
+
@tempfile0_list = LazyList[File.new(@tempfile0.path)]
|
176
|
+
@tempfile10 = Tempfile.new("test")
|
177
|
+
1.upto(10) do |i|
|
178
|
+
@tempfile10.puts i
|
179
|
+
end
|
180
|
+
@tempfile10.close
|
181
|
+
@tempfile10_list = LazyList[File.new(@tempfile10.path)]
|
182
|
+
assert_equal(0, @tempfile0_list.size)
|
183
|
+
assert_equal([], @tempfile0_list.to_a)
|
184
|
+
assert_equal(10, @tempfile10_list.size)
|
185
|
+
assert_equal((1..10).map { |x| x.to_s + "\n" },
|
186
|
+
@tempfile10_list.to_a)
|
187
|
+
temp = LazyList.io(File.new(@tempfile0.path)) do |io|
|
188
|
+
io.readline
|
189
|
+
end
|
190
|
+
content = temp.inject([]) { |c, line| c << line }
|
191
|
+
assert_equal([], content)
|
192
|
+
temp = LazyList.io(File.new(@tempfile10.path)) do |io|
|
193
|
+
io.readline
|
194
|
+
end
|
195
|
+
content = temp.inject([]) { |c, line| c << line }
|
196
|
+
assert_equal((1..10).map { |x| x.to_s + "\n" }, content)
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_iterate
|
200
|
+
f = LazyList.iterate(5) do |x|
|
201
|
+
if x % 2 == 0
|
202
|
+
x / 2
|
203
|
+
else
|
204
|
+
5 * x + 1
|
205
|
+
end
|
206
|
+
end
|
207
|
+
assert_equal(nil, f[-1])
|
208
|
+
assert_equal(5, f[0])
|
209
|
+
assert_equal(26, f[1])
|
210
|
+
assert_equal([5, 26, 13, 66, 33, 166, 83, 416], f[0, 8])
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_inpsect
|
214
|
+
l = LazyList[1..11]
|
215
|
+
assert_equal("[]", LazyList::Empty.inspect)
|
216
|
+
assert_equal("[1,... ]", l.inspect)
|
217
|
+
l[1]
|
218
|
+
assert_equal("[1, 2,... ]", l.inspect)
|
219
|
+
l[2]
|
220
|
+
assert_equal("[1, 2, 3,... ]", l.inspect)
|
221
|
+
l[9]
|
222
|
+
assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10,... ]", l.inspect)
|
223
|
+
l.to_a
|
224
|
+
assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", l.inspect)
|
225
|
+
end
|
226
|
+
|
227
|
+
def test_combine
|
228
|
+
combined = @natural.combine(@ones) { |x, y| x + y }
|
229
|
+
assert_equal (12..21).to_a, combined[10,10]
|
230
|
+
assert_equal (2..11).to_a, combined[0,10]
|
231
|
+
end
|
232
|
+
|
233
|
+
def from(n = 0)
|
234
|
+
list(n) { from(n + 1) }
|
235
|
+
end
|
20
236
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@ones = LazyList.iterate(1) { 1 }
|
25
|
-
@oddp = lambda { |x| x % 2 == 1 }
|
26
|
-
@odd = @natural.filter(&@oddp)
|
27
|
-
@evenp = lambda { |x| x % 2 == 0 }
|
28
|
-
@boolean = @natural.mapper { |x| x % 2 == 0}
|
29
|
-
@even = @natural.filter(&@evenp)
|
30
|
-
@finite_inner0 = MyEnum.new(0)
|
31
|
-
@finite0 = LazyList[@finite_inner0]
|
32
|
-
@finite_inner1 = MyEnum.new(1)
|
33
|
-
@finite1 = LazyList[@finite_inner1]
|
34
|
-
@finite_inner10 = MyEnum.new(10)
|
35
|
-
@finite10 = LazyList[@finite_inner10]
|
36
|
-
@finite_span = LazyList.span("A", 10)
|
37
|
-
@finite_span_generated = ("A".."J").to_a
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_constructor
|
41
|
-
ll1 = LazyList.new(:foo, LazyList::Empty)
|
42
|
-
assert(!ll1.empty?)
|
43
|
-
ll2 = LazyList.new(:foo) { Empty }
|
44
|
-
assert(!ll2.empty?)
|
45
|
-
assert_raises(LazyList::Exception) do
|
46
|
-
ll3 = LazyList.new(:foo, :argh) { Empty }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def test_read_queue
|
51
|
-
@read_queue0 = LazyList::ReadQueue.new(1..0)
|
52
|
-
@read_queue1 = LazyList::ReadQueue.new(1..1)
|
53
|
-
@read_queue10 = LazyList::ReadQueue.new(1..10)
|
54
|
-
assert(@read_queue0.empty?)
|
55
|
-
assert_equal(nil, @read_queue0.pop)
|
56
|
-
assert(!@read_queue1.empty?)
|
57
|
-
assert_equal(1, @read_queue1.pop)
|
58
|
-
assert(!@read_queue10.empty?)
|
59
|
-
for i in 1..10 do
|
60
|
-
assert_equal(i, @read_queue10.pop)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_finite
|
65
|
-
assert_equal(@finite_inner0.to_a, @finite0.to_a)
|
66
|
-
assert_equal(@finite_inner1.to_a, @finite1.to_a)
|
67
|
-
assert_equal(@finite_inner10.to_a, @finite10.to_a)
|
68
|
-
assert_equal(@finite_span_generated, @finite_span.to_a)
|
69
|
-
end
|
70
|
-
|
71
|
-
def test_size
|
72
|
-
assert_equal(0, @finite0.size)
|
73
|
-
assert_equal(1, @finite1.size)
|
74
|
-
assert_equal(10, @finite10.size)
|
75
|
-
assert_equal(10, @finite_span.size)
|
76
|
-
assert_equal(0, @finite0.length)
|
77
|
-
assert_equal(1, @finite1.length)
|
78
|
-
assert_equal(10, @finite10.length)
|
79
|
-
assert_equal(10, @finite_span.length)
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_filter
|
83
|
-
assert_equal(1, @odd[0])
|
84
|
-
assert_equal(3, @odd[1])
|
85
|
-
assert_equal(5, @odd[2])
|
86
|
-
assert_equal((1..19).select(&@oddp), @odd[0, 10])
|
87
|
-
assert_equal((1..10).to_a, @natural[0, 10])
|
88
|
-
assert_equal([ 1 ] * 10, @ones[0, 10].to_a)
|
89
|
-
ends_with_a = @strings.filter { |x| x[-1] == ?a }
|
90
|
-
assert(ends_with_a[0, 27] ==
|
91
|
-
[ "a", ("a".."z").map { |x| x + "a" } ].flatten)
|
92
|
-
end
|
93
|
-
|
94
|
-
def test_map
|
95
|
-
id = @natural.mapper
|
96
|
-
assert_equal(1, id[0])
|
97
|
-
assert_equal(2, id[1])
|
98
|
-
assert_equal(3, id[2])
|
99
|
-
assert_equal((1..10).map, id[0, 10])
|
100
|
-
assert_equal((1..10).to_a, @natural[0, 10])
|
101
|
-
squaredf = lambda { |x| x ** 2 }
|
102
|
-
squared = @natural.mapper(&squaredf)
|
103
|
-
assert_equal(1, squared[0])
|
104
|
-
assert_equal(4, squared[1])
|
105
|
-
assert_equal(9, squared[2])
|
106
|
-
assert_equal((1..10).map(&squaredf), squared[0, 10])
|
107
|
-
assert_equal((1..10).to_a, @natural[0, 10])
|
108
|
-
strangef = lambda { |x| x * (x[0] - ?a + 1) }
|
109
|
-
strange = @strings.mapper(&strangef)
|
110
|
-
assert_equal("a", strange[0])
|
111
|
-
assert_equal("bb", strange[1])
|
112
|
-
assert_equal("ccc", strange[2])
|
113
|
-
assert_equal(("a".."z").map(&strangef), strange[0, 26])
|
114
|
-
assert_equal(("a".."z").to_a, @strings[0, 26])
|
115
|
-
end
|
116
|
-
|
117
|
-
def test_index
|
118
|
-
assert_equal(nil, @natural[-1])
|
119
|
-
assert_equal(1, @natural[0])
|
120
|
-
assert_equal(2, @natural[1])
|
121
|
-
assert_equal(nil, @natural[-1, 10])
|
122
|
-
assert_equal((1..10).to_a, @natural[0, 10])
|
123
|
-
assert_equal((6..15).to_a, @natural[5, 10])
|
124
|
-
assert_equal((1..1).to_a, @natural[0..0])
|
125
|
-
assert_equal((1..0).to_a, @natural[0..-1])
|
126
|
-
assert_equal((1...1).to_a, @natural[0...0])
|
127
|
-
assert_equal((1...0).to_a, @natural[0...-1])
|
128
|
-
assert_equal((1..10).to_a, @natural[0..9])
|
129
|
-
assert_equal((6..15).to_a, @natural[5..14])
|
130
|
-
assert_equal((1..10).to_a, @natural[0...10])
|
131
|
-
assert_equal((6..15).to_a, @natural[5...15])
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_merge
|
135
|
-
natural = @even.merge(@odd)
|
136
|
-
assert_equal(@natural[0, 10].to_a, natural[0, 10].to_a)
|
137
|
-
natural = @odd.merge(@even)
|
138
|
-
assert_equal(@natural[0, 10].to_a, natural[0, 10].to_a)
|
139
|
-
double_list = @natural.merge(@natural) { |a,b| a <= b }
|
140
|
-
assert(double_list[0, 10].to_a, (1..5).map { |x| [x, x] }.flatten)
|
141
|
-
odd2 = @natural.filter(&@oddp).drop(1)
|
142
|
-
some = @even.merge(odd2)
|
143
|
-
assert_equal(@natural[1, 9].to_a, some[0, 9].to_a)
|
144
|
-
end
|
145
|
-
|
146
|
-
def test_take_drop
|
147
|
-
assert_equal([ ], @odd.take(0))
|
148
|
-
assert_equal([ 1, 3, 5 ], @odd.take(3))
|
149
|
-
assert_equal([ 1, 3, 5 ], @odd.take(3))
|
150
|
-
assert_equal([ ], @odd.take!(0))
|
151
|
-
assert_equal([ 1 ], @odd.take(1))
|
152
|
-
assert_equal([ 1 ], @odd.take!(1))
|
153
|
-
assert_equal([ 3, 5, 7 ], @odd.take(3))
|
154
|
-
assert_equal([ 3, 5 ], @odd.take!(2))
|
155
|
-
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
156
|
-
assert_equal([ 7, 9, 11 ], @odd.drop(0).take(3))
|
157
|
-
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
158
|
-
assert_equal([ 9, 11, 13 ], @odd.drop(1).take(3))
|
159
|
-
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
160
|
-
assert_equal([ 11, 13, 15 ], @odd.drop(2).take(3))
|
161
|
-
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
162
|
-
@odd.drop!(0)
|
163
|
-
assert_equal([ 7, 9, 11 ], @odd.take(3))
|
164
|
-
@odd.drop!(1)
|
165
|
-
assert_equal([ 9, 11, 13 ], @odd.take(3))
|
166
|
-
@odd.drop!(2)
|
167
|
-
assert_equal([ 13, 15, 17 ], @odd.take(3))
|
168
|
-
end
|
169
|
-
|
170
|
-
def test_io
|
171
|
-
@tempfile0 = Tempfile.new("test")
|
172
|
-
1.upto(0) do |i|
|
173
|
-
@tempfile0.puts i
|
174
|
-
end
|
175
|
-
@tempfile0.close
|
176
|
-
@tempfile0_list = LazyList[File.new(@tempfile0.path)]
|
177
|
-
@tempfile10 = Tempfile.new("test")
|
178
|
-
1.upto(10) do |i|
|
179
|
-
@tempfile10.puts i
|
180
|
-
end
|
181
|
-
@tempfile10.close
|
182
|
-
@tempfile10_list = LazyList[File.new(@tempfile10.path)]
|
183
|
-
assert_equal(0, @tempfile0_list.size)
|
184
|
-
assert_equal([], @tempfile0_list.to_a)
|
185
|
-
assert_equal(10, @tempfile10_list.size)
|
186
|
-
assert_equal((1..10).map { |x| x.to_s + "\n" },
|
187
|
-
@tempfile10_list.to_a)
|
188
|
-
temp = LazyList.io(File.new(@tempfile0.path)) do |io|
|
189
|
-
io.readline
|
190
|
-
end
|
191
|
-
content = temp.inject([]) { |c, line| c << line }
|
192
|
-
assert_equal([], content)
|
193
|
-
temp = LazyList.io(File.new(@tempfile10.path)) do |io|
|
194
|
-
io.readline
|
195
|
-
end
|
196
|
-
content = temp.inject([]) { |c, line| c << line }
|
197
|
-
assert_equal((1..10).map { |x| x.to_s + "\n" }, content)
|
198
|
-
end
|
199
|
-
|
200
|
-
def test_iterate
|
201
|
-
f = LazyList.iterate(5) do |x|
|
202
|
-
if x % 2 == 0
|
203
|
-
x / 2
|
204
|
-
else
|
205
|
-
5 * x + 1
|
206
|
-
end
|
207
|
-
end
|
208
|
-
assert_equal(nil, f[-1])
|
209
|
-
assert_equal(5, f[0])
|
210
|
-
assert_equal(26, f[1])
|
211
|
-
assert_equal([5, 26, 13, 66, 33, 166, 83, 416], f[0, 8])
|
212
|
-
end
|
213
|
-
|
214
|
-
def test_inpsect
|
215
|
-
list = LazyList[1..11]
|
216
|
-
assert_equal("[]", LazyList::Empty.inspect)
|
217
|
-
assert_equal("[1,... ]", list.inspect)
|
218
|
-
list[1]
|
219
|
-
assert_equal("[1, 2,... ]", list.inspect)
|
220
|
-
list[2]
|
221
|
-
assert_equal("[1, 2, 3,... ]", list.inspect)
|
222
|
-
list[9]
|
223
|
-
assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10,... ]", list.inspect)
|
224
|
-
list.to_a
|
225
|
-
assert_equal("[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", list.inspect)
|
226
|
-
end
|
227
|
-
|
228
|
-
def test_combine
|
229
|
-
combined = @natural.combine(@ones) { |x, y| x + y }
|
230
|
-
assert_equal((12..21).to_a, combined[10,10])
|
231
|
-
assert_equal((2..11).to_a, combined[0,10])
|
232
|
-
end
|
237
|
+
def odd
|
238
|
+
from(1).filter { |x| x % 2 == 1 }
|
239
|
+
end
|
233
240
|
|
241
|
+
def test_list
|
242
|
+
assert_equal LazyList::Empty, list
|
243
|
+
assert_equal [], list.to_a
|
244
|
+
assert_equal LazyList.new(1) { LazyList::Empty }, list(1)
|
245
|
+
assert_equal [1], list(1).to_a
|
246
|
+
assert_equal LazyList::Empty, list
|
247
|
+
o = odd
|
248
|
+
assert_equal [1, 3, 5, 7, 9, 11, 13, 15, 17, 19], o.take(10)
|
249
|
+
assert_equal @odd.take(10), o.take(10)
|
250
|
+
ones = list(1) { ones }
|
251
|
+
assert_equal 1, ones.head
|
252
|
+
assert_equal '[1,... ]', ones.inspect
|
253
|
+
assert_equal [ 1 ] * 10 , ones.take(10)
|
254
|
+
assert_equal '[1,... ]', ones.inspect
|
255
|
+
end
|
234
256
|
end
|
235
|
-
|
257
|
+
# vim: set et sw=2 ts=2:
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.
|
2
|
+
rubygems_version: 0.8.11
|
3
3
|
specification_version: 1
|
4
4
|
name: lazylist
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
7
|
-
date:
|
6
|
+
version: 0.1.3
|
7
|
+
date: 2005-10-03 00:00:00 +02:00
|
8
8
|
summary: Implementation of lazy lists for Ruby
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
|
-
author: Florian Frank
|
12
11
|
email: flori@ping.de
|
13
12
|
homepage: http://lazylist.rubyforge.org
|
14
13
|
rubyforge_project: lazylist
|
@@ -25,23 +24,28 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
24
|
version: 0.0.0
|
26
25
|
version:
|
27
26
|
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Florian Frank
|
28
31
|
files:
|
29
|
-
- README.en
|
30
|
-
- CHANGES
|
31
|
-
- GPL
|
32
32
|
- examples
|
33
|
+
- install.rb
|
34
|
+
- GPL
|
33
35
|
- Rakefile
|
34
36
|
- VERSION
|
35
|
-
- install.rb
|
36
|
-
- make_doc.rb
|
37
|
-
- lib
|
38
37
|
- tests
|
39
|
-
-
|
38
|
+
- CHANGES
|
39
|
+
- lib
|
40
|
+
- make_doc.rb
|
41
|
+
- README.en
|
40
42
|
- examples/hamming.rb
|
41
|
-
- examples/pi.rb
|
42
43
|
- examples/sieve.rb
|
43
|
-
-
|
44
|
+
- examples/pi.rb
|
45
|
+
- examples/examples.rb
|
44
46
|
- tests/test.rb
|
47
|
+
- tests/runner.rb
|
48
|
+
- lib/lazylist.rb
|
45
49
|
test_files:
|
46
50
|
- tests/test.rb
|
47
51
|
rdoc_options: []
|