ytry 1.0.0 → 2.0.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.
- checksums.yaml +4 -4
- data/README.md +38 -0
- data/lib/ytry.rb +57 -13
- data/lib/ytry/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6575212d45e0fb109f44a9da7cba53ad23693ee7
|
4
|
+
data.tar.gz: 7054016b7dfb31dcff32878f13ae6ef30e0e9b1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e1deff71f7aad49b3b29832fca250bcfb5b05778cb6c05111dd5dd13289c4b23857bc79b8901c420bc023a661973d0ca30b9a791d8c5b85df1d5d7b4be5037d
|
7
|
+
data.tar.gz: b519003d0a36612a5e70610b4a5369a7c1f92c75359b56739980ad0e5ff381fcce3aaafd139f118c8d869bce3e5fc36868dc58d840a15025eef56d85577d2290
|
data/README.md
CHANGED
@@ -82,6 +82,44 @@ Using Try instead of rescue blocks can make your software both clearer and safer
|
|
82
82
|
- privileges method chaining thus reducing the need for auxiliary variables to store intermediate results in a computation
|
83
83
|
- encourages programming towards immutability, where the data is transformed rather than mutated in place.
|
84
84
|
|
85
|
+
## Advanced Usage
|
86
|
+
### #reduce
|
87
|
+
Given a Try instance `try`, a value `c` and a lambda `f`,
|
88
|
+
```
|
89
|
+
try.reduce(c, &f)
|
90
|
+
```
|
91
|
+
returns `f.(c, try)` if `try` is a `Success` AND the evaluation of the lambda `f` did not throw any error, it returns `c` otherwise.
|
92
|
+
|
93
|
+
This is a shortcut to
|
94
|
+
```
|
95
|
+
try.map{|v| f.(c,v)}.get_or_else {c}
|
96
|
+
```
|
97
|
+
|
98
|
+
|
99
|
+
### #flatten
|
100
|
+
When dealing with nested `Try`s we can use flatten to reduce the level of nesting
|
101
|
+
```
|
102
|
+
success = Try{:ok}
|
103
|
+
failure = Try{fail}
|
104
|
+
Try{success}.flatten # Success(:ok)
|
105
|
+
Try{failure}.flatten # Failure(RuntimeError)
|
106
|
+
```
|
107
|
+
|
108
|
+
### Interoperability with Array-like obects
|
109
|
+
Because of it's ary-like nature, instances of `Try` play well with Array instances. In particular, flattening an Array of `Try`s is equivalent to filtering out the `Failures` from the array and then calling #get on the Success instances
|
110
|
+
```
|
111
|
+
(1..4).map{|v| Try{v}.select(&:odd?)}
|
112
|
+
.flatten # [1, 3]
|
113
|
+
```
|
114
|
+
Behind the scenes `Array#flatten` is iterating over the collection and concatenating the ary-representation of each element.
|
115
|
+
Now `Failure#to_ary` returns `[]`, while `Success#to_ary` returns `[v]` - where `v` is the value wrapped by Success - and that does the trick.
|
116
|
+
|
117
|
+
We can squeeze the code listed above even more with `Array#flat_map`
|
118
|
+
```
|
119
|
+
(1..4).flat_map{|v| Try{v}.select(&:odd?)} # [1, 3]
|
120
|
+
```
|
121
|
+
Again, there is no magic behind this behaviour, we are just exploiting Ruby's duck typing.
|
122
|
+
|
85
123
|
## Development
|
86
124
|
|
87
125
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/ytry.rb
CHANGED
@@ -24,14 +24,30 @@ module Ytry
|
|
24
24
|
end
|
25
25
|
def each
|
26
26
|
return enum_for(__method__) unless block_given?
|
27
|
-
yield self.get unless empty?
|
27
|
+
Try { yield self.get unless empty? }
|
28
28
|
return self
|
29
29
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
alias_method :on_success, :each
|
31
|
+
def on_failure
|
32
|
+
return enum_for(__method__) unless block_given?
|
33
|
+
return self
|
34
|
+
end
|
35
|
+
def map &block
|
36
|
+
block or return enum_for(__method__)
|
37
|
+
self.empty? ? self : Try{block.call(self.get)}
|
38
|
+
end
|
39
|
+
alias_method :collect, :map
|
40
|
+
def select &block
|
41
|
+
block or return enum_for(__method__)
|
42
|
+
return self if empty?
|
43
|
+
predicate = Try{ block.call(self.get) }
|
44
|
+
return predicate if predicate.empty?
|
45
|
+
predicate.get ? self : Try.ary_to_type([])
|
46
|
+
end
|
47
|
+
def reject &block
|
48
|
+
if block_given? then select {|v| ! block.call(v)}
|
49
|
+
else enum_for(__method__)
|
50
|
+
end
|
35
51
|
end
|
36
52
|
def flat_map &block
|
37
53
|
block or return enum_for(method)
|
@@ -40,12 +56,19 @@ module Ytry
|
|
40
56
|
return wrapped_result if (!wrapped_result.empty? && !wrapped_result.get.respond_to?(:to_ary))
|
41
57
|
Try.ary_to_type(wrapped_result.flatten)
|
42
58
|
end
|
43
|
-
|
44
|
-
|
59
|
+
alias_method :collect_concat, :flat_map
|
60
|
+
def grep pattern
|
61
|
+
return self if self.empty?
|
62
|
+
match = Try {
|
63
|
+
(pattern === self.get) ? self.get : (raise RuntimeError.new("Element not found"))
|
64
|
+
}
|
65
|
+
block_given? ? match.map{|v| yield v} : match
|
45
66
|
end
|
46
|
-
def flatten
|
47
|
-
|
48
|
-
|
67
|
+
def flatten level = 1
|
68
|
+
level.times.reduce(self) { |current, _|
|
69
|
+
break(current) if current.empty?
|
70
|
+
Try.ary_to_type current.get
|
71
|
+
}
|
49
72
|
end
|
50
73
|
def zip *others
|
51
74
|
Try.zip(self, *others)
|
@@ -55,8 +78,12 @@ module Ytry
|
|
55
78
|
end
|
56
79
|
def or_else
|
57
80
|
return self unless empty?
|
58
|
-
|
59
|
-
|
81
|
+
candidate = Try{ yield }
|
82
|
+
if (!candidate.empty? && !candidate.get.is_a?(Try))
|
83
|
+
raise(Try.invalid_argument('Block should evaluate to an instance of Try', candidate.get))
|
84
|
+
else
|
85
|
+
candidate.flatten
|
86
|
+
end
|
60
87
|
end
|
61
88
|
def get_or_else
|
62
89
|
raise ArgumentError, 'missing block' unless block_given?
|
@@ -88,6 +115,10 @@ module Ytry
|
|
88
115
|
raise ArgumentError, 'missing block' unless block_given?
|
89
116
|
self
|
90
117
|
end
|
118
|
+
def recover_with &block
|
119
|
+
raise ArgumentError, 'missing block' unless block_given?
|
120
|
+
self
|
121
|
+
end
|
91
122
|
end
|
92
123
|
class Failure
|
93
124
|
include Try
|
@@ -105,10 +136,23 @@ module Ytry
|
|
105
136
|
def === other
|
106
137
|
other.is_a?(Failure) && self.error === other.error
|
107
138
|
end
|
139
|
+
def on_failure
|
140
|
+
return enum_for(__method__) unless block_given?
|
141
|
+
Try { yield @error }
|
142
|
+
return self
|
143
|
+
end
|
108
144
|
def recover &block
|
109
145
|
raise ArgumentError, 'missing block' unless block_given?
|
110
146
|
candidate = Success.new(@error).map &block
|
111
147
|
(!candidate.empty? && candidate.get.nil?) ? self : candidate
|
112
148
|
end
|
149
|
+
def recover_with &block
|
150
|
+
candidate = self.recover(&block)
|
151
|
+
if (!candidate.empty? && !candidate.get.is_a?(Try))
|
152
|
+
raise(Try.invalid_argument('Block should evaluate to an instance of Try', candidate.get))
|
153
|
+
else
|
154
|
+
candidate.flatten
|
155
|
+
end
|
156
|
+
end
|
113
157
|
end
|
114
158
|
end
|
data/lib/ytry/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ytry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- lorenzo.barasti
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|