halu 0.0.1
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/History.txt +5 -0
- data/License.txt +1 -0
- data/Manifest.txt +13 -0
- data/README.txt +28 -0
- data/Rakefile +123 -0
- data/example/fib.rb +27 -0
- data/example/insert_sort.rb +17 -0
- data/example/select_sort.rb +21 -0
- data/lib/halu.rb +502 -0
- data/lib/halu/version.rb +9 -0
- data/setup.rb +1585 -0
- data/test/test_halu.rb +442 -0
- data/test/test_helper.rb +2 -0
- metadata +63 -0
data/History.txt
ADDED
data/License.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Ruby's License
|
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Halu ... HAskell-like List Utility
|
2
|
+
==================================
|
3
|
+
|
4
|
+
������ĉ��H
|
5
|
+
-----------
|
6
|
+
Haskell���ۂ�List���C�u�����ł��B
|
7
|
+
Haskell��Prelude�̃��X�g�֘A����S�Ď������Ă��܂��B
|
8
|
+
|
9
|
+
�C���X�g�[��
|
10
|
+
------------
|
11
|
+
Gem�ŃC���X�g�[�����Ă��������B
|
12
|
+
|
13
|
+
$ gem install cohi
|
14
|
+
|
15
|
+
�}�j���A��
|
16
|
+
----------
|
17
|
+
���݂܂���B�����Ă��܂���B
|
18
|
+
lib/halu.rb���Q�Ƃ��Ă��������B
|
19
|
+
Haskell��Prelude�̃}�j���A�����Q�l�ɂȂ�Ǝv���܂��B
|
20
|
+
|
21
|
+
�T���v��
|
22
|
+
--------
|
23
|
+
example�f�B���N�g�����Q�Ƃ��Ă��������B
|
24
|
+
|
25
|
+
�T�|�[�g
|
26
|
+
--------
|
27
|
+
��������܂����牺�L�܂ł��肢���܂��B
|
28
|
+
<tanaka.shinya@gmail.com>
|
data/Rakefile
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
require 'rake/contrib/rubyforgepublisher'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'hoe'
|
11
|
+
|
12
|
+
include FileUtils
|
13
|
+
require File.join(File.dirname(__FILE__), 'lib', 'halu', 'version')
|
14
|
+
|
15
|
+
AUTHOR = 'TANAKA Shin-ya(id:ha-tan)' # can also be an array of Authors
|
16
|
+
EMAIL = "tanaka.shinya@gmail.com"
|
17
|
+
DESCRIPTION = "Halu ... HAskell-like List Utility"
|
18
|
+
GEM_NAME = 'halu' # what ppl will type to install your gem
|
19
|
+
|
20
|
+
@config_file = "~/.rubyforge/user-config.yml"
|
21
|
+
@config = nil
|
22
|
+
def rubyforge_username
|
23
|
+
unless @config
|
24
|
+
begin
|
25
|
+
@config = YAML.load(File.read(File.expand_path(@config_file)))
|
26
|
+
rescue
|
27
|
+
puts <<-EOS
|
28
|
+
ERROR: No rubyforge config file found: #{@config_file}"
|
29
|
+
Run 'rubyforge setup' to prepare your env for access to Rubyforge
|
30
|
+
- See http://newgem.rubyforge.org/rubyforge.html for more details
|
31
|
+
EOS
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@rubyforge_username ||= @config["username"]
|
36
|
+
end
|
37
|
+
|
38
|
+
RUBYFORGE_PROJECT = 'halu' # The unix name for your project
|
39
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
40
|
+
DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
|
41
|
+
|
42
|
+
NAME = "halu"
|
43
|
+
REV = nil
|
44
|
+
# UNCOMMENT IF REQUIRED:
|
45
|
+
# REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
|
46
|
+
VERS = Halu::VERSION::STRING + (REV ? ".#{REV}" : "")
|
47
|
+
CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
|
48
|
+
RDOC_OPTS = ['--quiet', '--title', 'halu documentation',
|
49
|
+
"--opname", "index.html",
|
50
|
+
"--line-numbers",
|
51
|
+
"--main", "README",
|
52
|
+
"--inline-source"]
|
53
|
+
|
54
|
+
class Hoe
|
55
|
+
def extra_deps
|
56
|
+
@extra_deps.reject { |x| Array(x).first == 'hoe' }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Generate all the Rake tasks
|
61
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
62
|
+
hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
63
|
+
p.author = AUTHOR
|
64
|
+
p.description = DESCRIPTION
|
65
|
+
p.email = EMAIL
|
66
|
+
p.summary = DESCRIPTION
|
67
|
+
p.url = HOMEPATH
|
68
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
69
|
+
p.test_globs = ["test/**/test_*.rb"]
|
70
|
+
p.clean_globs |= CLEAN #An array of file patterns to delete on clean.
|
71
|
+
|
72
|
+
# == Optional
|
73
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
74
|
+
#p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
75
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
76
|
+
end
|
77
|
+
|
78
|
+
CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\n\n")
|
79
|
+
PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
80
|
+
hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
|
81
|
+
|
82
|
+
desc 'Generate website files'
|
83
|
+
task :website_generate do
|
84
|
+
Dir['website/**/*.txt'].each do |txt|
|
85
|
+
sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
desc 'Upload website files to rubyforge'
|
90
|
+
task :website_upload do
|
91
|
+
host = "#{rubyforge_username}@rubyforge.org"
|
92
|
+
remote_dir = "/var/www/gforge-projects/#{PATH}/"
|
93
|
+
local_dir = 'website'
|
94
|
+
sh %{rsync -aCv #{local_dir}/ #{host}:#{remote_dir}}
|
95
|
+
end
|
96
|
+
|
97
|
+
desc 'Generate and upload website files'
|
98
|
+
task :website => [:website_generate, :website_upload, :publish_docs]
|
99
|
+
|
100
|
+
desc 'Release the website and new gem version'
|
101
|
+
task :deploy => [:check_version, :website, :release] do
|
102
|
+
puts "Remember to create SVN tag:"
|
103
|
+
puts "svn copy svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/trunk " +
|
104
|
+
"svn+ssh://#{rubyforge_username}@rubyforge.org/var/svn/#{PATH}/tags/REL-#{VERS} "
|
105
|
+
puts "Suggested comment:"
|
106
|
+
puts "Tagging release #{CHANGES}"
|
107
|
+
end
|
108
|
+
|
109
|
+
desc 'Runs tasks website_generate and install_gem as a local deployment of the gem'
|
110
|
+
task :local_deploy => [:website_generate, :install_gem]
|
111
|
+
|
112
|
+
task :check_version do
|
113
|
+
unless ENV['VERSION']
|
114
|
+
puts 'Must pass a VERSION=x.y.z release version'
|
115
|
+
exit
|
116
|
+
end
|
117
|
+
unless ENV['VERSION'] == VERS
|
118
|
+
puts "Please update your version.rb to match the release version, currently #{VERS}"
|
119
|
+
exit
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
data/example/fib.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- compile-command: "ruby fib.rb" -*-
|
3
|
+
|
4
|
+
$LOAD_PATH << '../lib'
|
5
|
+
require 'halu'
|
6
|
+
|
7
|
+
include Halu
|
8
|
+
|
9
|
+
# �t�B�{�i�b�`����̃��X�g(�~��)��Ԃ��B
|
10
|
+
def fib(n)
|
11
|
+
case n
|
12
|
+
when 0
|
13
|
+
List[0]
|
14
|
+
when 1
|
15
|
+
fib(0) >> 1
|
16
|
+
when 2
|
17
|
+
fib(1) >> 1
|
18
|
+
else
|
19
|
+
xs = fib(n - 1)
|
20
|
+
xs >> (xs.head + xs.tail.head)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
p fib(0) # => Halu::List[0]
|
25
|
+
p fib(3) # => Halu::List[2, 1, 1, 0]
|
26
|
+
p fib(5) # => Halu::List[5, 3, 2, 1, 1, 0]
|
27
|
+
p fib(20).head # => 6765
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- compile-command: "ruby insert_sort.rb" -*-
|
3
|
+
|
4
|
+
$LOAD_PATH << '../lib'
|
5
|
+
require 'halu'
|
6
|
+
|
7
|
+
include Halu
|
8
|
+
|
9
|
+
def insert_sort(xs)
|
10
|
+
xs.fold(EMPTY_LIST) do |rs, x|
|
11
|
+
rs1, rs2 = rs.span {|h| h < x} # rs��x��}������ӏ���2�ɕ�����B
|
12
|
+
rs1.append(rs2 >> x) # rs2�̓���x�����đS�̂�rs1�̌�ɂ���B
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
p insert_sort(List[8, 4, 3, 7, 6, 5, 2, 1])
|
17
|
+
# => Halu::List[1, 2, 3, 4, 5, 6, 7, 8]
|
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# -*- compile-command: "ruby select_sort.rb" -*-
|
3
|
+
|
4
|
+
$LOAD_PATH << '../lib'
|
5
|
+
require 'halu'
|
6
|
+
|
7
|
+
include Halu
|
8
|
+
|
9
|
+
def select_sort(xs)
|
10
|
+
if xs.null?
|
11
|
+
EMPTY_LIST
|
12
|
+
else
|
13
|
+
min = xs.minimum # �ŏ��̗v�f�B
|
14
|
+
xs2 = xs.filter {|x| x != min } # ����ȊO�̗v�f�B
|
15
|
+
select_sort(xs2) >> min # �ċA�I�Ƀ\�[�g�B
|
16
|
+
# �擪�ɍŏ��̗v�f����������B
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
p select_sort(List[8, 4, 3, 7, 6, 5, 2, 1])
|
21
|
+
# => Halu::List[1, 2, 3, 4, 5, 6, 7, 8]
|
data/lib/halu.rb
ADDED
@@ -0,0 +1,502 @@
|
|
1
|
+
module Halu
|
2
|
+
class List
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def List::[](*ary)
|
6
|
+
root = list = EMPTY_LIST
|
7
|
+
ary.each do |h|
|
8
|
+
list = list << h
|
9
|
+
root = list if root.null?
|
10
|
+
end
|
11
|
+
root
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(h, t = EMPTY_LIST)
|
15
|
+
@head = h
|
16
|
+
@tail = t
|
17
|
+
end
|
18
|
+
|
19
|
+
def each
|
20
|
+
list = self
|
21
|
+
loop do
|
22
|
+
yield(list.head)
|
23
|
+
break if list.tail.null?
|
24
|
+
list = list.tail
|
25
|
+
end
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_a
|
30
|
+
inject([]) {|ary, h| ary << h }
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
self.class.to_s + to_a.inspect
|
35
|
+
end
|
36
|
+
|
37
|
+
def last_list
|
38
|
+
list = self
|
39
|
+
list = list.tail until list.tail.null?
|
40
|
+
list
|
41
|
+
end
|
42
|
+
private :last_list
|
43
|
+
|
44
|
+
def <<(h)
|
45
|
+
last_list.tail = List.new(h)
|
46
|
+
end
|
47
|
+
|
48
|
+
def >>(h)
|
49
|
+
list = List.new(h)
|
50
|
+
list.tail = self
|
51
|
+
list
|
52
|
+
end
|
53
|
+
|
54
|
+
# map :: (a -> b) -> [a] -> [b]
|
55
|
+
def map2
|
56
|
+
root = list = EMPTY_LIST
|
57
|
+
each do |h|
|
58
|
+
list = list << yield(h)
|
59
|
+
root = list if root.null?
|
60
|
+
end
|
61
|
+
root
|
62
|
+
end
|
63
|
+
|
64
|
+
# (++) :: [a] -> [a] -> [a]
|
65
|
+
def append(list)
|
66
|
+
last_list.tail = list
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
# filter :: (a -> Bool) -> [a] -> [a]
|
71
|
+
def filter
|
72
|
+
root = list = EMPTY_LIST
|
73
|
+
each do |h|
|
74
|
+
if yield(h)
|
75
|
+
list = list << h
|
76
|
+
root = list if root.null?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
root
|
80
|
+
end
|
81
|
+
|
82
|
+
# head :: [a] -> a
|
83
|
+
attr_accessor :head
|
84
|
+
|
85
|
+
# last :: [a] -> a
|
86
|
+
def last
|
87
|
+
inject(nil) {|r, h| h }
|
88
|
+
end
|
89
|
+
|
90
|
+
# tail :: [a] -> [a]
|
91
|
+
attr_accessor :tail
|
92
|
+
|
93
|
+
# init :: [a] -> [a]
|
94
|
+
def init
|
95
|
+
root = list = prelist = EMPTY_LIST
|
96
|
+
each do |h|
|
97
|
+
prelist = list
|
98
|
+
list = list << h
|
99
|
+
root = list if root.null?
|
100
|
+
end
|
101
|
+
prelist.tail = EMPTY_LIST
|
102
|
+
root
|
103
|
+
end
|
104
|
+
|
105
|
+
# null :: [a] -> Bool
|
106
|
+
def null?
|
107
|
+
self == EMPTY_LIST
|
108
|
+
end
|
109
|
+
|
110
|
+
# length :: [a] -> Int
|
111
|
+
def length
|
112
|
+
inject(0) {|r, h| r.succ }
|
113
|
+
end
|
114
|
+
|
115
|
+
# (!!) :: [a] -> Int -> a
|
116
|
+
def at(i)
|
117
|
+
each_with_index do |h, j|
|
118
|
+
return h if i == j
|
119
|
+
end
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
|
123
|
+
# reverse :: [a] -> [a]
|
124
|
+
def reverse
|
125
|
+
inject(EMPTY_LIST) {|list, h| list >> h }
|
126
|
+
end
|
127
|
+
|
128
|
+
# foldl :: (a -> b -> a) -> a -> [b] -> a
|
129
|
+
# foldl1 :: (a -> a -> a) -> [a] -> a
|
130
|
+
# foldr :: (a -> b -> b) -> b -> [a] -> b
|
131
|
+
# foldr1 :: (a -> a -> a) -> [a] -> a
|
132
|
+
def fold(x)
|
133
|
+
inject(x) {|*arg| yield(*arg) }
|
134
|
+
end
|
135
|
+
|
136
|
+
def fold1
|
137
|
+
inject {|*arg| yield(*arg) }
|
138
|
+
end
|
139
|
+
|
140
|
+
# and :: [Bool] -> Bool
|
141
|
+
def and?
|
142
|
+
each do |h|
|
143
|
+
return false unless h
|
144
|
+
end
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
# or :: [Bool] -> Bool
|
149
|
+
def or?
|
150
|
+
each do |h|
|
151
|
+
return true if h
|
152
|
+
end
|
153
|
+
false
|
154
|
+
end
|
155
|
+
|
156
|
+
# any :: (a -> Bool) -> [a] -> Bool
|
157
|
+
# Enumerable#any?
|
158
|
+
|
159
|
+
# all :: (a -> Bool) -> [a] -> Bool
|
160
|
+
# Enumerable#all?
|
161
|
+
|
162
|
+
# sum :: Num a => [a] -> a
|
163
|
+
def sum
|
164
|
+
inject(0) {|r, h| r + h }
|
165
|
+
end
|
166
|
+
|
167
|
+
# product :: Num a => [a] -> a
|
168
|
+
def product
|
169
|
+
inject(1) {|r, h| r * h }
|
170
|
+
end
|
171
|
+
|
172
|
+
# concat :: [[a]] -> [a]
|
173
|
+
def concat
|
174
|
+
root = list = EMPTY_LIST
|
175
|
+
each do |h|
|
176
|
+
list.append h
|
177
|
+
list = h
|
178
|
+
root = list if root.null?
|
179
|
+
end
|
180
|
+
root
|
181
|
+
end
|
182
|
+
|
183
|
+
# concatMap :: (a -> [b]) -> [a] -> [b]
|
184
|
+
def concat_map(&block)
|
185
|
+
map2(&block).concat
|
186
|
+
end
|
187
|
+
|
188
|
+
# maximum :: Ord a => [a] -> a
|
189
|
+
alias :maximum :max
|
190
|
+
|
191
|
+
# minimum :: Ord a => [a] -> a
|
192
|
+
alias :minimum :min
|
193
|
+
|
194
|
+
# scanl :: (a -> b -> a) -> a -> [b] -> [a]
|
195
|
+
# scanl1 :: (a -> a -> a) -> [a] -> [a]
|
196
|
+
# scanr :: (a -> b -> b) -> b -> [a] -> [b]
|
197
|
+
# scanr1 :: (a -> a -> a) -> [a] -> [a]
|
198
|
+
def scan(x)
|
199
|
+
root = rs = EMPTY_LIST
|
200
|
+
inject(x) do |r, h|
|
201
|
+
root = rs = rs << r if root.null?
|
202
|
+
r2 = yield(r, h)
|
203
|
+
rs = rs << r2
|
204
|
+
r2
|
205
|
+
end
|
206
|
+
root
|
207
|
+
end
|
208
|
+
|
209
|
+
def scan1
|
210
|
+
root = rs = EMPTY_LIST
|
211
|
+
inject do |r, h|
|
212
|
+
root = rs = rs << r if root.null?
|
213
|
+
r2 = yield(r, h)
|
214
|
+
rs = rs << r2
|
215
|
+
r2
|
216
|
+
end
|
217
|
+
root
|
218
|
+
end
|
219
|
+
|
220
|
+
# replicate :: Int -> a -> [a]
|
221
|
+
def List::replicate(n, h)
|
222
|
+
root = list = EMPTY_LIST
|
223
|
+
n.times do
|
224
|
+
list = list << h
|
225
|
+
root = list if root.null?
|
226
|
+
end
|
227
|
+
root
|
228
|
+
end
|
229
|
+
|
230
|
+
# take :: Int -> [a] -> [a]
|
231
|
+
def take(n)
|
232
|
+
root = list = EMPTY_LIST
|
233
|
+
each_with_index do |h, i|
|
234
|
+
break if i >= n
|
235
|
+
list = list << h
|
236
|
+
root = list if root.null?
|
237
|
+
end
|
238
|
+
root
|
239
|
+
end
|
240
|
+
|
241
|
+
# drop :: Int -> [a] -> [a]
|
242
|
+
def drop(n)
|
243
|
+
root = list = EMPTY_LIST
|
244
|
+
each_with_index do |h, i|
|
245
|
+
if i >= n
|
246
|
+
list = list << h
|
247
|
+
root = list if root.null?
|
248
|
+
end
|
249
|
+
end
|
250
|
+
root
|
251
|
+
end
|
252
|
+
|
253
|
+
# splitAt :: Int -> [a] -> ([a], [a])
|
254
|
+
def split_at(n)
|
255
|
+
root1 = root2 = list1 = list2 = EMPTY_LIST
|
256
|
+
each_with_index do |h, i|
|
257
|
+
if i < n
|
258
|
+
list1 = list1 << h
|
259
|
+
root1 = list1 if root1.null?
|
260
|
+
else
|
261
|
+
list2 = list2 << h
|
262
|
+
root2 = list2 if root2.null?
|
263
|
+
end
|
264
|
+
end
|
265
|
+
[root1, root2]
|
266
|
+
end
|
267
|
+
|
268
|
+
# takeWhile :: (a -> Bool) -> [a] -> [a]
|
269
|
+
def take_while
|
270
|
+
root = list = EMPTY_LIST
|
271
|
+
each do |h|
|
272
|
+
break unless yield(h)
|
273
|
+
list = list << h
|
274
|
+
root = list if root.null?
|
275
|
+
end
|
276
|
+
root
|
277
|
+
end
|
278
|
+
|
279
|
+
# dropWhile :: (a -> Bool) -> [a] -> [a]
|
280
|
+
def drop_while
|
281
|
+
root = list = EMPTY_LIST
|
282
|
+
drop_f = true
|
283
|
+
each do |h|
|
284
|
+
if drop_f
|
285
|
+
drop_f = false unless yield(h)
|
286
|
+
end
|
287
|
+
unless drop_f
|
288
|
+
list = list << h
|
289
|
+
root = list if root.null?
|
290
|
+
end
|
291
|
+
end
|
292
|
+
root
|
293
|
+
end
|
294
|
+
|
295
|
+
# span :: (a -> Bool) -> [a] -> ([a], [a])
|
296
|
+
def span
|
297
|
+
root1 = root2 = list1 = list2 = EMPTY_LIST
|
298
|
+
span_f = false
|
299
|
+
each do |h|
|
300
|
+
unless span_f
|
301
|
+
span_f = true unless yield(h)
|
302
|
+
end
|
303
|
+
unless span_f
|
304
|
+
list1 = list1 << h
|
305
|
+
root1 = list1 if root1.null?
|
306
|
+
else
|
307
|
+
list2 = list2 << h
|
308
|
+
root2 = list2 if root2.null?
|
309
|
+
end
|
310
|
+
end
|
311
|
+
[root1, root2]
|
312
|
+
end
|
313
|
+
|
314
|
+
# break :: (a -> Bool) -> [a] -> ([a], [a])
|
315
|
+
def break
|
316
|
+
root1 = root2 = list1 = list2 = EMPTY_LIST
|
317
|
+
span_f = false
|
318
|
+
each do |h|
|
319
|
+
unless span_f
|
320
|
+
span_f = true if yield(h)
|
321
|
+
end
|
322
|
+
unless span_f
|
323
|
+
list1 = list1 << h
|
324
|
+
root1 = list1 if root1.null?
|
325
|
+
else
|
326
|
+
list2 = list2 << h
|
327
|
+
root2 = list2 if root2.null?
|
328
|
+
end
|
329
|
+
end
|
330
|
+
[root1, root2]
|
331
|
+
end
|
332
|
+
|
333
|
+
# elem :: Eq a => a -> [a] -> Bool
|
334
|
+
def elem(h)
|
335
|
+
list = EMPTY_LIST
|
336
|
+
each do |h2|
|
337
|
+
return true if h == h2
|
338
|
+
end
|
339
|
+
false
|
340
|
+
end
|
341
|
+
|
342
|
+
# notElem :: Eq a => a -> [a] -> Bool
|
343
|
+
def not_elem(h)
|
344
|
+
not elem(h)
|
345
|
+
end
|
346
|
+
|
347
|
+
# lookup :: Eq a => a -> [(a, b)] -> Maybe b
|
348
|
+
def lookup(h)
|
349
|
+
list = EMPTY_LIST
|
350
|
+
each do |a|
|
351
|
+
return a[1] if h == a[0]
|
352
|
+
end
|
353
|
+
nil
|
354
|
+
end
|
355
|
+
|
356
|
+
# zip :: [a] -> [b] -> [(a, b)]
|
357
|
+
def zip2(list2)
|
358
|
+
return EMPTY_LIST if null?
|
359
|
+
return EMPTY_LIST if list2.null?
|
360
|
+
root = list = EMPTY_LIST
|
361
|
+
list1 = self
|
362
|
+
loop do
|
363
|
+
list = list << [list1.head, list2.head]
|
364
|
+
root = list if root.null?
|
365
|
+
break if list1.tail.null?
|
366
|
+
break if list2.tail.null?
|
367
|
+
list1 = list1.tail
|
368
|
+
list2 = list2.tail
|
369
|
+
end
|
370
|
+
root
|
371
|
+
end
|
372
|
+
|
373
|
+
# zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
|
374
|
+
def zip3(list2, list3)
|
375
|
+
return EMPTY_LIST if null?
|
376
|
+
return EMPTY_LIST if list2.null?
|
377
|
+
return EMPTY_LIST if list3.null?
|
378
|
+
root = list = EMPTY_LIST
|
379
|
+
list1 = self
|
380
|
+
loop do
|
381
|
+
list = list << [list1.head, list2.head, list3.head]
|
382
|
+
root = list if root.null?
|
383
|
+
break if list1.tail.null?
|
384
|
+
break if list2.tail.null?
|
385
|
+
break if list3.tail.null?
|
386
|
+
list1 = list1.tail
|
387
|
+
list2 = list2.tail
|
388
|
+
list3 = list3.tail
|
389
|
+
end
|
390
|
+
root
|
391
|
+
end
|
392
|
+
|
393
|
+
# zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
|
394
|
+
def zip_with(list2)
|
395
|
+
return EMPTY_LIST if null?
|
396
|
+
return EMPTY_LIST if list2.null?
|
397
|
+
root = list = EMPTY_LIST
|
398
|
+
list1 = self
|
399
|
+
loop do
|
400
|
+
list = list << yield(list1.head, list2.head)
|
401
|
+
root = list if root.null?
|
402
|
+
break if list1.tail.null?
|
403
|
+
break if list2.tail.null?
|
404
|
+
list1 = list1.tail
|
405
|
+
list2 = list2.tail
|
406
|
+
end
|
407
|
+
root
|
408
|
+
end
|
409
|
+
|
410
|
+
# zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
|
411
|
+
def zip_with3(list2, list3)
|
412
|
+
return EMPTY_LIST if null?
|
413
|
+
return EMPTY_LIST if list2.null?
|
414
|
+
return EMPTY_LIST if list3.null?
|
415
|
+
root = list = EMPTY_LIST
|
416
|
+
list1 = self
|
417
|
+
loop do
|
418
|
+
list = list << yield(list1.head, list2.head, list3.head)
|
419
|
+
root = list if root.null?
|
420
|
+
break if list1.tail.null?
|
421
|
+
break if list2.tail.null?
|
422
|
+
break if list3.tail.null?
|
423
|
+
list1 = list1.tail
|
424
|
+
list2 = list2.tail
|
425
|
+
list3 = list3.tail
|
426
|
+
end
|
427
|
+
root
|
428
|
+
end
|
429
|
+
|
430
|
+
# unzip :: [(a, b)] -> ([a], [b])
|
431
|
+
def unzip
|
432
|
+
root1 = root2 = list1 = list2 = EMPTY_LIST
|
433
|
+
each do |h|
|
434
|
+
list1 = list1 << h[0]
|
435
|
+
list2 = list2 << h[1]
|
436
|
+
root1 = list1 if root1.null?
|
437
|
+
root2 = list2 if root2.null?
|
438
|
+
end
|
439
|
+
[root1, root2]
|
440
|
+
end
|
441
|
+
|
442
|
+
# unzip3 :: [(a, b, c)] -> ([a], [b], [c])
|
443
|
+
def unzip3
|
444
|
+
root1 = root2 = root3 = list1 = list2 = list3 = EMPTY_LIST
|
445
|
+
each do |h|
|
446
|
+
list1 = list1 << h[0]
|
447
|
+
list2 = list2 << h[1]
|
448
|
+
list3 = list3 << h[2]
|
449
|
+
root1 = list1 if root1.null?
|
450
|
+
root2 = list2 if root2.null?
|
451
|
+
root3 = list3 if root3.null?
|
452
|
+
end
|
453
|
+
[root1, root2, root3]
|
454
|
+
end
|
455
|
+
|
456
|
+
# unlines :: [String] -> String
|
457
|
+
def unlines(nl = "\n")
|
458
|
+
inject('') do |s, h|
|
459
|
+
s + h.to_s + nl
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
# unwords :: [String] -> String
|
464
|
+
def unwords(sp = ' ')
|
465
|
+
inject('') do |s, h|
|
466
|
+
s + (s.empty? ? '' : sp) + h.to_s
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
class EmptyList < List
|
472
|
+
def initialize
|
473
|
+
end
|
474
|
+
|
475
|
+
def each
|
476
|
+
end
|
477
|
+
|
478
|
+
def to_a
|
479
|
+
[]
|
480
|
+
end
|
481
|
+
|
482
|
+
def <<(h)
|
483
|
+
List.new(h)
|
484
|
+
end
|
485
|
+
|
486
|
+
def >>(h)
|
487
|
+
List.new(h)
|
488
|
+
end
|
489
|
+
|
490
|
+
def append(list)
|
491
|
+
list
|
492
|
+
end
|
493
|
+
|
494
|
+
def scan(x)
|
495
|
+
List.new(x)
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
EMPTY_LIST = EmptyList.new
|
500
|
+
end
|
501
|
+
|
502
|
+
require 'halu/version'
|