ytry 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|