lazylist 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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: []
|