lazy_string 0.4.0 → 0.8.0
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/LICENSE.txt +16 -17
- data/README.txt +14 -29
- data/lib/lazy_string.rb +26 -26
- data/test/lazy_string_test.rb +145 -38
- metadata +52 -30
- checksums.yaml +0 -7
- data/lazy_string.gemspec +0 -19
data/LICENSE.txt
CHANGED
@@ -1,20 +1,19 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2012-2025 Aaron Beckerman
|
2
2
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
the following conditions:
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
8
|
+
so, subject to the following conditions:
|
10
9
|
|
11
|
-
The above copyright notice and this permission notice shall be included
|
12
|
-
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
13
12
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
SOFTWARE
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.txt
CHANGED
@@ -1,43 +1,28 @@
|
|
1
1
|
LazyString
|
2
2
|
|
3
3
|
LazyString is a Ruby class for computing strings only when necessary. This is
|
4
|
-
useful when computing the string is expensive but the string
|
5
|
-
used
|
4
|
+
useful when computing the string is expensive but the string might never be
|
5
|
+
used.
|
6
6
|
|
7
|
-
Thanks to duck typing and
|
8
|
-
|
7
|
+
Thanks to Ruby's duck typing and conversion protocols, you can often use an
|
8
|
+
instance of LazyString where you previously used an instance of String.
|
9
9
|
|
10
10
|
|
11
11
|
Usage
|
12
12
|
|
13
|
-
LazyString is packaged as a
|
14
|
-
|
13
|
+
LazyString is packaged as a gem. Once you've installed it and loaded the file,
|
14
|
+
you can create a lazy string by sending new to LazyString with a block. The
|
15
|
+
block should return an object that converts to a string:
|
15
16
|
|
16
17
|
ls = LazyString.new { "answer = #{expensive_computation}" }
|
17
18
|
|
18
|
-
The block (and therefore expensive_computation) will not be
|
19
|
-
But later, if
|
20
|
-
called with no arguments
|
19
|
+
The block (and therefore expensive_computation) will not be run immediately.
|
20
|
+
But later, if to_str or to_s is sent to the lazy string, the saved proc
|
21
|
+
representing your block will be called with no arguments and the returned
|
22
|
+
object converted to create the real string.
|
21
23
|
|
22
|
-
# String interpolation
|
24
|
+
# String interpolation sends to_s.
|
23
25
|
s = "Lazy string computes this: #{ls}"
|
24
26
|
|
25
|
-
Once the string is computed, it will be saved, so
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
Compatibility
|
30
|
-
|
31
|
-
This works on version 1.8.7 and later of Matz's Ruby Interpreter. (At the time
|
32
|
-
of this writing, 2.2.3 is the current version.)
|
33
|
-
|
34
|
-
|
35
|
-
Author
|
36
|
-
|
37
|
-
This software was written by Aaron Beckerman.
|
38
|
-
|
39
|
-
|
40
|
-
License
|
41
|
-
|
42
|
-
This software is distributed under the MIT License (also known as the Expat
|
43
|
-
License). See the LICENSE.txt file for details.
|
27
|
+
Once the string is computed, it will be saved, so sending to_str or to_s again
|
28
|
+
will not cause the computation to be performed again.
|
data/lib/lazy_string.rb
CHANGED
@@ -1,46 +1,46 @@
|
|
1
1
|
##
|
2
|
-
#
|
3
|
-
|
4
|
-
# be used: an error message passed as an argument, for example.
|
5
|
-
#
|
2
|
+
# A class for computing strings only when necessary.
|
3
|
+
|
6
4
|
class LazyString
|
7
|
-
##
|
8
|
-
# The version string.
|
9
|
-
#
|
10
|
-
VERSION = '0.4.0'
|
11
5
|
|
12
6
|
##
|
13
|
-
# Creates a new lazy string.
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
def initialize
|
18
|
-
@
|
7
|
+
# Creates a new lazy string. It saves the block as a proc for later use by
|
8
|
+
# #to_str. If no block is given, it saves a proc that returns an empty
|
9
|
+
# string.
|
10
|
+
|
11
|
+
def initialize &prc
|
12
|
+
@prc = prc || ::Proc.new { "" }
|
13
|
+
nil
|
19
14
|
end
|
20
15
|
|
21
16
|
##
|
22
|
-
#
|
23
|
-
|
17
|
+
# Computes the string if necessary and returns it. It delegates to #to_str.
|
18
|
+
|
24
19
|
def to_s
|
25
20
|
to_str
|
26
21
|
end
|
27
22
|
|
28
23
|
##
|
29
|
-
#
|
30
|
-
# arguments
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
24
|
+
# Computes the string if necessary and returns it. It computes the string by
|
25
|
+
# calling, with no arguments, the saved proc representing the block passed to
|
26
|
+
# ::new. If an object is returned, this method converts it to a string and
|
27
|
+
# returns the result. It converts the object to a string by sending \to_str
|
28
|
+
# to the object if it responds to that message and \to_s otherwise. It saves
|
29
|
+
# the computed string, so subsequent invocations of this method will not
|
30
|
+
# recompute the string. If an exception is raised, this method immediately
|
31
|
+
# raises that exception and does not save any result.
|
32
|
+
|
36
33
|
def to_str
|
37
|
-
@str
|
38
|
-
|
39
|
-
|
34
|
+
if defined? @str
|
35
|
+
@str
|
36
|
+
else
|
37
|
+
result = @prc.call
|
38
|
+
@str = if result.respond_to? :to_str
|
40
39
|
result.to_str
|
41
40
|
else
|
42
41
|
result.to_s
|
43
42
|
end
|
44
43
|
end
|
45
44
|
end
|
45
|
+
|
46
46
|
end
|
data/test/lazy_string_test.rb
CHANGED
@@ -1,55 +1,162 @@
|
|
1
|
-
|
1
|
+
# Sections that create local variables are in class definitions so that later
|
2
|
+
# sections cannot accidentally reference those local variables.
|
2
3
|
|
3
|
-
|
4
|
+
require "lazy_string"
|
4
5
|
|
5
|
-
|
6
|
+
# LazyString should be a class.
|
7
|
+
fail "" unless Class.equal? LazyString.class
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
LazyString.new { obj.freeze }
|
10
|
-
!obj.frozen? or fail
|
11
|
-
end.call
|
9
|
+
# LazyString.new should return an instance of LazyString.
|
10
|
+
fail "" unless LazyString.equal? LazyString.new.class
|
12
11
|
|
13
|
-
LazyString.new
|
12
|
+
# LazyString.new should raise an exception if any non-block arguments are sent.
|
13
|
+
begin
|
14
|
+
LazyString.new nil
|
15
|
+
rescue ArgumentError
|
16
|
+
else
|
17
|
+
fail ""
|
18
|
+
end
|
19
|
+
begin
|
20
|
+
LazyString.new(nil) {}
|
21
|
+
rescue ArgumentError
|
22
|
+
else
|
23
|
+
fail ""
|
24
|
+
end
|
14
25
|
|
15
|
-
|
26
|
+
# The block should not be called when creating a lazy string.
|
27
|
+
class ::Object
|
28
|
+
calls = 0
|
29
|
+
LazyString.new { calls += 1 }
|
30
|
+
fail "" unless 0 == calls
|
31
|
+
end
|
16
32
|
|
17
|
-
|
33
|
+
# An instance of LazyString should say it responds to to_str and to_s.
|
34
|
+
fail "" unless LazyString.new.respond_to? :to_str
|
35
|
+
fail "" unless LazyString.new.respond_to? :to_s
|
18
36
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
37
|
+
# LazyString#to_s should delegate to #to_str.
|
38
|
+
class ::Object
|
39
|
+
ls = LazyString.new
|
40
|
+
ls.instance_variable_set :@_test_to_str, test_to_str = Object.new
|
41
|
+
def ls.to_str
|
42
|
+
@_test_to_str
|
43
|
+
end
|
44
|
+
fail "" unless test_to_str.equal? ls.to_s
|
45
|
+
end
|
25
46
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
!obj.respond_to?(:to_str) or fail
|
30
|
-
'to_s' == LazyString.new { obj }.to_str or fail
|
31
|
-
end.call
|
47
|
+
# LazyString#to_str should return an empty string if the lazy string was made
|
48
|
+
# without a block.
|
49
|
+
fail "" unless "" == LazyString.new.to_str
|
32
50
|
|
33
|
-
|
51
|
+
# LazyString#to_str should convert the object returned by the saved proc to a
|
52
|
+
# string and return the result. If the object responds to to_str, the
|
53
|
+
# conversion should be done by sending that message.
|
54
|
+
class ::Object
|
55
|
+
block_result = Object.new
|
56
|
+
block_result.instance_variable_set :@_test_to_str, test_to_str = Object.new
|
57
|
+
def block_result.to_str
|
58
|
+
@_test_to_str
|
59
|
+
end
|
60
|
+
def block_result.to_s
|
61
|
+
"to_s"
|
62
|
+
end
|
63
|
+
fail "" unless test_to_str.equal? LazyString.new { block_result }.to_str
|
64
|
+
end
|
34
65
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
66
|
+
# LazyString#to_str should convert the object returned by the saved proc to a
|
67
|
+
# string and return the result. If the object does not respond to to_str, the
|
68
|
+
# conversion should be done by sending to_s.
|
69
|
+
class ::Object
|
70
|
+
block_result = Object.new
|
71
|
+
block_result.instance_variable_set :@_test_to_s, test_to_s = Object.new
|
72
|
+
def block_result.to_s
|
73
|
+
@_test_to_s
|
74
|
+
end
|
75
|
+
fail "" unless test_to_s.equal? LazyString.new { block_result }.to_str
|
76
|
+
end
|
42
77
|
|
43
|
-
|
44
|
-
|
45
|
-
|
78
|
+
# After LazyString#to_str calls the saved proc as part of a successful string
|
79
|
+
# conversion, it should not call it again in subsequent invocations but return
|
80
|
+
# the same object.
|
81
|
+
class ::Object
|
82
|
+
calls = 0
|
83
|
+
ls = LazyString.new do
|
84
|
+
calls += 1
|
85
|
+
"string"
|
86
|
+
end
|
87
|
+
fail "" unless ls.to_str.equal? ls.to_str
|
88
|
+
fail "" unless 1 == calls
|
89
|
+
end
|
90
|
+
|
91
|
+
# LazyString#to_str should convert the object returned by the saved proc to a
|
92
|
+
# string and save the result. If that was successful, it should not convert the
|
93
|
+
# object again in subsequent invocations but return the same object.
|
94
|
+
class ::Object
|
95
|
+
block_result = Object.new
|
96
|
+
block_result.instance_variable_set :@_test_calls, 0
|
97
|
+
def block_result.to_s
|
98
|
+
@_test_calls += 1
|
99
|
+
"string"
|
100
|
+
end
|
101
|
+
ls = LazyString.new { block_result }
|
102
|
+
fail "" unless ls.to_str.equal? ls.to_str
|
103
|
+
fail "" unless 1 == block_result.instance_variable_get(:@_test_calls)
|
104
|
+
end
|
105
|
+
|
106
|
+
# LazyString#to_str should not save any result if converting to a string raised
|
107
|
+
# an exception.
|
108
|
+
class ::Object
|
109
|
+
block_result = Object.new
|
110
|
+
def block_result.to_s
|
111
|
+
raise RuntimeError
|
112
|
+
end
|
113
|
+
calls = 0
|
114
|
+
ls = LazyString.new do
|
115
|
+
calls += 1
|
116
|
+
block_result
|
117
|
+
end
|
118
|
+
ls.to_str rescue nil
|
119
|
+
ls.to_str rescue nil
|
120
|
+
fail "" unless 2 == calls
|
121
|
+
end
|
122
|
+
|
123
|
+
# LazyString#to_str and #to_s should propagate exceptions.
|
124
|
+
class ::Object
|
125
|
+
e = StandardError.new
|
126
|
+
ls = LazyString.new { ::Kernel.raise e }
|
46
127
|
begin
|
47
128
|
ls.to_str
|
48
129
|
rescue
|
49
|
-
|
130
|
+
fail "" unless e.equal? $!
|
131
|
+
else
|
132
|
+
fail ""
|
133
|
+
end
|
134
|
+
begin
|
135
|
+
ls.to_s
|
136
|
+
rescue
|
137
|
+
fail "" unless e.equal? $!
|
50
138
|
else
|
51
|
-
fail
|
139
|
+
fail ""
|
52
140
|
end
|
53
|
-
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# LazyString#to_str should raise an exception if any non-block arguments are
|
144
|
+
# sent.
|
145
|
+
begin
|
146
|
+
LazyString.new.to_str nil
|
147
|
+
rescue ArgumentError
|
148
|
+
else
|
149
|
+
fail ""
|
150
|
+
end
|
151
|
+
|
152
|
+
# LazyString#to_s should raise an exception if any non-block arguments are
|
153
|
+
# sent.
|
154
|
+
begin
|
155
|
+
LazyString.new.to_s nil
|
156
|
+
rescue ArgumentError
|
157
|
+
else
|
158
|
+
fail ""
|
159
|
+
end
|
54
160
|
|
55
|
-
|
161
|
+
# If this message doesn't get written, there was a problem.
|
162
|
+
puts "Test finished: #{__FILE__}"
|
metadata
CHANGED
@@ -1,50 +1,72 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: lazy_string
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 63
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 8
|
9
|
+
- 0
|
10
|
+
version: 0.8.0
|
5
11
|
platform: ruby
|
6
|
-
authors:
|
12
|
+
authors:
|
7
13
|
- Aaron Beckerman
|
8
|
-
autorequire:
|
14
|
+
autorequire:
|
9
15
|
bindir: bin
|
10
16
|
cert_chain: []
|
11
|
-
|
17
|
+
|
18
|
+
date: 2025-05-16 00:00:00 -07:00
|
19
|
+
default_executable:
|
12
20
|
dependencies: []
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
email:
|
21
|
+
|
22
|
+
description: This library provides LazyString, a class for computing strings only when necessary. This is useful when computing the string is expensive but the string might never be used.
|
23
|
+
email:
|
17
24
|
executables: []
|
25
|
+
|
18
26
|
extensions: []
|
27
|
+
|
19
28
|
extra_rdoc_files: []
|
20
|
-
|
29
|
+
|
30
|
+
files:
|
21
31
|
- LICENSE.txt
|
22
32
|
- README.txt
|
23
|
-
- lazy_string.gemspec
|
24
33
|
- lib/lazy_string.rb
|
25
34
|
- test/lazy_string_test.rb
|
26
|
-
|
27
|
-
|
35
|
+
has_rdoc: true
|
36
|
+
homepage:
|
37
|
+
licenses:
|
28
38
|
- MIT
|
29
|
-
|
30
|
-
post_install_message:
|
39
|
+
post_install_message:
|
31
40
|
rdoc_options: []
|
32
|
-
|
41
|
+
|
42
|
+
require_paths:
|
33
43
|
- lib
|
34
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
-
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
36
47
|
- - ">="
|
37
|
-
- !ruby/object:Gem::Version
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
hash: 57
|
50
|
+
segments:
|
51
|
+
- 1
|
52
|
+
- 8
|
53
|
+
- 7
|
38
54
|
version: 1.8.7
|
39
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
40
|
-
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
41
58
|
- - ">="
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
44
64
|
requirements: []
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
65
|
+
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.6.2
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: A class for computing strings only when necessary.
|
71
|
+
test_files: []
|
72
|
+
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA256:
|
3
|
-
metadata.gz: b95d72633b9419e5306c154c7adda01b3ea723d39d4bf3ee58b41111371bc128
|
4
|
-
data.tar.gz: 2fde23cece3bb04dec3570ab777fd8cf6528024dc1ead33ac2d6dae9d8fde974
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 5ea1f4d2c963a844fe677fdf59bf866b8ce33a323997357f243301640f79fb73dc15f45e7ff456db8274120de018a96d7aa36a5d782186299855ba9123e60699
|
7
|
-
data.tar.gz: 375eb324a2af06e24b661eabce5e674420eb476f33a8165b457123dacb86fbf67148a391d8f24f4839e480b517f8d4be11899e8944283c570fc71e3e8da0de6d
|
data/lazy_string.gemspec
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require "lazy_string"
|
5
|
-
|
6
|
-
Gem::Specification.new do |gem|
|
7
|
-
gem.name = 'lazy_string'
|
8
|
-
gem.version = LazyString::VERSION
|
9
|
-
gem.authors = ['Aaron Beckerman']
|
10
|
-
gem.description = %q{This library provides LazyString, a class for computing strings only when necessary. This is useful when computing the string is expensive but the string is unlikely to be used: an error message passed as an argument, for example.}
|
11
|
-
gem.summary = %q{A Ruby library for lazily computing strings.}
|
12
|
-
gem.license = 'MIT'
|
13
|
-
gem.required_ruby_version = '>= 1.8.7'
|
14
|
-
|
15
|
-
gem.files = %w{LICENSE.txt README.txt lazy_string.gemspec lib/lazy_string.rb test/lazy_string_test.rb}
|
16
|
-
gem.executables = %w{}
|
17
|
-
gem.test_files = %w{test/lazy_string_test.rb}
|
18
|
-
gem.require_paths = %w{lib}
|
19
|
-
end
|