comp_tree 0.5.2 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +24 -0
- data/README +19 -52
- data/Rakefile +1 -138
- data/comp_tree.gemspec +33 -30
- data/install.rb +3 -3
- data/lib/comp_tree/algorithm.rb +117 -156
- data/lib/comp_tree/driver.rb +39 -154
- data/lib/comp_tree/error.rb +18 -23
- data/lib/comp_tree/node.rb +46 -50
- data/lib/comp_tree.rb +56 -0
- data/rakelib/jumpstart/ruby.rb +51 -0
- data/{contrib/quix/lib/quix → rakelib/jumpstart}/simple_installer.rb +11 -13
- data/test/common.rb +29 -0
- data/test/test_basic.rb +189 -0
- data/test/test_circular.rb +34 -31
- data/test/test_drain.rb +38 -0
- data/test/test_exception.rb +37 -86
- data/test/test_flood.rb +14 -0
- data/test/test_grind.rb +77 -0
- data/test/test_sequential.rb +21 -0
- metadata +45 -58
- data/contrib/quix/Rakefile +0 -16
- data/contrib/quix/install.rb +0 -3
- data/contrib/quix/lib/quix/builtin/dir/casefold_brackets.rb +0 -7
- data/contrib/quix/lib/quix/builtin/kernel/tap.rb +0 -9
- data/contrib/quix/lib/quix/builtin/module/include.rb +0 -21
- data/contrib/quix/lib/quix/builtin/module/private.rb +0 -41
- data/contrib/quix/lib/quix/config.rb +0 -37
- data/contrib/quix/lib/quix/cygwin.rb +0 -60
- data/contrib/quix/lib/quix/diagnostic.rb +0 -44
- data/contrib/quix/lib/quix/enumerable.rb +0 -33
- data/contrib/quix/lib/quix/fileutils.rb +0 -37
- data/contrib/quix/lib/quix/hash_struct.rb +0 -27
- data/contrib/quix/lib/quix/kernel.rb +0 -61
- data/contrib/quix/lib/quix/lazy_struct.rb +0 -55
- data/contrib/quix/lib/quix/string.rb +0 -38
- data/contrib/quix/lib/quix/subpackager.rb +0 -52
- data/contrib/quix/lib/quix/thread_local.rb +0 -32
- data/contrib/quix/lib/quix/vars.rb +0 -138
- data/contrib/quix/lib/quix.rb +0 -32
- data/contrib/quix/test/all.rb +0 -12
- data/contrib/quix/test/test_deps.rb +0 -25
- data/contrib/quix/test/test_include.rb +0 -47
- data/contrib/quix/test/test_private.rb +0 -86
- data/contrib/quix/test/test_root.rb +0 -19
- data/contrib/quix/test/test_struct.rb +0 -48
- data/contrib/quix/test/test_vars.rb +0 -187
- data/lib/comp_tree/bucket_ipc.rb +0 -151
- data/lib/comp_tree/diagnostic.rb +0 -44
- data/lib/comp_tree/misc.rb +0 -61
- data/lib/comp_tree/retriable_fork.rb +0 -42
- data/lib/comp_tree/tap.rb +0 -9
- data/lib/comp_tree/task_node.rb +0 -22
- data/test/all.rb +0 -12
- data/test/test_bucketipc.rb +0 -72
- data/test/test_comp_tree.rb +0 -364
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: comp_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James M. Lawrence
|
@@ -9,11 +9,11 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-04-09 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description: Build a computation tree and execute it with N parallel threads.
|
16
|
+
description: Build a computation tree and execute it with N parallel threads.
|
17
17
|
email: quixoticsycophant@gmail.com
|
18
18
|
executables: []
|
19
19
|
|
@@ -22,53 +22,26 @@ extensions: []
|
|
22
22
|
extra_rdoc_files:
|
23
23
|
- README
|
24
24
|
files:
|
25
|
+
- CHANGES
|
25
26
|
- README
|
27
|
+
- Rakefile
|
26
28
|
- comp_tree.gemspec
|
27
|
-
-
|
28
|
-
-
|
29
|
-
-
|
30
|
-
-
|
31
|
-
-
|
32
|
-
-
|
33
|
-
-
|
34
|
-
-
|
35
|
-
-
|
36
|
-
-
|
37
|
-
-
|
38
|
-
-
|
39
|
-
-
|
40
|
-
-
|
41
|
-
-
|
42
|
-
-
|
43
|
-
- ./contrib/quix/lib/quix/thread_local.rb
|
44
|
-
- ./contrib/quix/lib/quix/vars.rb
|
45
|
-
- ./contrib/quix/lib/quix.rb
|
46
|
-
- ./contrib/quix/test/all.rb
|
47
|
-
- ./contrib/quix/test/test_deps.rb
|
48
|
-
- ./contrib/quix/test/test_include.rb
|
49
|
-
- ./contrib/quix/test/test_private.rb
|
50
|
-
- ./contrib/quix/test/test_root.rb
|
51
|
-
- ./contrib/quix/test/test_struct.rb
|
52
|
-
- ./contrib/quix/test/test_vars.rb
|
53
|
-
- ./install.rb
|
54
|
-
- ./lib/comp_tree/algorithm.rb
|
55
|
-
- ./lib/comp_tree/bucket_ipc.rb
|
56
|
-
- ./lib/comp_tree/diagnostic.rb
|
57
|
-
- ./lib/comp_tree/driver.rb
|
58
|
-
- ./lib/comp_tree/error.rb
|
59
|
-
- ./lib/comp_tree/misc.rb
|
60
|
-
- ./lib/comp_tree/node.rb
|
61
|
-
- ./lib/comp_tree/retriable_fork.rb
|
62
|
-
- ./lib/comp_tree/tap.rb
|
63
|
-
- ./lib/comp_tree/task_node.rb
|
64
|
-
- ./lib/comp_tree.rb
|
65
|
-
- ./test/all.rb
|
66
|
-
- ./test/test_bucketipc.rb
|
67
|
-
- ./test/test_circular.rb
|
68
|
-
- ./test/test_comp_tree.rb
|
69
|
-
- ./test/test_exception.rb
|
70
|
-
- ./Rakefile
|
71
|
-
- ./contrib/quix/Rakefile
|
29
|
+
- install.rb
|
30
|
+
- lib/comp_tree/algorithm.rb
|
31
|
+
- lib/comp_tree/driver.rb
|
32
|
+
- lib/comp_tree/error.rb
|
33
|
+
- lib/comp_tree/node.rb
|
34
|
+
- lib/comp_tree.rb
|
35
|
+
- rakelib/jumpstart/ruby.rb
|
36
|
+
- rakelib/jumpstart/simple_installer.rb
|
37
|
+
- test/common.rb
|
38
|
+
- test/test_basic.rb
|
39
|
+
- test/test_circular.rb
|
40
|
+
- test/test_drain.rb
|
41
|
+
- test/test_exception.rb
|
42
|
+
- test/test_flood.rb
|
43
|
+
- test/test_grind.rb
|
44
|
+
- test/test_sequential.rb
|
72
45
|
has_rdoc: true
|
73
46
|
homepage: comptree.rubyforge.org
|
74
47
|
post_install_message:
|
@@ -78,23 +51,37 @@ rdoc_options:
|
|
78
51
|
- --title
|
79
52
|
- "comp_tree: Parallel Computation Tree"
|
80
53
|
- --exclude
|
81
|
-
-
|
54
|
+
- CHANGES
|
82
55
|
- --exclude
|
83
|
-
-
|
56
|
+
- Rakefile
|
84
57
|
- --exclude
|
85
|
-
-
|
58
|
+
- comp_tree.gemspec
|
59
|
+
- --exclude
|
60
|
+
- install.rb
|
61
|
+
- --exclude
|
62
|
+
- lib/comp_tree/algorithm.rb
|
63
|
+
- --exclude
|
64
|
+
- lib/comp_tree/node.rb
|
65
|
+
- --exclude
|
66
|
+
- rakelib/jumpstart/ruby.rb
|
67
|
+
- --exclude
|
68
|
+
- rakelib/jumpstart/simple_installer.rb
|
69
|
+
- --exclude
|
70
|
+
- test/common.rb
|
71
|
+
- --exclude
|
72
|
+
- test/test_basic.rb
|
86
73
|
- --exclude
|
87
|
-
-
|
74
|
+
- test/test_circular.rb
|
88
75
|
- --exclude
|
89
|
-
-
|
76
|
+
- test/test_drain.rb
|
90
77
|
- --exclude
|
91
|
-
-
|
78
|
+
- test/test_exception.rb
|
92
79
|
- --exclude
|
93
|
-
-
|
80
|
+
- test/test_flood.rb
|
94
81
|
- --exclude
|
95
|
-
-
|
82
|
+
- test/test_grind.rb
|
96
83
|
- --exclude
|
97
|
-
-
|
84
|
+
- test/test_sequential.rb
|
98
85
|
require_paths:
|
99
86
|
- lib
|
100
87
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -112,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
99
|
requirements: []
|
113
100
|
|
114
101
|
rubyforge_project: comptree
|
115
|
-
rubygems_version: 1.
|
102
|
+
rubygems_version: 1.3.1
|
116
103
|
signing_key:
|
117
104
|
specification_version: 2
|
118
105
|
summary: Parallel Computation Tree
|
data/contrib/quix/Rakefile
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
$LOAD_PATH.unshift "./lib"
|
2
|
-
|
3
|
-
require 'quix/simple_installer'
|
4
|
-
require 'quix/config'
|
5
|
-
|
6
|
-
task :test do
|
7
|
-
load './test/all.rb'
|
8
|
-
end
|
9
|
-
|
10
|
-
task :install do
|
11
|
-
Quix::SimpleInstaller.new.install
|
12
|
-
end
|
13
|
-
|
14
|
-
task :uninstall do
|
15
|
-
Quix::SimpleInstaller.new.uninstall
|
16
|
-
end
|
data/contrib/quix/install.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
|
2
|
-
if $DEBUG and !(defined?($NO_DEBUG_INCLUDE) and $NO_DEBUG_INCLUDE)
|
3
|
-
class Module
|
4
|
-
orig_include = instance_method(:include)
|
5
|
-
remove_method(:include)
|
6
|
-
define_method(:include) { |*mods|
|
7
|
-
mods.each { |mod|
|
8
|
-
if mod.class == Module
|
9
|
-
mod.instance_methods(true).each { |name|
|
10
|
-
if self.instance_methods(true).include?(name)
|
11
|
-
STDERR.puts("Note: replacing #{self.inspect}##{name} " +
|
12
|
-
"with #{mod.inspect}##{name}")
|
13
|
-
end
|
14
|
-
}
|
15
|
-
end
|
16
|
-
orig_include.bind(self).call(*mods)
|
17
|
-
}
|
18
|
-
}
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
@@ -1,41 +0,0 @@
|
|
1
|
-
|
2
|
-
class Module
|
3
|
-
alias_method :private__original, :private
|
4
|
-
def private(*args, &block)
|
5
|
-
private__original(*args)
|
6
|
-
if block
|
7
|
-
singleton_class = (class << self ; self ; end)
|
8
|
-
caller_self = block.binding.eval("self")
|
9
|
-
method_added__original =
|
10
|
-
if (t = method(:method_added)) and t.owner == singleton_class
|
11
|
-
t
|
12
|
-
else
|
13
|
-
nil
|
14
|
-
end
|
15
|
-
begin
|
16
|
-
singleton_class.instance_eval {
|
17
|
-
define_method(:method_added) { |name|
|
18
|
-
caller_self.instance_eval {
|
19
|
-
private__original(name.to_sym)
|
20
|
-
}
|
21
|
-
if t = method_added__original
|
22
|
-
t.call(name)
|
23
|
-
end
|
24
|
-
}
|
25
|
-
}
|
26
|
-
block.call
|
27
|
-
ensure
|
28
|
-
if t = method_added__original
|
29
|
-
t.owner.instance_eval {
|
30
|
-
define_method(:method_added, t)
|
31
|
-
}
|
32
|
-
else
|
33
|
-
singleton_class.instance_eval {
|
34
|
-
remove_method(:method_added)
|
35
|
-
}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
@@ -1,37 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'rbconfig'
|
3
|
-
|
4
|
-
module Quix
|
5
|
-
module Config
|
6
|
-
CONFIG = ::Config::CONFIG
|
7
|
-
|
8
|
-
def ruby_executable
|
9
|
-
File.join(CONFIG["bindir"], CONFIG["RUBY_INSTALL_NAME"])
|
10
|
-
end
|
11
|
-
|
12
|
-
def version_gt(version) ; version_compare( :>, version) ; end
|
13
|
-
def version_lt(version) ; version_compare( :<, version) ; end
|
14
|
-
def version_eq(version) ; version_compare(:==, version) ; end
|
15
|
-
def version_ge(version) ; version_compare(:>=, version) ; end
|
16
|
-
def version_le(version) ; version_compare(:<=, version) ; end
|
17
|
-
def version_ne(version) ; version_compare(:"!=", version) ; end
|
18
|
-
|
19
|
-
def version_compare(op, version)
|
20
|
-
major, minor, teeny =
|
21
|
-
version.split(".").map { |n| n.to_i }
|
22
|
-
|
23
|
-
this_major, this_minor, this_teeny =
|
24
|
-
%w(MAJOR MINOR TEENY).map { |v| CONFIG[v].to_i }
|
25
|
-
|
26
|
-
if this_major == major and this_minor == minor
|
27
|
-
this_teeny.send(op, teeny)
|
28
|
-
elsif this_major == major
|
29
|
-
this_minor.send(op, minor)
|
30
|
-
else
|
31
|
-
this_major.send(op, major)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
extend self
|
36
|
-
end
|
37
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
|
2
|
-
unless RUBY_PLATFORM =~ %r!cygwin!
|
3
|
-
raise NotImplementedError, "cygwin-only module"
|
4
|
-
end
|
5
|
-
|
6
|
-
require 'fileutils'
|
7
|
-
require 'thread'
|
8
|
-
|
9
|
-
module Quix
|
10
|
-
module Cygwin
|
11
|
-
def run_batchfile(file, *args)
|
12
|
-
dos_pwd_env {
|
13
|
-
sh("cmd", "/c", dos_path(file), *args)
|
14
|
-
}
|
15
|
-
end
|
16
|
-
|
17
|
-
def normalize_path(path)
|
18
|
-
path.sub(%r!/+\Z!, "")
|
19
|
-
end
|
20
|
-
|
21
|
-
def unix2dos(string)
|
22
|
-
string.
|
23
|
-
gsub("\n", "\r\n").
|
24
|
-
gsub(%r!\r+!, "\r")
|
25
|
-
end
|
26
|
-
|
27
|
-
def dos_path(unix_path)
|
28
|
-
`cygpath -w #{normalize_path(unix_path)}`.chomp
|
29
|
-
end
|
30
|
-
|
31
|
-
def unix_path(dos_path)
|
32
|
-
escaped_path = dos_path.sub(%r!\\+\Z!, "").gsub("\\", "\\\\\\\\")
|
33
|
-
`cygpath #{escaped_path}`.chomp
|
34
|
-
end
|
35
|
-
|
36
|
-
def dos_pwd_env
|
37
|
-
Thread.exclusive {
|
38
|
-
orig = ENV["PWD"]
|
39
|
-
ENV["PWD"] = dos_path(Dir.pwd)
|
40
|
-
begin
|
41
|
-
yield
|
42
|
-
ensure
|
43
|
-
ENV["PWD"] = orig
|
44
|
-
end
|
45
|
-
}
|
46
|
-
end
|
47
|
-
|
48
|
-
def avoid_dll(file)
|
49
|
-
temp_file = file + ".avoiding-link"
|
50
|
-
FileUtils.mv(file, temp_file)
|
51
|
-
begin
|
52
|
-
yield
|
53
|
-
ensure
|
54
|
-
FileUtils.mv(temp_file, file)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
extend self
|
59
|
-
end
|
60
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'comp_tree/tap'
|
3
|
-
|
4
|
-
module CompTree
|
5
|
-
module Diagnostic
|
6
|
-
def show(desc = nil, stream = STDOUT, &block)
|
7
|
-
if desc
|
8
|
-
stream.puts(desc)
|
9
|
-
end
|
10
|
-
if block
|
11
|
-
expression = block.call
|
12
|
-
eval(expression, block.binding).tap { |result|
|
13
|
-
stream.printf("%-16s => %s\n", expression, result.inspect)
|
14
|
-
}
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
if $DEBUG
|
19
|
-
def debug
|
20
|
-
yield
|
21
|
-
end
|
22
|
-
|
23
|
-
def debugging?
|
24
|
-
true
|
25
|
-
end
|
26
|
-
|
27
|
-
def trace(desc = nil, &block)
|
28
|
-
if desc
|
29
|
-
show("#{desc}.".sub(%r!\.\.+\Z!, ""), STDERR, &block)
|
30
|
-
else
|
31
|
-
show(nil, STDERR, &block)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
else
|
35
|
-
# non-$DEBUG
|
36
|
-
def debug ; end
|
37
|
-
def debugging? ; end
|
38
|
-
def trace(*args) ; end
|
39
|
-
end
|
40
|
-
|
41
|
-
extend self
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
@@ -1,33 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'quix/builtin/kernel/tap'
|
3
|
-
|
4
|
-
module Quix
|
5
|
-
module Enumerable
|
6
|
-
def inject_with_index(*args)
|
7
|
-
index = 0
|
8
|
-
inject(*args) { |acc, elem|
|
9
|
-
yield(acc, elem, index).tap {
|
10
|
-
index += 1
|
11
|
-
}
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
def map_with_index
|
16
|
-
Array.new.tap { |result|
|
17
|
-
each_with_index { |elem, index|
|
18
|
-
result << yield(elem, index)
|
19
|
-
}
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
def select_with_index
|
24
|
-
Array.new.tap { |result|
|
25
|
-
each_with_index { |elem, index|
|
26
|
-
if yield(elem, index)
|
27
|
-
result << elem
|
28
|
-
end
|
29
|
-
}
|
30
|
-
}
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'tmpdir'
|
3
|
-
require 'quix/builtin/kernel/tap'
|
4
|
-
|
5
|
-
module Quix
|
6
|
-
module FileUtils
|
7
|
-
def rename_file(file, new_name)
|
8
|
-
#
|
9
|
-
# For case-insensitive systems, we must move the file elsewhere
|
10
|
-
# before changing case.
|
11
|
-
#
|
12
|
-
temp = File.join(Dir.tmpdir, File.basename(file))
|
13
|
-
::FileUtils.mv(file, temp)
|
14
|
-
begin
|
15
|
-
::FileUtils.mv(temp, new_name)
|
16
|
-
rescue
|
17
|
-
::FileUtils.mv(temp, file)
|
18
|
-
raise
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def replace_file(file)
|
23
|
-
old_contents = File.read(file)
|
24
|
-
yield(old_contents).tap { |new_contents|
|
25
|
-
File.open(file, "w") { |output|
|
26
|
-
output.print(new_contents)
|
27
|
-
}
|
28
|
-
}
|
29
|
-
end
|
30
|
-
|
31
|
-
def stem(file)
|
32
|
-
file.sub(%r!#{File.extname(file)}\Z!, "")
|
33
|
-
end
|
34
|
-
|
35
|
-
extend self
|
36
|
-
end
|
37
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'quix/builtin/kernel/tap'
|
3
|
-
require 'ostruct'
|
4
|
-
|
5
|
-
module Quix
|
6
|
-
class HashStruct < OpenStruct
|
7
|
-
def method_missing(sym, *args, &block)
|
8
|
-
if table.respond_to? sym
|
9
|
-
table.send(sym, *args, &block)
|
10
|
-
else
|
11
|
-
super
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class << self
|
16
|
-
def recursive_new(hash)
|
17
|
-
new.tap { |s|
|
18
|
-
hash.each_pair { |key, value|
|
19
|
-
s.send(
|
20
|
-
:"#{key}=",
|
21
|
-
value.is_a?(Hash) ? recursive_new(value) : value)
|
22
|
-
}
|
23
|
-
}
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'thread'
|
3
|
-
|
4
|
-
module CompTree
|
5
|
-
module Misc
|
6
|
-
def let
|
7
|
-
yield self
|
8
|
-
end
|
9
|
-
|
10
|
-
def singleton_class
|
11
|
-
class << self
|
12
|
-
self
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
module Gensym
|
17
|
-
@mutex = Mutex.new
|
18
|
-
@count = 0
|
19
|
-
|
20
|
-
def gensym(prefix = nil)
|
21
|
-
count = Gensym.module_eval {
|
22
|
-
@mutex.synchronize {
|
23
|
-
@count += 1
|
24
|
-
}
|
25
|
-
}
|
26
|
-
"#{prefix || :G}_#{count}".to_sym
|
27
|
-
end
|
28
|
-
end
|
29
|
-
include Gensym
|
30
|
-
|
31
|
-
def call_private(method, *args, &block)
|
32
|
-
instance_eval { send(method, *args, &block) }
|
33
|
-
end
|
34
|
-
|
35
|
-
def with_warnings(value = true)
|
36
|
-
previous = $VERBOSE
|
37
|
-
$VERBOSE = value
|
38
|
-
begin
|
39
|
-
yield
|
40
|
-
ensure
|
41
|
-
$VERBOSE = previous
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def no_warnings(&block)
|
46
|
-
with_warnings(false, &block)
|
47
|
-
end
|
48
|
-
|
49
|
-
def abort_on_exception(value = true)
|
50
|
-
previous = Thread.abort_on_exception
|
51
|
-
Thread.abort_on_exception = value
|
52
|
-
begin
|
53
|
-
yield
|
54
|
-
ensure
|
55
|
-
Thread.abort_on_exception = previous
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
extend self
|
60
|
-
end
|
61
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'ostruct'
|
3
|
-
require 'quix/builtin/kernel/tap'
|
4
|
-
|
5
|
-
module Quix
|
6
|
-
#
|
7
|
-
# An OpenStruct with the ability to define lazily-evaluated fields.
|
8
|
-
#
|
9
|
-
class LazyStruct < OpenStruct
|
10
|
-
#
|
11
|
-
# For mixing into an existing OpenStruct instance singleton class.
|
12
|
-
#
|
13
|
-
module Mixin
|
14
|
-
#
|
15
|
-
# &block is evaluated when this attribute is requested. The
|
16
|
-
# same result is returned for subsquent calls, until the field
|
17
|
-
# is assigned a different value.
|
18
|
-
#
|
19
|
-
def attribute(reader, &block)
|
20
|
-
singleton = (class << self ; self ; end)
|
21
|
-
singleton.instance_eval {
|
22
|
-
#
|
23
|
-
# Define a special reader method in the singleton class.
|
24
|
-
#
|
25
|
-
define_method(reader) {
|
26
|
-
block.call.tap { |value|
|
27
|
-
#
|
28
|
-
# The value has been computed. Replace this method with a
|
29
|
-
# one-liner giving the value.
|
30
|
-
#
|
31
|
-
singleton.instance_eval {
|
32
|
-
remove_method(reader)
|
33
|
-
define_method(reader) { value }
|
34
|
-
}
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
#
|
39
|
-
# Revert to the old OpenStruct behavior when the writer is called.
|
40
|
-
#
|
41
|
-
writer = "#{reader}=".to_sym
|
42
|
-
define_method(writer) { |value|
|
43
|
-
singleton.instance_eval {
|
44
|
-
remove_method(reader)
|
45
|
-
remove_method(writer)
|
46
|
-
}
|
47
|
-
method_missing(writer, value)
|
48
|
-
}
|
49
|
-
}
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
include Mixin
|
54
|
-
end
|
55
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'quix/builtin/kernel/tap'
|
3
|
-
|
4
|
-
module Quix
|
5
|
-
module String
|
6
|
-
def trim_left!
|
7
|
-
sub!(%r!\A\s+!, "")
|
8
|
-
end
|
9
|
-
|
10
|
-
def trim_right!
|
11
|
-
sub!(%r!\s+\Z!, "")
|
12
|
-
end
|
13
|
-
|
14
|
-
def trim!
|
15
|
-
result_left = trim_left!
|
16
|
-
result_right = trim_right!
|
17
|
-
result_left || result_right
|
18
|
-
end
|
19
|
-
|
20
|
-
def trim_left
|
21
|
-
clone.tap { |result|
|
22
|
-
result.trim_left!
|
23
|
-
}
|
24
|
-
end
|
25
|
-
|
26
|
-
def trim_right
|
27
|
-
clone.tap { |result|
|
28
|
-
result.trim_right!
|
29
|
-
}
|
30
|
-
end
|
31
|
-
|
32
|
-
def trim
|
33
|
-
clone.tap { |result|
|
34
|
-
result.trim!
|
35
|
-
}
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|