lazy_string 0.3.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt CHANGED
@@ -1,20 +1,19 @@
1
- Copyright (c) 2018 Aaron Beckerman
1
+ Copyright (c) 2024 Aaron Beckerman
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
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
- in all copies or substantial portions of the Software.
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
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 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,44 +1,28 @@
1
1
  LazyString
2
2
 
3
- LazyString is a Ruby class for computing strings only when necessary -- that
4
- is, when #to_str or #to_s is called. This is useful when computing the string
5
- is expensive, but the string is unlikely to be used: an error message passed as
6
- a method argument, for example.
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 might never be
5
+ used.
7
6
 
8
- Thanks to duck typing and Ruby's standard conversion protocols, you can pass
9
- an instance of LazyString to many methods that ask for a string.
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.
10
9
 
11
10
 
12
11
  Usage
13
12
 
14
- LazyString is packaged as a RubyGem. Once you've installed it and required the
15
- file, you can create a lazy string by passing a block to LazyString.new:
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:
16
16
 
17
17
  ls = LazyString.new { "answer = #{expensive_computation}" }
18
18
 
19
- The block (and therefore expensive_computation) will not be called immediately.
20
- But later, if #to_str or #to_s is called on the lazy string, the block will be
21
- called with no arguments in order to create the real string.
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.
22
23
 
23
- # String interpolation calls #to_s automatically.
24
+ # String interpolation sends to_s.
24
25
  s = "Lazy string computes this: #{ls}"
25
26
 
26
- Once the string is computed, it will be saved, so any future invocations of
27
- #to_str or #to_s will not perform the computation again.
28
-
29
-
30
- Compatibility
31
-
32
- This works on version 1.8.7 and later of Matz's Ruby Interpreter. (At the time
33
- of this writing, 2.2.3 is the current version.)
34
-
35
-
36
- Author
37
-
38
- This software was written by Aaron Beckerman.
39
-
40
-
41
- License
42
-
43
- This software is distributed under the MIT License (also known as the Expat
44
- 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/lazy_string.gemspec CHANGED
@@ -1,19 +1,14 @@
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 -- that is, when #to_str or #to_s is called. This is useful when computing the string is expensive but the string is unlikely to be used: an error message passed as a method 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}
1
+ Gem::Specification.new do |s|
2
+ s.name = "lazy_string"
3
+ s.version = "0.7.0"
4
+ s.authors = ["Aaron Beckerman"]
5
+ s.summary = "A class for computing strings only when necessary."
6
+ s.description = "This library provides LazyString, a class for computing" \
7
+ " strings only when necessary. This is useful when computing the string" \
8
+ " is expensive but the string might never be used."
9
+ s.licenses = ["MIT"]
10
+ s.files = ["LICENSE.txt", "README.txt", "lazy_string.gemspec",
11
+ "lib/lazy_string.rb", "test/lazy_string_test.rb"]
12
+ s.test_files = ["test/lazy_string_test.rb"]
13
+ s.required_ruby_version = ">= 1.8.7"
19
14
  end
data/lib/lazy_string.rb CHANGED
@@ -1,47 +1,46 @@
1
1
  ##
2
- # LazyString is a class for computing strings only when necessary -- that is,
3
- # when #to_str or #to_s is called. This is useful when computing the string is
4
- # expensive, but the string is unlikely to be used: an error message passed as
5
- # a method argument, for example.
6
- #
2
+ # A class for computing strings only when necessary.
3
+
7
4
  class LazyString
8
- ##
9
- # The version string.
10
- #
11
- VERSION = '0.3.0'
12
5
 
13
6
  ##
14
- # Creates a new lazy string. The block argument will be saved for later use
15
- # by #to_str. If no block argument is given, it will default to a block that
16
- # returns an empty string.
17
- #
18
- def initialize(&block)
19
- @block = block || lambda { '' }
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
20
14
  end
21
15
 
22
16
  ##
23
- # A synonym for #to_str.
24
- #
17
+ # Computes the string if necessary and returns it. It delegates to #to_str.
18
+
25
19
  def to_s
26
20
  to_str
27
21
  end
28
22
 
29
23
  ##
30
- # Returns the computed string. It will compute the string by calling (with no
31
- # arguments) the block passed to ::new. If the block's return value responds
32
- # to the \to_str message, \to_str will be called on it to create the string.
33
- # Otherwise, \to_s will be called on it. The computed string will be saved,
34
- # so subsequent calls of this method will not cause the block to be called
35
- # again.
36
- #
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
+
37
33
  def to_str
38
- @str ||= begin
39
- result = @block.call
40
- if result.respond_to?(:to_str)
34
+ if defined? @str
35
+ @str
36
+ else
37
+ result = @prc.call
38
+ @str = if result.respond_to? :to_str
41
39
  result.to_str
42
40
  else
43
41
  result.to_s
44
42
  end
45
43
  end
46
44
  end
45
+
47
46
  end
@@ -1,55 +1,162 @@
1
- require 'lazy_string'
1
+ # Sections that create local variables are in class definitions so that later
2
+ # sections cannot accidentally reference those local variables.
2
3
 
3
- Class == LazyString.class or fail
4
+ require "lazy_string"
4
5
 
5
- String == LazyString::VERSION.class or fail
6
+ # LazyString should be a class.
7
+ fail "" unless Class.equal? LazyString.class
6
8
 
7
- lambda do
8
- obj = Object.new
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.respond_to?(:to_str) or fail
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
- LazyString.new.respond_to?(:to_s) or fail
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
- '' == LazyString.new.to_str or fail
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
- lambda do
20
- obj = Object.new
21
- def obj.to_str; 'to_str' end
22
- def obj.to_s; 'to_s' end
23
- 'to_str' == LazyString.new { obj }.to_str or fail
24
- end.call
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
- lambda do
27
- obj = Object.new
28
- def obj.to_s; 'to_s' end
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
- '42' == LazyString.new { 2 * 21 }.to_s or fail
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
- lambda do
36
- arr = []
37
- ls = LazyString.new { arr << nil; 'foo' }
38
- ls.to_str
39
- 'foo' == ls.to_str or fail
40
- 1 == arr.length or fail
41
- end.call
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
- lambda do
44
- ex = StandardError.new
45
- ls = LazyString.new { raise(ex) }
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
- ex.equal?($!) or fail
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.call
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
- puts 'Test finished.'
161
+ # If this message doesn't get written, there was a problem.
162
+ puts "Test finished: #{__FILE__}"
metadata CHANGED
@@ -1,52 +1,73 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: lazy_string
3
- version: !ruby/object:Gem::Version
4
- version: 0.3.0
3
+ version: !ruby/object:Gem::Version
4
+ hash: 3
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 7
9
+ - 0
10
+ version: 0.7.0
5
11
  platform: ruby
6
- authors:
12
+ authors:
7
13
  - Aaron Beckerman
8
14
  autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
- date: 2018-05-28 00:00:00.000000000 Z
17
+
18
+ date: 2024-03-11 00:00:00 -07:00
19
+ default_executable:
12
20
  dependencies: []
13
- description: 'This library provides LazyString, a class for computing strings only
14
- when necessary -- that is, when #to_str or #to_s is called. This is useful when
15
- computing the string is expensive but the string is unlikely to be used: an error
16
- message passed as a method argument, for example.'
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.
17
23
  email:
18
24
  executables: []
25
+
19
26
  extensions: []
27
+
20
28
  extra_rdoc_files: []
21
- files:
29
+
30
+ files:
22
31
  - LICENSE.txt
23
32
  - README.txt
24
33
  - lazy_string.gemspec
25
34
  - lib/lazy_string.rb
26
35
  - test/lazy_string_test.rb
36
+ has_rdoc: true
27
37
  homepage:
28
- licenses:
38
+ licenses:
29
39
  - MIT
30
- metadata: {}
31
40
  post_install_message:
32
41
  rdoc_options: []
33
- require_paths:
42
+
43
+ require_paths:
34
44
  - lib
35
- required_ruby_version: !ruby/object:Gem::Requirement
36
- requirements:
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
37
48
  - - ">="
38
- - !ruby/object:Gem::Version
49
+ - !ruby/object:Gem::Version
50
+ hash: 57
51
+ segments:
52
+ - 1
53
+ - 8
54
+ - 7
39
55
  version: 1.8.7
40
- required_rubygems_version: !ruby/object:Gem::Requirement
41
- requirements:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
42
59
  - - ">="
43
- - !ruby/object:Gem::Version
44
- version: '0'
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
45
65
  requirements: []
66
+
46
67
  rubyforge_project:
47
- rubygems_version: 2.7.6
68
+ rubygems_version: 1.6.2
48
69
  signing_key:
49
- specification_version: 4
50
- summary: A Ruby library for lazily computing strings.
51
- test_files:
70
+ specification_version: 3
71
+ summary: A class for computing strings only when necessary.
72
+ test_files:
52
73
  - test/lazy_string_test.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA256:
3
- metadata.gz: d7ef828d0d6e270b3c763849c5503bef8434ac156e487d517b528ec64d5c4ab4
4
- data.tar.gz: 4cbba8428b89845019b048a1bbb700f2dcaeda71c853f849ef9462914e364293
5
- SHA512:
6
- metadata.gz: ee16dc18e4c5035ee131cfa0c92e3bc1c5f6fcd1f7cacc5c9c3a8632c20fecc1683781c2498340e2a322c8c077eea2beea90238ac0bb3839a025c96fb136730c
7
- data.tar.gz: '048e4f0fea648cb3655db2042b174ddc13e81d3f9933d166542e3bf61c15e1e005cf47a1b1594fb2833c88f2c1adad4c0b445a6e077a1d8ac62d95cdb75fc1f5'